Skip to content

Commit

Permalink
fix(compare_singleton_primitives_by_is): compare Name directly instea…
Browse files Browse the repository at this point in the history
…d of QualifiedName (#391)

fixes #378 and #375 which are caused by Instagram/LibCST#389.

Qualifying a name will never make some thing that wasn't already
True/False/None into a True/False/None:

```python
import libcst as cst
from libcst.metadata.name_provider import QualifiedNameProvider
from textwrap import dedent

wrapper = cst.MetadataWrapper(
    cst.parse_module(dedent(
    '''
        x = None
        x()
    '''
    ))
)
x_ref = wrapper.module.body[1].body[0].value
print(wrapper.resolve(QualifiedNameProvider)[x_ref]())
```
prints:
```python
{QualifiedName(name='x', source=<QualifiedNameSource.LOCAL: 3>)}
```

Co-authored-by: Amethyst Reese <[email protected]>
  • Loading branch information
llllvvuu and amyreese authored Oct 17, 2023
1 parent f98cb3b commit 79d2080
Showing 1 changed file with 12 additions and 7 deletions.
19 changes: 12 additions & 7 deletions src/fixit/rules/compare_singleton_primitives_by_is.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from typing import FrozenSet, Union
from typing import cast, FrozenSet, Union

import libcst as cst
from libcst.metadata import QualifiedName, QualifiedNameProvider, QualifiedNameSource
Expand Down Expand Up @@ -37,6 +37,8 @@ class CompareSingletonPrimitivesByIs(LintRule):
Valid("False is x"),
Valid("x == 2"),
Valid("2 != x"),
Valid('"True" == "True"'),
Valid('"True" != "False".lower()'),
]
INVALID = [
Invalid(
Expand Down Expand Up @@ -76,6 +78,14 @@ class CompareSingletonPrimitivesByIs(LintRule):
}
)

def is_singleton(self, node: cst.BaseExpression):
qual_name = cast(set, self.get_metadata(QualifiedNameProvider, node, set()))
return (
isinstance(node, cst.Name)
and qual_name
and qual_name < self.QUALIFIED_SINGLETON_PRIMITIVES
)

def visit_Comparison(self, node: cst.Comparison) -> None:
# Initialize the needs_report flag as False to begin with
needs_report = False
Expand All @@ -84,12 +94,7 @@ def visit_Comparison(self, node: cst.Comparison) -> None:
for target in node.comparisons:
operator, right_comp = target.operator, target.comparator
if isinstance(operator, (cst.Equal, cst.NotEqual)) and (
not self.QUALIFIED_SINGLETON_PRIMITIVES.isdisjoint(
self.get_metadata(QualifiedNameProvider, left_comp, set())
)
or not self.QUALIFIED_SINGLETON_PRIMITIVES.isdisjoint(
self.get_metadata(QualifiedNameProvider, right_comp, set())
)
self.is_singleton(left_comp) or self.is_singleton(right_comp)
):
needs_report = True
altered_comparisons.append(
Expand Down

0 comments on commit 79d2080

Please sign in to comment.