summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/codemods/rename_pyqt.py98
1 files changed, 53 insertions, 45 deletions
diff --git a/scripts/codemods/rename_pyqt.py b/scripts/codemods/rename_pyqt.py
index b27cbd00b..306203c82 100644
--- a/scripts/codemods/rename_pyqt.py
+++ b/scripts/codemods/rename_pyqt.py
@@ -8,7 +8,6 @@
"""libCST codemod to rename imports and references to them."""
import argparse
-from fnmatch import fnmatch
from typing import Callable, Optional, Sequence, Set, Tuple, Union
import libcst as cst
@@ -18,6 +17,21 @@ from libcst.helpers import get_full_name_for_node
from libcst.metadata import QualifiedNameProvider
+def fnmatch(name, pat):
+ ret = False
+ if pat == "*" and name:
+ ret = True
+ elif not pat.endswith(".*"):
+ ret = name == pat
+ elif "." not in name:
+ ret = False
+ else:
+ remaining_name, _, _ = name.rpartition(".")
+ remaining_pat, _, _ = pat.rpartition(".")
+ ret = remaining_name == remaining_pat
+ return ret
+
+
def leave_import_decorator(
method: Callable[..., Union[cst.Import, cst.ImportFrom]]
) -> Callable[..., Union[cst.Import, cst.ImportFrom]]:
@@ -131,10 +145,12 @@ class RenameCommand(VisitorBasedCodemodCommand):
# Might, be in use elsewhere in the code, so schedule a potential removal, and add another alias.
new_names.append(import_alias)
self.scheduled_removals.add(original_node)
+ print(f"leave_Import {import_alias_full_name=} -> {self.gen_replacement_module(import_alias_full_name)=} {self.old_name=} {import_alias=} {updated_node=} {import_alias=}")
+ replacement_name = self.gen_replacement_module(import_alias_full_name)
new_names.append(
cst.ImportAlias(
name=cst.Name(
- value=self.gen_replacement_module(import_alias_full_name)
+ value=replacement_name,
)
)
)
@@ -196,7 +212,7 @@ class RenameCommand(VisitorBasedCodemodCommand):
imported_module_name
)
replacement_obj = self.gen_replacement(alias_name)
- if not replacement_obj:
+ if not replacement_obj or replacement_obj == "*":
# The user has requested an `import` statement rather than an `from ... import`.
# This will be taken care of in `leave_Module`, in the meantime, schedule for potential removal.
new_names.append(import_alias)
@@ -208,12 +224,11 @@ class RenameCommand(VisitorBasedCodemodCommand):
] = self.gen_name_or_attr_node(replacement_obj)
# Rename on the spot only if this is the only imported name under the module.
if len(names) == 1:
- print(f"just one {new_import_alias_name}")
- self.bypass_import = True
- return updated_node.with_changes(
+ updated_node = updated_node.with_changes(
module=cst.parse_expression(replacement_module),
- names=(cst.ImportAlias(name=new_import_alias_name),),
)
+ self.scheduled_removals.add(updated_node)
+ new_names.append(import_alias)
# Or if the module name is to stay the same.
elif replacement_module == imported_module_name:
self.bypass_import = True
@@ -226,6 +241,8 @@ class RenameCommand(VisitorBasedCodemodCommand):
self.scheduled_removals.add(original_node)
new_names.append(import_alias)
+ if not new_names:
+ return updated_node
return updated_node.with_changes(names=new_names)
return updated_node
@@ -234,7 +251,7 @@ class RenameCommand(VisitorBasedCodemodCommand):
if isinstance(old_name, str):
return any(fnmatch(qn.name, old_name) for qn in qualified_names)
else:
- return any(fnmatch(qn == old_name) for qn in qualified_names)
+ return any(fnmatch(qn, old_name) for qn in qualified_names)
def leave_Name(
self, original_node: cst.Name, updated_node: cst.Name
@@ -246,28 +263,21 @@ class RenameCommand(VisitorBasedCodemodCommand):
inside_import_statement: bool = not self.get_metadata(
QualifiedNameProvider, original_node, set()
)
- #qns = self.get_metadata(
- # QualifiedNameProvider, original_node, set()
- #)
- #print(original_node)
- #print(f"{full_name_for_node} vs {self.old_name} and {qns}")
if self.has_name_wildcard(original_node, self.old_name) or (
inside_import_statement and full_replacement_name == self.new_name
- ) or (
- fnmatch(self.old_name, full_name_for_node)
):
if not full_replacement_name:
- full_replacement_name = self.new_mod_or_obj
+ full_replacement_name = self.new_name
if not inside_import_statement:
self.scheduled_removals.add(original_node)
if full_replacement_name.endswith('.*'):
full_replacement_name, _, _ = full_replacement_name.rpartition('.')
- full_replacement_name = ".".join((full_replacement_name, full_name_for_node))
- #print(f'yes a {full_replacement_name} from {self.new_mod_or_obj}')
+ _, _, original_attr = full_name_for_node.rpartition(".")
+ full_replacement_name = ".".join((full_replacement_name, original_attr))
+ elif full_replacement_name == '*':
+ _, _, original_attr = full_name_for_node.rpartition(".")
+ full_replacement_name = original_attr
return self.gen_name_or_attr_node(full_replacement_name)
- else:
- #print('no')
- pass
return updated_node
@@ -290,20 +300,19 @@ class RenameCommand(VisitorBasedCodemodCommand):
new_value, new_attr = self.new_module, self.new_mod_or_obj
if not inside_import_statement:
self.scheduled_removals.add(original_node.value)
- print(f"{full_replacement_name} vs {self.new_name}")
- print(f"{new_value} and {new_attr}")
- print(f"old {self.old_name} {original_node} {original_node.value}")
- qualified_names = self.get_metadata(QualifiedNameProvider, original_node, set())
- print(f"qns {qualified_names}")
if full_replacement_name == self.new_name:
return updated_node.with_changes(
value=cst.parse_expression(new_value),
attr=cst.Name(value=new_attr.rstrip(".")),
)
- if new_attr.endswith('.*'):
+ if new_attr and new_attr.endswith('.*'):
new_attr, _, _ = new_attr.rpartition('.')
- new_attr = ".".join((new_attr, full_name_for_node))
+ _, _, original_attr = full_name_for_node.rpartition(".")
+ new_attr = ".".join((new_attr, original_attr))
+ elif not new_attr or new_attr and new_attr == '*':
+ _, _, original_attr = full_name_for_node.rpartition(".")
+ new_attr = ".".join((new_value, original_attr))
return self.gen_name_or_attr_node(new_attr)
return updated_node
@@ -337,27 +346,27 @@ class RenameCommand(VisitorBasedCodemodCommand):
module_as_name[0] + ".", module_as_name[1] + ".", 1
)
- if False and self.old_mod_or_obj == "*":
- print(f"wildcard to {original_name}")
- #return original_name # QIcon
- #return self.new_mod_or_obj # QtGui.*
- return self.new_name
- elif original_name == self.old_mod_or_obj:
- #print(f"orig = old {self.new_mod_or_obj}")
- return self.new_mod_or_obj
- elif original_name == ".".join([self.old_module, self.old_mod_or_obj]):
- #print(f"orig = full.old {self.old_module}.{self.new_mod_or_obj}")
- return self.new_name
+ if fnmatch(original_name, self.old_mod_or_obj):
+ new = self.new_mod_or_obj
+ elif fnmatch(original_name, ".".join([self.old_module,
+ self.old_mod_or_obj])):
+ new = self.new_name
elif original_name.endswith("." + self.old_mod_or_obj):
- #print(f"orig.endswith(old) {self.new_mod_or_obj}")
- return self.new_mod_or_obj
+ new = self.new_mod_or_obj
else:
new = self.gen_replacement_module(original_name)
- #print(f"{original_name} -> {new}")
- return new
+ if new.endswith('.*'):
+ new, _, _ = new.rpartition('.')
+ _, _, original_attr = original_name.rpartition(".")
+ new = ".".join((new, original_attr))
+ return new
def gen_replacement_module(self, original_module: str) -> str:
- return self.new_module if fnmatch(original_module, self.old_module) else ""
+ #print(f"gen_rm {self.new_module=} {original_module=} {self.old_module=}")
+ old_module = self.old_module
+ if old_module.endswith(".*") and "." not in original_module:
+ old_module, _, _ = old_module.rpartition(".")
+ return self.new_module if fnmatch(original_module, old_module) else ""
def gen_name_or_attr_node(
self, dotted_expression: str
@@ -394,7 +403,6 @@ class RenameCommand(VisitorBasedCodemodCommand):
as_name_node = (
as_name_optional.name if as_name_optional is not None else None
)
- #print(f"{qual_name} as {as_name_node}")
if as_name_node is not None and isinstance(
as_name_node, (cst.Name, cst.Attribute)
):