|
16 | 16 |
|
17 | 17 | from codesorter.const import ( |
18 | 18 | ORDER_SENSITIVE_BASES, |
| 19 | + ORDER_SENSITIVE_CALLS, |
19 | 20 | ORDER_SENSITIVE_DECORATORS, |
20 | 21 | PLAIN_DECORATOR_PARTS, |
21 | 22 | PROPERTY_DECORATOR_PARTS, |
@@ -69,6 +70,22 @@ class KeywordArgumentSorter(cst.CSTTransformer): |
69 | 70 |
|
70 | 71 | """ |
71 | 72 |
|
| 73 | + @staticmethod |
| 74 | + def _called_name(func: cst.BaseExpression) -> str | None: |
| 75 | + """Return the trailing name of a call target, or ``None`` if it is not a name. |
| 76 | +
|
| 77 | + Resolves both a bare ``OrderedDict`` (``Name``) and a dotted |
| 78 | + ``collections.OrderedDict`` (``Attribute``) to ``"OrderedDict"``. An import |
| 79 | + alias is not followed, matching the suffix-based name matching used elsewhere |
| 80 | + for order-sensitive classes. |
| 81 | +
|
| 82 | + """ |
| 83 | + if isinstance(func, cst.Attribute): |
| 84 | + return func.attr.value |
| 85 | + if isinstance(func, cst.Name): |
| 86 | + return func.value |
| 87 | + return None |
| 88 | + |
72 | 89 | @staticmethod |
73 | 90 | def _sort_comma_runs( |
74 | 91 | elements: Sequence[_CommaT], |
@@ -107,9 +124,13 @@ def leave_Call(self, original_node: cst.Call, updated_node: cst.Call) -> cst.Cal |
107 | 124 | barriers: a call raises ``TypeError`` on any duplicate keyword regardless of |
108 | 125 | order, so moving keyword arguments across a ``**`` cannot change the result. |
109 | 126 | Positional arguments and ``*`` unpackings stay put because their order |
110 | | - determines positional binding. |
| 127 | + determines positional binding. Calls to an order-sensitive callable such as |
| 128 | + ``OrderedDict`` are left untouched, since their keyword-argument order is the |
| 129 | + iteration order and reordering it would change the resulting value. |
111 | 130 |
|
112 | 131 | """ |
| 132 | + if self._called_name(updated_node.func) in ORDER_SENSITIVE_CALLS: |
| 133 | + return updated_node |
113 | 134 | return updated_node.with_changes( |
114 | 135 | args=self._sort_comma_runs( |
115 | 136 | updated_node.args, |
|
0 commit comments