Skip to content

Commit 79d2080

Browse files
llllvvuuamyreese
andauthored
fix(compare_singleton_primitives_by_is): compare Name directly instead 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]>
1 parent f98cb3b commit 79d2080

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

src/fixit/rules/compare_singleton_primitives_by_is.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# This source code is licensed under the MIT license found in the
44
# LICENSE file in the root directory of this source tree.
55

6-
from typing import FrozenSet, Union
6+
from typing import cast, FrozenSet, Union
77

88
import libcst as cst
99
from libcst.metadata import QualifiedName, QualifiedNameProvider, QualifiedNameSource
@@ -37,6 +37,8 @@ class CompareSingletonPrimitivesByIs(LintRule):
3737
Valid("False is x"),
3838
Valid("x == 2"),
3939
Valid("2 != x"),
40+
Valid('"True" == "True"'),
41+
Valid('"True" != "False".lower()'),
4042
]
4143
INVALID = [
4244
Invalid(
@@ -76,6 +78,14 @@ class CompareSingletonPrimitivesByIs(LintRule):
7678
}
7779
)
7880

81+
def is_singleton(self, node: cst.BaseExpression):
82+
qual_name = cast(set, self.get_metadata(QualifiedNameProvider, node, set()))
83+
return (
84+
isinstance(node, cst.Name)
85+
and qual_name
86+
and qual_name < self.QUALIFIED_SINGLETON_PRIMITIVES
87+
)
88+
7989
def visit_Comparison(self, node: cst.Comparison) -> None:
8090
# Initialize the needs_report flag as False to begin with
8191
needs_report = False
@@ -84,12 +94,7 @@ def visit_Comparison(self, node: cst.Comparison) -> None:
8494
for target in node.comparisons:
8595
operator, right_comp = target.operator, target.comparator
8696
if isinstance(operator, (cst.Equal, cst.NotEqual)) and (
87-
not self.QUALIFIED_SINGLETON_PRIMITIVES.isdisjoint(
88-
self.get_metadata(QualifiedNameProvider, left_comp, set())
89-
)
90-
or not self.QUALIFIED_SINGLETON_PRIMITIVES.isdisjoint(
91-
self.get_metadata(QualifiedNameProvider, right_comp, set())
92-
)
97+
self.is_singleton(left_comp) or self.is_singleton(right_comp)
9398
):
9499
needs_report = True
95100
altered_comparisons.append(

0 commit comments

Comments
 (0)