From 2d5ce4532ade11710ff854516cd085b9ea629cf2 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sun, 5 Nov 2023 18:28:47 -0800 Subject: [PATCH] Flag all comparisons against builtin types in E721 (#8491) See #8483. Generalised fix on top of #8485 Based on the output of `print("\n".join(k for k, v in builtins.__dict__.items() if isinstance(v, type)))` --- .../test/fixtures/pycodestyle/E721.py | 6 ++ .../pycodestyle/rules/type_comparison.rs | 96 +++++++++++++++++-- ...les__pycodestyle__tests__E721_E721.py.snap | 20 ++-- ...destyle__tests__preview__E721_E721.py.snap | 10 ++ 4 files changed, 115 insertions(+), 17 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pycodestyle/E721.py b/crates/ruff_linter/resources/test/fixtures/pycodestyle/E721.py index 2c6ad7fcb9..872fa7042a 100644 --- a/crates/ruff_linter/resources/test/fixtures/pycodestyle/E721.py +++ b/crates/ruff_linter/resources/test/fixtures/pycodestyle/E721.py @@ -53,6 +53,12 @@ if isinstance(res, types.MethodType): if isinstance(res, memoryview): pass #: Okay +if type(res) is type: + pass +#: E721 +if type(res) == type: + pass +#: Okay def func_histype(a, b, c): pass #: E722 diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/type_comparison.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/type_comparison.rs index b5a5eb56d7..598b9a9c11 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/type_comparison.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/type_comparison.rs @@ -198,16 +198,98 @@ fn is_type(expr: &Expr, semantic: &SemanticModel) -> bool { // Ex) `type(obj) == int` matches!( id.as_str(), - "int" - | "str" - | "float" - | "bool" - | "complex" + "bool" + | "bytearray" | "bytes" - | "list" + | "classmethod" + | "complex" | "dict" - | "set" + | "enumerate" + | "filter" + | "float" + | "frozenset" + | "int" + | "list" + | "map" | "memoryview" + | "object" + | "property" + | "range" + | "reversed" + | "set" + | "slice" + | "staticmethod" + | "str" + | "super" + | "tuple" + | "type" + | "zip" + | "ArithmeticError" + | "AssertionError" + | "AttributeError" + | "BaseException" + | "BlockingIOError" + | "BrokenPipeError" + | "BufferError" + | "BytesWarning" + | "ChildProcessError" + | "ConnectionAbortedError" + | "ConnectionError" + | "ConnectionRefusedError" + | "ConnectionResetError" + | "DeprecationWarning" + | "EnvironmentError" + | "EOFError" + | "Exception" + | "FileExistsError" + | "FileNotFoundError" + | "FloatingPointError" + | "FutureWarning" + | "GeneratorExit" + | "ImportError" + | "ImportWarning" + | "IndentationError" + | "IndexError" + | "InterruptedError" + | "IOError" + | "IsADirectoryError" + | "KeyboardInterrupt" + | "KeyError" + | "LookupError" + | "MemoryError" + | "ModuleNotFoundError" + | "NameError" + | "NotADirectoryError" + | "NotImplementedError" + | "OSError" + | "OverflowError" + | "PendingDeprecationWarning" + | "PermissionError" + | "ProcessLookupError" + | "RecursionError" + | "ReferenceError" + | "ResourceWarning" + | "RuntimeError" + | "RuntimeWarning" + | "StopAsyncIteration" + | "StopIteration" + | "SyntaxError" + | "SyntaxWarning" + | "SystemError" + | "SystemExit" + | "TabError" + | "TimeoutError" + | "TypeError" + | "UnboundLocalError" + | "UnicodeDecodeError" + | "UnicodeEncodeError" + | "UnicodeError" + | "UnicodeTranslateError" + | "UnicodeWarning" + | "UserWarning" + | "ValueError" + | "Warning" + | "ZeroDivisionError" ) && semantic.is_builtin(id) } _ => false, diff --git a/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__E721_E721.py.snap b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__E721_E721.py.snap index e0a5626238..415b71d592 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__E721_E721.py.snap +++ b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__E721_E721.py.snap @@ -149,22 +149,22 @@ E721.py:41:8: E721 Do not compare types, use `isinstance()` 42 | #: | -E721.py:101:12: E721 Do not compare types, use `isinstance()` +E721.py:107:12: E721 Do not compare types, use `isinstance()` | - 99 | def asdf(self, value: str | None): -100 | #: E721 -101 | if type(value) is str: +105 | def asdf(self, value: str | None): +106 | #: E721 +107 | if type(value) is str: | ^^^^^^^^^^^^^^^^^^ E721 -102 | ... +108 | ... | -E721.py:111:12: E721 Do not compare types, use `isinstance()` +E721.py:117:12: E721 Do not compare types, use `isinstance()` | -109 | def asdf(self, value: str | None): -110 | #: E721 -111 | if type(value) is str: +115 | def asdf(self, value: str | None): +116 | #: E721 +117 | if type(value) is str: | ^^^^^^^^^^^^^^^^^^ E721 -112 | ... +118 | ... | diff --git a/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__preview__E721_E721.py.snap b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__preview__E721_E721.py.snap index cd70263e68..8971d3f3cc 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__preview__E721_E721.py.snap +++ b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__preview__E721_E721.py.snap @@ -119,4 +119,14 @@ E721.py:41:8: E721 Use `is` and `is not` for type comparisons, or `isinstance()` 42 | #: | +E721.py:59:4: E721 Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks + | +57 | pass +58 | #: E721 +59 | if type(res) == type: + | ^^^^^^^^^^^^^^^^^ E721 +60 | pass +61 | #: Okay + | +