| 34 | |
| 35 | |
| 36 | class SortMethodsTransformer(cst.CSTTransformer): |
| 37 | def __init__(self, class_name: str | None = None, sort_funcs: bool = False): |
| 38 | super().__init__() |
| 39 | self.visit_class_name = [] |
| 40 | self.class_name = class_name |
| 41 | self.sort_funcs = sort_funcs |
| 42 | |
| 43 | @property |
| 44 | def current_class_name(self) -> str: |
| 45 | return ".".join(self.visit_class_name) |
| 46 | |
| 47 | def visit_ClassDef(self, node: cst.ClassDef): |
| 48 | self.visit_class_name.append(node.name.value) |
| 49 | |
| 50 | def leave_ClassDef(self, original_node: cst.ClassDef, updated_node: cst.ClassDef): |
| 51 | try: |
| 52 | if self.class_name is not None and self.current_class_name != self.class_name: |
| 53 | return updated_node |
| 54 | if not any( |
| 55 | base.value.value.endswith("GithubObject") |
| 56 | if isinstance(base.value, cst.Name) |
| 57 | else ( |
| 58 | base.value.value.value.endswith("GithubObject") |
| 59 | if isinstance(base.value.value, cst.Name) |
| 60 | else base.value.value.attr.value.endswith("GithubObject") |
| 61 | ) |
| 62 | for base in updated_node.bases |
| 63 | ): |
| 64 | return updated_node |
| 65 | |
| 66 | statements = list(updated_node.body.body) |
| 67 | if sum(1 for s in statements if isinstance(s, cst.FunctionDef)) == 0: |
| 68 | raise ValueError(f"There are no functions in class {self.current_class_name}") |
| 69 | first = next(idx for idx, s in enumerate(statements) if isinstance(s, cst.FunctionDef)) |
| 70 | last = len(statements) - next( |
| 71 | idx for idx, s in enumerate(reversed(statements)) if isinstance(s, cst.FunctionDef) |
| 72 | ) |
| 73 | if any(not isinstance(s, cst.FunctionDef) for s in statements[first:last]): |
| 74 | raise ValueError(f"There is no consecutive block of functions in class {self.current_class_name}") |
| 75 | |
| 76 | # noinspection PyTypeChecker |
| 77 | function_defs: list[cst.FunctionDef] = statements[first:last] |
| 78 | prolog = statements[:first] |
| 79 | |
| 80 | init = self.find_func(function_defs, "__init__") |
| 81 | init = [init] if init is not None else [] |
| 82 | |
| 83 | init_attrs = self.find_func(function_defs, "_initAttributes") |
| 84 | init_attrs = [init_attrs] if init_attrs is not None else [] |
| 85 | |
| 86 | dunders = list( |
| 87 | s |
| 88 | for s in function_defs |
| 89 | if s.name.value.startswith("__") and s.name.value.endswith("__") and s.name.value != "__init__" |
| 90 | ) |
| 91 | properties = list(s for s in function_defs if self.contains_decorator(s.decorators, "property")) |
| 92 | |
| 93 | use_attrs = self.find_func(function_defs, "_useAttributes") |
no outgoing calls
no test coverage detected
searching dependent graphs…