From 09d0864d492ada29b7e5adf35699b477c8c66531 Mon Sep 17 00:00:00 2001 From: Anuda Weerasinghe Date: Wed, 26 Apr 2023 21:13:28 -0400 Subject: [PATCH 01/14] adds asttokens and progress update --- .gitignore | 1 + enum_issue_progress.md | 82 ++++++++++++++++++++++++++++++++++++++++++ enum_scope.txt | 64 +++++++++++++++++++++++++++++++++ enum_test.py | 7 ++++ vulture/core.py | 5 +++ 5 files changed, 159 insertions(+) create mode 100644 enum_issue_progress.md create mode 100644 enum_scope.txt create mode 100644 enum_test.py diff --git a/.gitignore b/.gitignore index df191195..0ec272f6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ vulture.egg-info/ .pytest_cache/ .tox/ .venv/ +.vscode/ diff --git a/enum_issue_progress.md b/enum_issue_progress.md new file mode 100644 index 00000000..184b4b96 --- /dev/null +++ b/enum_issue_progress.md @@ -0,0 +1,82 @@ +## Our progress thus far on [issue #304](https://github.com/jendrikseipp/vulture/issues/304) + +- We traced the code path by running the debugger on the source code. +- Identified that Vulture generates an AST of the provided source code in the `scan` function in `core.py` +- Each node in the AST is then visited by the `visit` function +- The `visit` function decides what helper to use based on the type of node +- For this issue, we specifically care about the `visit_Call` and `visit_ClassDef` functions because these are invoked when the `list()` function is called, and when a class is defined with the `Enum` subclass. + +Based on these findings, here is a high level approach of the solution we will implement: + +- Extend the ast with scoping information using the [asttokens](https://asttokens.readthedocs.io/en/latest/) package. +- In `visit_Call`, check if the `node.func.id=='list'` - are we calling the list function? +- If so, get the argument(`node.args[0].id`) and use the scoping information provided by asttokens to check if the argument is a class +- If so, use the scope info about the class to check if `Enum` is a superclass. +- If so, then add all the fields defined in the class to `defined_variables` + +Debug output is attached below. See `enum_scope.txt` for more details. + +``` +Module( + body=[ + ImportFrom( + module='enum', + names=[ + alias(name='Enum')], + level=0), + ClassDef( + name='E', + bases=[ + Name(id='Enum', ctx=Load())], + keywords=[], + body=[ + Assign( + targets=[ + Name(id='A', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='B', ctx=Store())], + value=Constant(value=2))], + decorator_list=[])], + type_ignores=[]) +Module( + body=[ + Import( + names=[ + alias(name='enum')]), + ClassDef( + name='EnumWhitelist', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Assign( + targets=[ + Name(id='EnumWhitelist', ctx=Store())], + value=Constant(value=1))], + decorator_list=[]), + Expr( + value=Attribute( + value=Attribute( + value=Name(id='EnumWhitelist', ctx=Load()), + attr='EnumWhitelist', + ctx=Load()), + attr='_name_', + ctx=Load())), + Expr( + value=Attribute( + value=Attribute( + value=Name(id='EnumWhitelist', ctx=Load()), + attr='EnumWhitelist', + ctx=Load()), + attr='_value_', + ctx=Load()))], + type_ignores=[]) +enum_test.py:3: unused class 'E' (60% confidence) +enum_test.py:4: unused variable 'A' (60% confidence) +enum_test.py:5: unused variable 'B' (60% confidence) +``` diff --git a/enum_scope.txt b/enum_scope.txt new file mode 100644 index 00000000..e5f4900b --- /dev/null +++ b/enum_scope.txt @@ -0,0 +1,64 @@ +AST without scoping info: +Module( + body=[ + ImportFrom( + module='enum', + names=[ + alias(name='Enum')], + level=0), + ClassDef( + name='E', + bases=[ + Name(id='Enum', ctx=Load())], + keywords=[], + body=[ + Assign( + targets=[ + Name(id='A', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='B', ctx=Store())], + value=Constant(value=2))], + decorator_list=[])], + type_ignores=[]) +AST without scoping info: +Module( + body=[ + Import( + names=[ + alias(name='enum')]), + ClassDef( + name='EnumWhitelist', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Assign( + targets=[ + Name(id='EnumWhitelist', ctx=Store())], + value=Constant(value=1))], + decorator_list=[]), + Expr( + value=Attribute( + value=Attribute( + value=Name(id='EnumWhitelist', ctx=Load()), + attr='EnumWhitelist', + ctx=Load()), + attr='_name_', + ctx=Load())), + Expr( + value=Attribute( + value=Attribute( + value=Name(id='EnumWhitelist', ctx=Load()), + attr='EnumWhitelist', + ctx=Load()), + attr='_value_', + ctx=Load()))], + type_ignores=[]) +enum_test.py:3: unused class 'E' (60% confidence) +enum_test.py:4: unused variable 'A' (60% confidence) +enum_test.py:5: unused variable 'B' (60% confidence) diff --git a/enum_test.py b/enum_test.py new file mode 100644 index 00000000..ad39e090 --- /dev/null +++ b/enum_test.py @@ -0,0 +1,7 @@ +from enum import Enum + +class E(Enum): + A = 1 + B = 2 + +# list(E) \ No newline at end of file diff --git a/vulture/core.py b/vulture/core.py index 16c71948..cb274b3b 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -5,6 +5,7 @@ import re import string import sys +from asttokens import asttokens from vulture import lines from vulture import noqa @@ -242,6 +243,10 @@ def handle_syntax_error(e): if sys.version_info >= (3, 8) # type_comments requires 3.8+ else ast.parse(code, filename=str(self.filename)) ) + tokens = asttokens.ASTTokens(code, parse=True) + print("AST without scoping info:") + print(ast.dump(node, indent=4)) + except SyntaxError as err: handle_syntax_error(err) except ValueError as err: From af7c890abbc130ffde469156e7a35a2b025c3799 Mon Sep 17 00:00:00 2001 From: addykan Date: Fri, 5 May 2023 17:00:42 -0400 Subject: [PATCH 02/14] Wrote initial enum detection code --- enum_test.py | 2 +- vulture/core.py | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/enum_test.py b/enum_test.py index ad39e090..92b831a3 100644 --- a/enum_test.py +++ b/enum_test.py @@ -4,4 +4,4 @@ class E(Enum): A = 1 B = 2 -# list(E) \ No newline at end of file +list(E) \ No newline at end of file diff --git a/vulture/core.py b/vulture/core.py index cb274b3b..8bb387bc 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -220,6 +220,8 @@ def get_list(typ): self.code = [] self.found_dead_code_or_error = False + self.enum_class_vars = dict() + def scan(self, code, filename=""): filename = Path(filename) self.code = code.splitlines() @@ -556,6 +558,12 @@ def visit_Call(self, node): ): self._handle_new_format_string(node.func.value.s) + if node.func.id=='list': + arg = node.args[0].id + if arg in self.enum_class_vars: + self.used_names.update(self.enum_class_vars[arg]) + + def _handle_new_format_string(self, s): def is_identifier(name): return bool(re.match(r"[a-zA-Z_][a-zA-Z0-9_]*", name)) @@ -599,6 +607,24 @@ def visit_ClassDef(self, node): self._define( self.defined_classes, node.name, node, ignore=_ignore_class ) + if self._subclassesEnum(node): + newKey = node.name + classVariables = [] + for stmt in node.body: + if isinstance(stmt, ast.Assign): + for target in stmt.targets: + classVariables.append(target.id) + self.enum_class_vars[newKey] = classVariables + + def _subclassesEnum(self, node): + for base in node.bases: + if isinstance(base, ast.Name): + if base.id.lower() == 'enum': + return True + elif isinstance(base, ast.Attribute): + if base.value.id.lower() == 'enum': + return True + return False def visit_FunctionDef(self, node): decorator_names = [ From d11e6b322c716ca65074faced1ce2fc8707cac74 Mon Sep 17 00:00:00 2001 From: addykan Date: Fri, 5 May 2023 17:18:13 -0400 Subject: [PATCH 03/14] Cleaned up debug output for unused enum bug --- vulture/core.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/vulture/core.py b/vulture/core.py index 8bb387bc..f5dc2920 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -246,9 +246,6 @@ def handle_syntax_error(e): else ast.parse(code, filename=str(self.filename)) ) tokens = asttokens.ASTTokens(code, parse=True) - print("AST without scoping info:") - print(ast.dump(node, indent=4)) - except SyntaxError as err: handle_syntax_error(err) except ValueError as err: @@ -558,12 +555,11 @@ def visit_Call(self, node): ): self._handle_new_format_string(node.func.value.s) - if node.func.id=='list': + if (isinstance(node.func, ast.Name) and node.func.id == 'list' and len(node.args) > 0 and isinstance(node.args[0], ast.Name)): arg = node.args[0].id if arg in self.enum_class_vars: self.used_names.update(self.enum_class_vars[arg]) - def _handle_new_format_string(self, s): def is_identifier(name): return bool(re.match(r"[a-zA-Z_][a-zA-Z0-9_]*", name)) @@ -607,7 +603,7 @@ def visit_ClassDef(self, node): self._define( self.defined_classes, node.name, node, ignore=_ignore_class ) - if self._subclassesEnum(node): + if self._subclassesEnum(node): newKey = node.name classVariables = [] for stmt in node.body: @@ -624,7 +620,7 @@ def _subclassesEnum(self, node): elif isinstance(base, ast.Attribute): if base.value.id.lower() == 'enum': return True - return False + return False def visit_FunctionDef(self, node): decorator_names = [ From b36da88906eb0f5c9d2846c194710ef60156f76a Mon Sep 17 00:00:00 2001 From: pm3512 Date: Fri, 5 May 2023 21:14:47 -0400 Subject: [PATCH 04/14] recursive enum check --- vulture/core.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/vulture/core.py b/vulture/core.py index f5dc2920..3e691ba3 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -5,7 +5,6 @@ import re import string import sys -from asttokens import asttokens from vulture import lines from vulture import noqa @@ -245,7 +244,7 @@ def handle_syntax_error(e): if sys.version_info >= (3, 8) # type_comments requires 3.8+ else ast.parse(code, filename=str(self.filename)) ) - tokens = asttokens.ASTTokens(code, parse=True) + print(ast.dump(node, indent=4)) except SyntaxError as err: handle_syntax_error(err) except ValueError as err: @@ -555,7 +554,12 @@ def visit_Call(self, node): ): self._handle_new_format_string(node.func.value.s) - if (isinstance(node.func, ast.Name) and node.func.id == 'list' and len(node.args) > 0 and isinstance(node.args[0], ast.Name)): + if ( + isinstance(node.func, ast.Name) + and node.func.id == "list" + and len(node.args) > 0 + and isinstance(node.args[0], ast.Name) + ): arg = node.args[0].id if arg in self.enum_class_vars: self.used_names.update(self.enum_class_vars[arg]) @@ -615,10 +619,13 @@ def visit_ClassDef(self, node): def _subclassesEnum(self, node): for base in node.bases: if isinstance(base, ast.Name): - if base.id.lower() == 'enum': + if ( + base.id.lower() == "enum" + or base.id in self.enum_class_vars + ): return True elif isinstance(base, ast.Attribute): - if base.value.id.lower() == 'enum': + if base.value.id.lower() == "enum": return True return False From d2cb7030bf3168c27166709de80e84bb55270386 Mon Sep 17 00:00:00 2001 From: pm3512 Date: Sat, 6 May 2023 18:41:22 -0400 Subject: [PATCH 05/14] added for loop handling --- vulture/core.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/vulture/core.py b/vulture/core.py index 3e691ba3..b5a74b9f 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -244,7 +244,6 @@ def handle_syntax_error(e): if sys.version_info >= (3, 8) # type_comments requires 3.8+ else ast.parse(code, filename=str(self.filename)) ) - print(ast.dump(node, indent=4)) except SyntaxError as err: handle_syntax_error(err) except ValueError as err: @@ -554,9 +553,11 @@ def visit_Call(self, node): ): self._handle_new_format_string(node.func.value.s) + # handle enum.Enum members + iter_functions = ["list", "tuple", "set"] if ( isinstance(node.func, ast.Name) - and node.func.id == "list" + and node.func.id in iter_functions and len(node.args) > 0 and isinstance(node.args[0], ast.Name) ): @@ -619,10 +620,7 @@ def visit_ClassDef(self, node): def _subclassesEnum(self, node): for base in node.bases: if isinstance(base, ast.Name): - if ( - base.id.lower() == "enum" - or base.id in self.enum_class_vars - ): + if base.id.lower() == "enum": return True elif isinstance(base, ast.Attribute): if base.value.id.lower() == "enum": @@ -695,6 +693,13 @@ def visit_Assign(self, node): def visit_While(self, node): self._handle_conditional_node(node, "while") + def visit_For(self, node): + if ( + isinstance(node.iter, ast.Name) + and node.iter.id in self.enum_class_vars + ): + self.used_names.update(self.enum_class_vars[node.iter.id]) + def visit_MatchClass(self, node): for kwd_attr in node.kwd_attrs: self.used_names.add(kwd_attr) From 755f84653891a6bb54f0e34b911f935b6bde3032 Mon Sep 17 00:00:00 2001 From: pm3512 Date: Sat, 6 May 2023 18:41:50 -0400 Subject: [PATCH 06/14] added tests --- tests/test_scavenging.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/test_scavenging.py b/tests/test_scavenging.py index 27154cd6..6a287547 100644 --- a/tests/test_scavenging.py +++ b/tests/test_scavenging.py @@ -899,3 +899,38 @@ class Color(Enum): check(v.unused_classes, []) check(v.unused_vars, ["BLUE"]) + + +def test_enum_list(v): + v.scan( + """\ +import enum +class E(enum.Enum): + A = 1 + B = 2 + +print(list(E)) +""" + ) + + check(v.defined_classes, ["E"]) + check(v.defined_vars, ["A", "B"]) + check(v.unused_vars, []) + + +def test_enum_for(v): + v.scan( + """\ +import enum +class E(enum.Enum): + A = 1 + B = 2 + +for e in E: + print(e) +""" + ) + + check(v.defined_classes, ["E"]) + check(v.defined_vars, ["A", "B", "e"]) + check(v.unused_vars, []) From 300435c2a3b84d10dea8ef4563263205fa499123 Mon Sep 17 00:00:00 2001 From: Anuda Weerasinghe Date: Sat, 6 May 2023 18:50:05 -0400 Subject: [PATCH 07/14] adds comments describing enum iteration changes --- enum_issue_progress.md | 82 ------------------------------------------ enum_scope.txt | 64 --------------------------------- enum_test.py | 7 ---- vulture/core.py | 7 +++- 4 files changed, 6 insertions(+), 154 deletions(-) delete mode 100644 enum_issue_progress.md delete mode 100644 enum_scope.txt delete mode 100644 enum_test.py diff --git a/enum_issue_progress.md b/enum_issue_progress.md deleted file mode 100644 index 184b4b96..00000000 --- a/enum_issue_progress.md +++ /dev/null @@ -1,82 +0,0 @@ -## Our progress thus far on [issue #304](https://github.com/jendrikseipp/vulture/issues/304) - -- We traced the code path by running the debugger on the source code. -- Identified that Vulture generates an AST of the provided source code in the `scan` function in `core.py` -- Each node in the AST is then visited by the `visit` function -- The `visit` function decides what helper to use based on the type of node -- For this issue, we specifically care about the `visit_Call` and `visit_ClassDef` functions because these are invoked when the `list()` function is called, and when a class is defined with the `Enum` subclass. - -Based on these findings, here is a high level approach of the solution we will implement: - -- Extend the ast with scoping information using the [asttokens](https://asttokens.readthedocs.io/en/latest/) package. -- In `visit_Call`, check if the `node.func.id=='list'` - are we calling the list function? -- If so, get the argument(`node.args[0].id`) and use the scoping information provided by asttokens to check if the argument is a class -- If so, use the scope info about the class to check if `Enum` is a superclass. -- If so, then add all the fields defined in the class to `defined_variables` - -Debug output is attached below. See `enum_scope.txt` for more details. - -``` -Module( - body=[ - ImportFrom( - module='enum', - names=[ - alias(name='Enum')], - level=0), - ClassDef( - name='E', - bases=[ - Name(id='Enum', ctx=Load())], - keywords=[], - body=[ - Assign( - targets=[ - Name(id='A', ctx=Store())], - value=Constant(value=1)), - Assign( - targets=[ - Name(id='B', ctx=Store())], - value=Constant(value=2))], - decorator_list=[])], - type_ignores=[]) -Module( - body=[ - Import( - names=[ - alias(name='enum')]), - ClassDef( - name='EnumWhitelist', - bases=[ - Attribute( - value=Name(id='enum', ctx=Load()), - attr='Enum', - ctx=Load())], - keywords=[], - body=[ - Assign( - targets=[ - Name(id='EnumWhitelist', ctx=Store())], - value=Constant(value=1))], - decorator_list=[]), - Expr( - value=Attribute( - value=Attribute( - value=Name(id='EnumWhitelist', ctx=Load()), - attr='EnumWhitelist', - ctx=Load()), - attr='_name_', - ctx=Load())), - Expr( - value=Attribute( - value=Attribute( - value=Name(id='EnumWhitelist', ctx=Load()), - attr='EnumWhitelist', - ctx=Load()), - attr='_value_', - ctx=Load()))], - type_ignores=[]) -enum_test.py:3: unused class 'E' (60% confidence) -enum_test.py:4: unused variable 'A' (60% confidence) -enum_test.py:5: unused variable 'B' (60% confidence) -``` diff --git a/enum_scope.txt b/enum_scope.txt deleted file mode 100644 index e5f4900b..00000000 --- a/enum_scope.txt +++ /dev/null @@ -1,64 +0,0 @@ -AST without scoping info: -Module( - body=[ - ImportFrom( - module='enum', - names=[ - alias(name='Enum')], - level=0), - ClassDef( - name='E', - bases=[ - Name(id='Enum', ctx=Load())], - keywords=[], - body=[ - Assign( - targets=[ - Name(id='A', ctx=Store())], - value=Constant(value=1)), - Assign( - targets=[ - Name(id='B', ctx=Store())], - value=Constant(value=2))], - decorator_list=[])], - type_ignores=[]) -AST without scoping info: -Module( - body=[ - Import( - names=[ - alias(name='enum')]), - ClassDef( - name='EnumWhitelist', - bases=[ - Attribute( - value=Name(id='enum', ctx=Load()), - attr='Enum', - ctx=Load())], - keywords=[], - body=[ - Assign( - targets=[ - Name(id='EnumWhitelist', ctx=Store())], - value=Constant(value=1))], - decorator_list=[]), - Expr( - value=Attribute( - value=Attribute( - value=Name(id='EnumWhitelist', ctx=Load()), - attr='EnumWhitelist', - ctx=Load()), - attr='_name_', - ctx=Load())), - Expr( - value=Attribute( - value=Attribute( - value=Name(id='EnumWhitelist', ctx=Load()), - attr='EnumWhitelist', - ctx=Load()), - attr='_value_', - ctx=Load()))], - type_ignores=[]) -enum_test.py:3: unused class 'E' (60% confidence) -enum_test.py:4: unused variable 'A' (60% confidence) -enum_test.py:5: unused variable 'B' (60% confidence) diff --git a/enum_test.py b/enum_test.py deleted file mode 100644 index 92b831a3..00000000 --- a/enum_test.py +++ /dev/null @@ -1,7 +0,0 @@ -from enum import Enum - -class E(Enum): - A = 1 - B = 2 - -list(E) \ No newline at end of file diff --git a/vulture/core.py b/vulture/core.py index b5a74b9f..145fa6c6 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -219,7 +219,7 @@ def get_list(typ): self.code = [] self.found_dead_code_or_error = False - self.enum_class_vars = dict() + self.enum_class_vars = dict() # stores variables defined in enum classes def scan(self, code, filename=""): filename = Path(filename) @@ -608,6 +608,7 @@ def visit_ClassDef(self, node): self._define( self.defined_classes, node.name, node, ignore=_ignore_class ) + # if subclasses enum add class variables to enum_class_vars if self._subclassesEnum(node): newKey = node.name classVariables = [] @@ -618,6 +619,9 @@ def visit_ClassDef(self, node): self.enum_class_vars[newKey] = classVariables def _subclassesEnum(self, node): + ''' + Checks if a class has Enum as a superclass + ''' for base in node.bases: if isinstance(base, ast.Name): if base.id.lower() == "enum": @@ -694,6 +698,7 @@ def visit_While(self, node): self._handle_conditional_node(node, "while") def visit_For(self, node): + # Handle iterating over Enum if ( isinstance(node.iter, ast.Name) and node.iter.id in self.enum_class_vars From c6d40425556a3c828b88880267453f951d631459 Mon Sep 17 00:00:00 2001 From: Anuda Weerasinghe Date: Sat, 6 May 2023 18:53:32 -0400 Subject: [PATCH 08/14] updates changelog --- CHANGELOG.md | 271 ++++++++++++++++++++++++++------------------------- 1 file changed, 136 insertions(+), 135 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d9d406..a044d2fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,304 +1,305 @@ -* Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). -* Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). +- Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). +- Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). +- Fix false positive when iterating over `Enum` (anudaweerasinghe, pm3512, akanagal, ) # 2.7 (2023-01-08) -* Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). -* Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). -* Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). -* Fix example in README file (Jendrik Seipp, #272). +- Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). +- Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). +- Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). +- Fix example in README file (Jendrik Seipp, #272). # 2.6 (2022-09-19) -* Add basic `match` statement support (kreathon, #276, #291). +- Add basic `match` statement support (kreathon, #276, #291). # 2.5 (2022-07-03) -* Mark imports in `__all__` as used (kreathon, #172, #282). -* Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). +- Mark imports in `__all__` as used (kreathon, #172, #282). +- Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). # 2.4 (2022-05-19) -* Print absolute filepaths as relative again (as in version 2.1 and before) +- Print absolute filepaths as relative again (as in version 2.1 and before) if they are below the current directory (The-Compiler, #246). -* Run tests and add PyPI trove for Python 3.10 (chayim, #266). -* Allow using the `del` keyword to mark unused variables (sshishov, #279). +- Run tests and add PyPI trove for Python 3.10 (chayim, #266). +- Allow using the `del` keyword to mark unused variables (sshishov, #279). # 2.3 (2021-01-16) -* Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). +- Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). # 2.2 (2021-01-15) -* Only parse format strings when being used with `locals()` (jingw, #225). -* Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). -* Run continuous integration tests for Python 3.9 (ju-sh, #232). -* Use pathlib internally (ju-sh, #226). +- Only parse format strings when being used with `locals()` (jingw, #225). +- Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). +- Run continuous integration tests for Python 3.9 (ju-sh, #232). +- Use pathlib internally (ju-sh, #226). # 2.1 (2020-08-19) -* Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to +- Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to `obj.constant_string` (jingw, #219). -* Fix false positives when assigning to `x.some_name` but reading via +- Fix false positives when assigning to `x.some_name` but reading via `some_name`, at the cost of potential false negatives (jingw, #221). -* Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). +- Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). # 2.0 (2020-08-11) -* Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). -* Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last +- Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). +- Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last Vulture release that supports Python 2.7 and Python 3.5 is version 1.6. -* Consider all files under `test` or `tests` directories test files +- Consider all files under `test` or `tests` directories test files (Jendrik Seipp). -* Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). +- Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). # 1.6 (2020-07-28) -* Differentiate between functions and methods (Jendrik Seipp, #112, #209). -* Move from Travis to GitHub actions (RJ722, #211). +- Differentiate between functions and methods (Jendrik Seipp, #112, #209). +- Move from Travis to GitHub actions (RJ722, #211). # 1.5 (2020-05-24) -* Support flake8 "noqa" error codes F401 (unused import) and F841 (unused +- Support flake8 "noqa" error codes F401 (unused import) and F841 (unused local variable) (RJ722, #195). -* Detect unreachable code in conditional expressions +- Detect unreachable code in conditional expressions (Agathiyan Bragadeesh, #178). # 1.4 (2020-03-30) -* Ignore unused import statements in `__init__.py` (RJ722, #192). -* Report first decorator's line number for unused decorated objects on +- Ignore unused import statements in `__init__.py` (RJ722, #192). +- Report first decorator's line number for unused decorated objects on Python 3.8+ (RJ722, #200). -* Check code with black and pyupgrade. +- Check code with black and pyupgrade. # 1.3 (2020-02-03) -* Detect redundant 'if' conditions without 'else' blocks. -* Add whitelist for `string.Formatter` (Joseph Bylund, #183). +- Detect redundant 'if' conditions without 'else' blocks. +- Add whitelist for `string.Formatter` (Joseph Bylund, #183). # 1.2 (2019-11-22) -* Fix tests for Python 3.8 (#166). -* Use new `Constant` AST node under Python 3.8+ (#175). -* Add test for f-strings (#177). -* Add whitelist for `logging` module. +- Fix tests for Python 3.8 (#166). +- Use new `Constant` AST node under Python 3.8+ (#175). +- Add test for f-strings (#177). +- Add whitelist for `logging` module. # 1.1 (2019-09-23) -* Add `sys.excepthook` to `sys` whitelist. -* Add whitelist for `ctypes` module. -* Check that type annotations are parsed and type comments are ignored +- Add `sys.excepthook` to `sys` whitelist. +- Add whitelist for `ctypes` module. +- Check that type annotations are parsed and type comments are ignored (thanks @kx-chen). -* Support checking files with BOM under Python 2.7 (#170). +- Support checking files with BOM under Python 2.7 (#170). # 1.0 (2018-10-23) -* Add `--ignore-decorators` flag (thanks @RJ722). -* Add whitelist for `threading` module (thanks @andrewhalle). +- Add `--ignore-decorators` flag (thanks @RJ722). +- Add whitelist for `threading` module (thanks @andrewhalle). # 0.29 (2018-07-31) -* Add `--ignore-names` flag for ignoring names matching the given glob +- Add `--ignore-names` flag for ignoring names matching the given glob patterns (thanks @RJ722). # 0.28 (2018-07-05) -* Add `--make-whitelist` flag for reporting output in whitelist format +- Add `--make-whitelist` flag for reporting output in whitelist format (thanks @RJ722). -* Ignore case of `--exclude` arguments on Windows. -* Add `*-test.py` to recognized test file patterns. -* Add `failureException`, `longMessage` and `maxDiff` to `unittest` +- Ignore case of `--exclude` arguments on Windows. +- Add `*-test.py` to recognized test file patterns. +- Add `failureException`, `longMessage` and `maxDiff` to `unittest` whitelist. -* Refer to actual objects rather than their mocks in default +- Refer to actual objects rather than their mocks in default whitelists (thanks @RJ722). -* Don't import any Vulture modules in setup.py (thanks @RJ722). +- Don't import any Vulture modules in setup.py (thanks @RJ722). # 0.27 (2018-06-05) -* Report `while (True): ... else: ...` as unreachable (thanks @RJ722). -* Use `argparse` instead of `optparse`. -* Whitelist Mock.return\_value and Mock.side\_effect in unittest.mock +- Report `while (True): ... else: ...` as unreachable (thanks @RJ722). +- Use `argparse` instead of `optparse`. +- Whitelist Mock.return_value and Mock.side_effect in unittest.mock module. -* Drop support for Python 2.6 and 3.3. -* Improve documentation and test coverage (thanks @RJ722). +- Drop support for Python 2.6 and 3.3. +- Improve documentation and test coverage (thanks @RJ722). # 0.26 (2017-08-28) -* Detect `async` function definitions (thanks @RJ722). -* Add `Item.get_report()` method (thanks @RJ722). -* Move method for finding Python modules out of Vulture class. +- Detect `async` function definitions (thanks @RJ722). +- Add `Item.get_report()` method (thanks @RJ722). +- Move method for finding Python modules out of Vulture class. # 0.25 (2017-08-15) -* Detect unsatisfiable statements containing `and`, `or` and `not`. -* Use filenames and line numbers as tie-breakers when sorting by size. -* Store first and last line numbers in Item objects. -* Pass relevant options directly to `scavenge()` and `report()`. +- Detect unsatisfiable statements containing `and`, `or` and `not`. +- Use filenames and line numbers as tie-breakers when sorting by size. +- Store first and last line numbers in Item objects. +- Pass relevant options directly to `scavenge()` and `report()`. # 0.24 (2017-08-14) -* Detect unsatisfiable `while`-conditions (thanks @RJ722). -* Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). -* Handle null bytes in source code. +- Detect unsatisfiable `while`-conditions (thanks @RJ722). +- Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). +- Handle null bytes in source code. # 0.23 (2017-08-10) -* Add `--min-confidence` flag (thanks @RJ722). +- Add `--min-confidence` flag (thanks @RJ722). # 0.22 (2017-08-04) -* Detect unreachable code after `return`, `break`, `continue` and +- Detect unreachable code after `return`, `break`, `continue` and `raise` (thanks @RJ722). -* Parse all variable and attribute names in new format strings. -* Extend ast whitelist. +- Parse all variable and attribute names in new format strings. +- Extend ast whitelist. # 0.21 (2017-07-26) -* If an unused item is defined multiple times, report it multiple +- If an unused item is defined multiple times, report it multiple times. -* Make size estimates for function calls more accurate. -* Create wheel files for Vulture (thanks @RJ722). +- Make size estimates for function calls more accurate. +- Create wheel files for Vulture (thanks @RJ722). # 0.20 (2017-07-26) -* Report unused tuple assignments as dead code. -* Report attribute names that have the same names as variables as dead +- Report unused tuple assignments as dead code. +- Report attribute names that have the same names as variables as dead code. -* Let Item class inherit from `object` (thanks @RJ722). -* Handle names imported as aliases like all other used variable names. -* Rename Vulture.used\_vars to Vulture.used\_names. -* Use function for determining which imports to ignore. -* Only try to import each whitelist file once. -* Store used names and used attributes in sets instead of lists. -* Fix estimating the size of code containing ellipses (...). -* Refactor and simplify code. +- Let Item class inherit from `object` (thanks @RJ722). +- Handle names imported as aliases like all other used variable names. +- Rename Vulture.used_vars to Vulture.used_names. +- Use function for determining which imports to ignore. +- Only try to import each whitelist file once. +- Store used names and used attributes in sets instead of lists. +- Fix estimating the size of code containing ellipses (...). +- Refactor and simplify code. # 0.19 (2017-07-20) -* Don't ignore \_\_foo variable names. -* Use separate methods for determining whether to ignore classes and +- Don't ignore \_\_foo variable names. +- Use separate methods for determining whether to ignore classes and functions. -* Only try to find a whitelist for each defined import once (thanks +- Only try to find a whitelist for each defined import once (thanks @roivanov). -* Fix finding the last child for many types of AST nodes. +- Fix finding the last child for many types of AST nodes. # 0.18 (2017-07-17) -* Make --sort-by-size faster and more +- Make --sort-by-size faster and more accurate (thanks @RJ722). # 0.17 (2017-07-17) -* Add get\_unused\_code() method. -* Return with exit code 1 when syntax errors are found or files can't +- Add get_unused_code() method. +- Return with exit code 1 when syntax errors are found or files can't be read. # 0.16 (2017-07-12) -* Differentiate between unused classes and functions (thanks @RJ722). -* Add --sort-by-size option (thanks @jackric and @RJ722). -* Count imports as used if they are accessed as module attributes. +- Differentiate between unused classes and functions (thanks @RJ722). +- Add --sort-by-size option (thanks @jackric and @RJ722). +- Count imports as used if they are accessed as module attributes. # 0.15 (2017-07-04) -* Automatically include whitelists based on imported modules (thanks +- Automatically include whitelists based on imported modules (thanks @RJ722). -* Add --version parameter (thanks @RJ722). -* Add appveyor tests for testing on Windows (thanks @RJ722). +- Add --version parameter (thanks @RJ722). +- Add appveyor tests for testing on Windows (thanks @RJ722). # 0.14 (2017-04-06) -* Add stub whitelist file for Python standard library (thanks @RJ722) -* Ignore class names starting with "Test" in "test\_" files (thanks +- Add stub whitelist file for Python standard library (thanks @RJ722) +- Ignore class names starting with "Test" in "test\_" files (thanks @thisch). -* Ignore "test\_" functions only in "test\_" files. +- Ignore "test\_" functions only in "test\_" files. # 0.13 (2017-03-06) -* Ignore star-imported names since we cannot detect whether they are +- Ignore star-imported names since we cannot detect whether they are used. -* Move repository to GitHub. +- Move repository to GitHub. # 0.12 (2017-01-05) -* Detect unused imports. -* Use tokenize.open() on Python \>= 3.2 for reading input files, +- Detect unused imports. +- Use tokenize.open() on Python \>= 3.2 for reading input files, assume UTF-8 encoding on older Python versions. # 0.11 (2016-11-27) -* Use the system's default encoding when reading files. -* Report syntax errors instead of aborting. +- Use the system's default encoding when reading files. +- Report syntax errors instead of aborting. # 0.10 (2016-07-14) -* Detect unused function and method arguments (issue #15). -* Detect unused \*args and \*\*kwargs parameters. -* Change license from GPL to MIT. +- Detect unused function and method arguments (issue #15). +- Detect unused \*args and \*\*kwargs parameters. +- Change license from GPL to MIT. # 0.9 (2016-06-29) -* Don't flag attributes as unused if they are used as global variables +- Don't flag attributes as unused if they are used as global variables in another module (thanks Florian Bruhin). -* Don't consider "True" and "False" variable names. -* Abort with error message when invoked on .pyc files. +- Don't consider "True" and "False" variable names. +- Abort with error message when invoked on .pyc files. # 0.8.1 (2015-09-28) -* Fix code for Python 3. +- Fix code for Python 3. # 0.8 (2015-09-28) -* Do not flag names imported with "import as" as dead code (thanks Tom +- Do not flag names imported with "import as" as dead code (thanks Tom Terrace). # 0.7 (2015-09-26) -* Exit with exitcode 1 if path on commandline can't be found. -* Test vulture with vulture using a whitelist module for false +- Exit with exitcode 1 if path on commandline can't be found. +- Test vulture with vulture using a whitelist module for false positives. -* Add tests that run vulture as a script. -* Add "python setup.py test" command for running tests. -* Add support for tox. -* Raise test coverage to 100%. -* Remove ez\_setup.py. +- Add tests that run vulture as a script. +- Add "python setup.py test" command for running tests. +- Add support for tox. +- Raise test coverage to 100%. +- Remove ez_setup.py. # 0.6 (2014-09-06) -* Ignore function names starting with "test\_". -* Parse variable names in new format strings (e.g. "This is +- Ignore function names starting with "test\_". +- Parse variable names in new format strings (e.g. "This is {x}".format(x="nice")). -* Only parse alphanumeric variable names in format strings and ignore +- Only parse alphanumeric variable names in format strings and ignore types. -* Abort with exit code 1 on syntax errors. -* Support installation under Windows by using setuptools (thanks +- Abort with exit code 1 on syntax errors. +- Support installation under Windows by using setuptools (thanks Reuben Fletcher-Costin). # 0.5 (2014-05-09) -* If dead code is found, exit with 1. +- If dead code is found, exit with 1. # 0.4.1 (2013-09-17) -* Only warn if a path given on the command line cannot be found. +- Only warn if a path given on the command line cannot be found. # 0.4 (2013-06-23) -* Ignore unused variables starting with an underscore. -* Show warning for syntax errors instead of aborting directly. -* Print warning if a file cannot be found. +- Ignore unused variables starting with an underscore. +- Show warning for syntax errors instead of aborting directly. +- Print warning if a file cannot be found. # 0.3 (2012-03-19) -* Add support for python3 -* Report unused attributes -* Find tuple assignments in comprehensions -* Scan files given on the command line even if they don't end with .py +- Add support for python3 +- Report unused attributes +- Find tuple assignments in comprehensions +- Scan files given on the command line even if they don't end with .py # 0.2 (2012-03-18) -* Only format nodes in verbose mode (gives 4x speedup). +- Only format nodes in verbose mode (gives 4x speedup). # 0.1 (2012-03-17) -* First release. +- First release. From 17193dd9316e22798d933845edd7c0005c25ebd3 Mon Sep 17 00:00:00 2001 From: Anuda Weerasinghe Date: Sat, 6 May 2023 18:54:24 -0400 Subject: [PATCH 09/14] fixes styling --- vulture/core.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vulture/core.py b/vulture/core.py index 145fa6c6..6a39e91e 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -219,7 +219,9 @@ def get_list(typ): self.code = [] self.found_dead_code_or_error = False - self.enum_class_vars = dict() # stores variables defined in enum classes + self.enum_class_vars = ( + dict() + ) # stores variables defined in enum classes def scan(self, code, filename=""): filename = Path(filename) @@ -619,9 +621,9 @@ def visit_ClassDef(self, node): self.enum_class_vars[newKey] = classVariables def _subclassesEnum(self, node): - ''' + """ Checks if a class has Enum as a superclass - ''' + """ for base in node.bases: if isinstance(base, ast.Name): if base.id.lower() == "enum": From 923692ec32bc7603a6f917d2ab202215ef837569 Mon Sep 17 00:00:00 2001 From: Anuda Weerasinghe Date: Sat, 6 May 2023 19:03:51 -0400 Subject: [PATCH 10/14] fixes changelog --- CHANGELOG.md | 272 +++++++++++++++++++++++++-------------------------- 1 file changed, 136 insertions(+), 136 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a044d2fb..0a61a922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,305 +1,305 @@ -- Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). -- Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). -- Fix false positive when iterating over `Enum` (anudaweerasinghe, pm3512, akanagal, ) +* Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). +* Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). +* Fix false positive when iterating over `Enum` (anudaweerasinghe, pm3512, addykan, #312) # 2.7 (2023-01-08) -- Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). -- Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). -- Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). -- Fix example in README file (Jendrik Seipp, #272). +* Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). +* Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). +* Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). +* Fix example in README file (Jendrik Seipp, #272). # 2.6 (2022-09-19) -- Add basic `match` statement support (kreathon, #276, #291). +* Add basic `match` statement support (kreathon, #276, #291). # 2.5 (2022-07-03) -- Mark imports in `__all__` as used (kreathon, #172, #282). -- Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). +* Mark imports in `__all__` as used (kreathon, #172, #282). +* Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). # 2.4 (2022-05-19) -- Print absolute filepaths as relative again (as in version 2.1 and before) +* Print absolute filepaths as relative again (as in version 2.1 and before) if they are below the current directory (The-Compiler, #246). -- Run tests and add PyPI trove for Python 3.10 (chayim, #266). -- Allow using the `del` keyword to mark unused variables (sshishov, #279). +* Run tests and add PyPI trove for Python 3.10 (chayim, #266). +* Allow using the `del` keyword to mark unused variables (sshishov, #279). # 2.3 (2021-01-16) -- Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). +* Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). # 2.2 (2021-01-15) -- Only parse format strings when being used with `locals()` (jingw, #225). -- Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). -- Run continuous integration tests for Python 3.9 (ju-sh, #232). -- Use pathlib internally (ju-sh, #226). +* Only parse format strings when being used with `locals()` (jingw, #225). +* Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). +* Run continuous integration tests for Python 3.9 (ju-sh, #232). +* Use pathlib internally (ju-sh, #226). # 2.1 (2020-08-19) -- Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to +* Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to `obj.constant_string` (jingw, #219). -- Fix false positives when assigning to `x.some_name` but reading via +* Fix false positives when assigning to `x.some_name` but reading via `some_name`, at the cost of potential false negatives (jingw, #221). -- Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). +* Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). # 2.0 (2020-08-11) -- Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). -- Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last +* Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). +* Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last Vulture release that supports Python 2.7 and Python 3.5 is version 1.6. -- Consider all files under `test` or `tests` directories test files +* Consider all files under `test` or `tests` directories test files (Jendrik Seipp). -- Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). +* Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). # 1.6 (2020-07-28) -- Differentiate between functions and methods (Jendrik Seipp, #112, #209). -- Move from Travis to GitHub actions (RJ722, #211). +* Differentiate between functions and methods (Jendrik Seipp, #112, #209). +* Move from Travis to GitHub actions (RJ722, #211). # 1.5 (2020-05-24) -- Support flake8 "noqa" error codes F401 (unused import) and F841 (unused +* Support flake8 "noqa" error codes F401 (unused import) and F841 (unused local variable) (RJ722, #195). -- Detect unreachable code in conditional expressions +* Detect unreachable code in conditional expressions (Agathiyan Bragadeesh, #178). # 1.4 (2020-03-30) -- Ignore unused import statements in `__init__.py` (RJ722, #192). -- Report first decorator's line number for unused decorated objects on +* Ignore unused import statements in `__init__.py` (RJ722, #192). +* Report first decorator's line number for unused decorated objects on Python 3.8+ (RJ722, #200). -- Check code with black and pyupgrade. +* Check code with black and pyupgrade. # 1.3 (2020-02-03) -- Detect redundant 'if' conditions without 'else' blocks. -- Add whitelist for `string.Formatter` (Joseph Bylund, #183). +* Detect redundant 'if' conditions without 'else' blocks. +* Add whitelist for `string.Formatter` (Joseph Bylund, #183). # 1.2 (2019-11-22) -- Fix tests for Python 3.8 (#166). -- Use new `Constant` AST node under Python 3.8+ (#175). -- Add test for f-strings (#177). -- Add whitelist for `logging` module. +* Fix tests for Python 3.8 (#166). +* Use new `Constant` AST node under Python 3.8+ (#175). +* Add test for f-strings (#177). +* Add whitelist for `logging` module. # 1.1 (2019-09-23) -- Add `sys.excepthook` to `sys` whitelist. -- Add whitelist for `ctypes` module. -- Check that type annotations are parsed and type comments are ignored +* Add `sys.excepthook` to `sys` whitelist. +* Add whitelist for `ctypes` module. +* Check that type annotations are parsed and type comments are ignored (thanks @kx-chen). -- Support checking files with BOM under Python 2.7 (#170). +* Support checking files with BOM under Python 2.7 (#170). # 1.0 (2018-10-23) -- Add `--ignore-decorators` flag (thanks @RJ722). -- Add whitelist for `threading` module (thanks @andrewhalle). +* Add `--ignore-decorators` flag (thanks @RJ722). +* Add whitelist for `threading` module (thanks @andrewhalle). # 0.29 (2018-07-31) -- Add `--ignore-names` flag for ignoring names matching the given glob +* Add `--ignore-names` flag for ignoring names matching the given glob patterns (thanks @RJ722). # 0.28 (2018-07-05) -- Add `--make-whitelist` flag for reporting output in whitelist format +* Add `--make-whitelist` flag for reporting output in whitelist format (thanks @RJ722). -- Ignore case of `--exclude` arguments on Windows. -- Add `*-test.py` to recognized test file patterns. -- Add `failureException`, `longMessage` and `maxDiff` to `unittest` +* Ignore case of `--exclude` arguments on Windows. +* Add `*-test.py` to recognized test file patterns. +* Add `failureException`, `longMessage` and `maxDiff` to `unittest` whitelist. -- Refer to actual objects rather than their mocks in default +* Refer to actual objects rather than their mocks in default whitelists (thanks @RJ722). -- Don't import any Vulture modules in setup.py (thanks @RJ722). +* Don't import any Vulture modules in setup.py (thanks @RJ722). # 0.27 (2018-06-05) -- Report `while (True): ... else: ...` as unreachable (thanks @RJ722). -- Use `argparse` instead of `optparse`. -- Whitelist Mock.return_value and Mock.side_effect in unittest.mock +* Report `while (True): ... else: ...` as unreachable (thanks @RJ722). +* Use `argparse` instead of `optparse`. +* Whitelist Mock.return\_value and Mock.side\_effect in unittest.mock module. -- Drop support for Python 2.6 and 3.3. -- Improve documentation and test coverage (thanks @RJ722). +* Drop support for Python 2.6 and 3.3. +* Improve documentation and test coverage (thanks @RJ722). # 0.26 (2017-08-28) -- Detect `async` function definitions (thanks @RJ722). -- Add `Item.get_report()` method (thanks @RJ722). -- Move method for finding Python modules out of Vulture class. +* Detect `async` function definitions (thanks @RJ722). +* Add `Item.get_report()` method (thanks @RJ722). +* Move method for finding Python modules out of Vulture class. # 0.25 (2017-08-15) -- Detect unsatisfiable statements containing `and`, `or` and `not`. -- Use filenames and line numbers as tie-breakers when sorting by size. -- Store first and last line numbers in Item objects. -- Pass relevant options directly to `scavenge()` and `report()`. +* Detect unsatisfiable statements containing `and`, `or` and `not`. +* Use filenames and line numbers as tie-breakers when sorting by size. +* Store first and last line numbers in Item objects. +* Pass relevant options directly to `scavenge()` and `report()`. # 0.24 (2017-08-14) -- Detect unsatisfiable `while`-conditions (thanks @RJ722). -- Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). -- Handle null bytes in source code. +* Detect unsatisfiable `while`-conditions (thanks @RJ722). +* Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). +* Handle null bytes in source code. # 0.23 (2017-08-10) -- Add `--min-confidence` flag (thanks @RJ722). +* Add `--min-confidence` flag (thanks @RJ722). # 0.22 (2017-08-04) -- Detect unreachable code after `return`, `break`, `continue` and +* Detect unreachable code after `return`, `break`, `continue` and `raise` (thanks @RJ722). -- Parse all variable and attribute names in new format strings. -- Extend ast whitelist. +* Parse all variable and attribute names in new format strings. +* Extend ast whitelist. # 0.21 (2017-07-26) -- If an unused item is defined multiple times, report it multiple +* If an unused item is defined multiple times, report it multiple times. -- Make size estimates for function calls more accurate. -- Create wheel files for Vulture (thanks @RJ722). +* Make size estimates for function calls more accurate. +* Create wheel files for Vulture (thanks @RJ722). # 0.20 (2017-07-26) -- Report unused tuple assignments as dead code. -- Report attribute names that have the same names as variables as dead +* Report unused tuple assignments as dead code. +* Report attribute names that have the same names as variables as dead code. -- Let Item class inherit from `object` (thanks @RJ722). -- Handle names imported as aliases like all other used variable names. -- Rename Vulture.used_vars to Vulture.used_names. -- Use function for determining which imports to ignore. -- Only try to import each whitelist file once. -- Store used names and used attributes in sets instead of lists. -- Fix estimating the size of code containing ellipses (...). -- Refactor and simplify code. +* Let Item class inherit from `object` (thanks @RJ722). +* Handle names imported as aliases like all other used variable names. +* Rename Vulture.used\_vars to Vulture.used\_names. +* Use function for determining which imports to ignore. +* Only try to import each whitelist file once. +* Store used names and used attributes in sets instead of lists. +* Fix estimating the size of code containing ellipses (...). +* Refactor and simplify code. # 0.19 (2017-07-20) -- Don't ignore \_\_foo variable names. -- Use separate methods for determining whether to ignore classes and +* Don't ignore \_\_foo variable names. +* Use separate methods for determining whether to ignore classes and functions. -- Only try to find a whitelist for each defined import once (thanks +* Only try to find a whitelist for each defined import once (thanks @roivanov). -- Fix finding the last child for many types of AST nodes. +* Fix finding the last child for many types of AST nodes. # 0.18 (2017-07-17) -- Make --sort-by-size faster and more +* Make --sort-by-size faster and more accurate (thanks @RJ722). # 0.17 (2017-07-17) -- Add get_unused_code() method. -- Return with exit code 1 when syntax errors are found or files can't +* Add get\_unused\_code() method. +* Return with exit code 1 when syntax errors are found or files can't be read. # 0.16 (2017-07-12) -- Differentiate between unused classes and functions (thanks @RJ722). -- Add --sort-by-size option (thanks @jackric and @RJ722). -- Count imports as used if they are accessed as module attributes. +* Differentiate between unused classes and functions (thanks @RJ722). +* Add --sort-by-size option (thanks @jackric and @RJ722). +* Count imports as used if they are accessed as module attributes. # 0.15 (2017-07-04) -- Automatically include whitelists based on imported modules (thanks +* Automatically include whitelists based on imported modules (thanks @RJ722). -- Add --version parameter (thanks @RJ722). -- Add appveyor tests for testing on Windows (thanks @RJ722). +* Add --version parameter (thanks @RJ722). +* Add appveyor tests for testing on Windows (thanks @RJ722). # 0.14 (2017-04-06) -- Add stub whitelist file for Python standard library (thanks @RJ722) -- Ignore class names starting with "Test" in "test\_" files (thanks +* Add stub whitelist file for Python standard library (thanks @RJ722) +* Ignore class names starting with "Test" in "test\_" files (thanks @thisch). -- Ignore "test\_" functions only in "test\_" files. +* Ignore "test\_" functions only in "test\_" files. # 0.13 (2017-03-06) -- Ignore star-imported names since we cannot detect whether they are +* Ignore star-imported names since we cannot detect whether they are used. -- Move repository to GitHub. +* Move repository to GitHub. # 0.12 (2017-01-05) -- Detect unused imports. -- Use tokenize.open() on Python \>= 3.2 for reading input files, +* Detect unused imports. +* Use tokenize.open() on Python \>= 3.2 for reading input files, assume UTF-8 encoding on older Python versions. # 0.11 (2016-11-27) -- Use the system's default encoding when reading files. -- Report syntax errors instead of aborting. +* Use the system's default encoding when reading files. +* Report syntax errors instead of aborting. # 0.10 (2016-07-14) -- Detect unused function and method arguments (issue #15). -- Detect unused \*args and \*\*kwargs parameters. -- Change license from GPL to MIT. +* Detect unused function and method arguments (issue #15). +* Detect unused \*args and \*\*kwargs parameters. +* Change license from GPL to MIT. # 0.9 (2016-06-29) -- Don't flag attributes as unused if they are used as global variables +* Don't flag attributes as unused if they are used as global variables in another module (thanks Florian Bruhin). -- Don't consider "True" and "False" variable names. -- Abort with error message when invoked on .pyc files. +* Don't consider "True" and "False" variable names. +* Abort with error message when invoked on .pyc files. # 0.8.1 (2015-09-28) -- Fix code for Python 3. +* Fix code for Python 3. # 0.8 (2015-09-28) -- Do not flag names imported with "import as" as dead code (thanks Tom +* Do not flag names imported with "import as" as dead code (thanks Tom Terrace). # 0.7 (2015-09-26) -- Exit with exitcode 1 if path on commandline can't be found. -- Test vulture with vulture using a whitelist module for false +* Exit with exitcode 1 if path on commandline can't be found. +* Test vulture with vulture using a whitelist module for false positives. -- Add tests that run vulture as a script. -- Add "python setup.py test" command for running tests. -- Add support for tox. -- Raise test coverage to 100%. -- Remove ez_setup.py. +* Add tests that run vulture as a script. +* Add "python setup.py test" command for running tests. +* Add support for tox. +* Raise test coverage to 100%. +* Remove ez\_setup.py. # 0.6 (2014-09-06) -- Ignore function names starting with "test\_". -- Parse variable names in new format strings (e.g. "This is +* Ignore function names starting with "test\_". +* Parse variable names in new format strings (e.g. "This is {x}".format(x="nice")). -- Only parse alphanumeric variable names in format strings and ignore +* Only parse alphanumeric variable names in format strings and ignore types. -- Abort with exit code 1 on syntax errors. -- Support installation under Windows by using setuptools (thanks +* Abort with exit code 1 on syntax errors. +* Support installation under Windows by using setuptools (thanks Reuben Fletcher-Costin). # 0.5 (2014-05-09) -- If dead code is found, exit with 1. +* If dead code is found, exit with 1. # 0.4.1 (2013-09-17) -- Only warn if a path given on the command line cannot be found. +* Only warn if a path given on the command line cannot be found. # 0.4 (2013-06-23) -- Ignore unused variables starting with an underscore. -- Show warning for syntax errors instead of aborting directly. -- Print warning if a file cannot be found. +* Ignore unused variables starting with an underscore. +* Show warning for syntax errors instead of aborting directly. +* Print warning if a file cannot be found. # 0.3 (2012-03-19) -- Add support for python3 -- Report unused attributes -- Find tuple assignments in comprehensions -- Scan files given on the command line even if they don't end with .py +* Add support for python3 +* Report unused attributes +* Find tuple assignments in comprehensions +* Scan files given on the command line even if they don't end with .py # 0.2 (2012-03-18) -- Only format nodes in verbose mode (gives 4x speedup). +* Only format nodes in verbose mode (gives 4x speedup). # 0.1 (2012-03-17) -- First release. +* First release. \ No newline at end of file From 33b76910b030c5f6896cec48318431867951d4e5 Mon Sep 17 00:00:00 2001 From: pm3512 Date: Sat, 6 May 2023 23:20:59 -0400 Subject: [PATCH 11/14] added more generic is_subclass function --- vulture/core.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/vulture/core.py b/vulture/core.py index b5a74b9f..2c46dc03 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -595,6 +595,21 @@ def _is_locals_call(node): and not node.keywords ) + @staticmethod + def _is_subclass(node, class_name): + """Return True if the node is a subclass of the given class.""" + if not isinstance(node, ast.ClassDef): + return False + for superclass in node.bases: + if ( + isinstance(superclass, ast.Name) + and superclass.id == class_name + or isinstance(superclass, ast.Attribute) + and superclass.attr == class_name + ): + return True + return False + def visit_ClassDef(self, node): for decorator in node.decorator_list: if _match( @@ -608,7 +623,7 @@ def visit_ClassDef(self, node): self._define( self.defined_classes, node.name, node, ignore=_ignore_class ) - if self._subclassesEnum(node): + if self._is_subclass(node, "Enum"): newKey = node.name classVariables = [] for stmt in node.body: @@ -617,16 +632,6 @@ def visit_ClassDef(self, node): classVariables.append(target.id) self.enum_class_vars[newKey] = classVariables - def _subclassesEnum(self, node): - for base in node.bases: - if isinstance(base, ast.Name): - if base.id.lower() == "enum": - return True - elif isinstance(base, ast.Attribute): - if base.value.id.lower() == "enum": - return True - return False - def visit_FunctionDef(self, node): decorator_names = [ utils.get_decorator_name(decorator) From 922772752efd150ee5840ca52b2b923de06f6963 Mon Sep 17 00:00:00 2001 From: Anuda Weerasinghe Date: Sun, 7 May 2023 00:02:59 -0400 Subject: [PATCH 12/14] fixes issue number in changelog --- CHANGELOG.md | 272 +++++++++++++++++++++++++-------------------------- 1 file changed, 136 insertions(+), 136 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a61a922..627cdd87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,305 +1,305 @@ -* Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). -* Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). -* Fix false positive when iterating over `Enum` (anudaweerasinghe, pm3512, addykan, #312) +- Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). +- Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). +- Fix false positive when iterating over `Enum` (anudaweerasinghe, pm3512, addykan, #304) # 2.7 (2023-01-08) -* Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). -* Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). -* Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). -* Fix example in README file (Jendrik Seipp, #272). +- Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). +- Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). +- Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). +- Fix example in README file (Jendrik Seipp, #272). # 2.6 (2022-09-19) -* Add basic `match` statement support (kreathon, #276, #291). +- Add basic `match` statement support (kreathon, #276, #291). # 2.5 (2022-07-03) -* Mark imports in `__all__` as used (kreathon, #172, #282). -* Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). +- Mark imports in `__all__` as used (kreathon, #172, #282). +- Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). # 2.4 (2022-05-19) -* Print absolute filepaths as relative again (as in version 2.1 and before) +- Print absolute filepaths as relative again (as in version 2.1 and before) if they are below the current directory (The-Compiler, #246). -* Run tests and add PyPI trove for Python 3.10 (chayim, #266). -* Allow using the `del` keyword to mark unused variables (sshishov, #279). +- Run tests and add PyPI trove for Python 3.10 (chayim, #266). +- Allow using the `del` keyword to mark unused variables (sshishov, #279). # 2.3 (2021-01-16) -* Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). +- Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). # 2.2 (2021-01-15) -* Only parse format strings when being used with `locals()` (jingw, #225). -* Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). -* Run continuous integration tests for Python 3.9 (ju-sh, #232). -* Use pathlib internally (ju-sh, #226). +- Only parse format strings when being used with `locals()` (jingw, #225). +- Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). +- Run continuous integration tests for Python 3.9 (ju-sh, #232). +- Use pathlib internally (ju-sh, #226). # 2.1 (2020-08-19) -* Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to +- Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to `obj.constant_string` (jingw, #219). -* Fix false positives when assigning to `x.some_name` but reading via +- Fix false positives when assigning to `x.some_name` but reading via `some_name`, at the cost of potential false negatives (jingw, #221). -* Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). +- Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). # 2.0 (2020-08-11) -* Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). -* Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last +- Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). +- Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last Vulture release that supports Python 2.7 and Python 3.5 is version 1.6. -* Consider all files under `test` or `tests` directories test files +- Consider all files under `test` or `tests` directories test files (Jendrik Seipp). -* Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). +- Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). # 1.6 (2020-07-28) -* Differentiate between functions and methods (Jendrik Seipp, #112, #209). -* Move from Travis to GitHub actions (RJ722, #211). +- Differentiate between functions and methods (Jendrik Seipp, #112, #209). +- Move from Travis to GitHub actions (RJ722, #211). # 1.5 (2020-05-24) -* Support flake8 "noqa" error codes F401 (unused import) and F841 (unused +- Support flake8 "noqa" error codes F401 (unused import) and F841 (unused local variable) (RJ722, #195). -* Detect unreachable code in conditional expressions +- Detect unreachable code in conditional expressions (Agathiyan Bragadeesh, #178). # 1.4 (2020-03-30) -* Ignore unused import statements in `__init__.py` (RJ722, #192). -* Report first decorator's line number for unused decorated objects on +- Ignore unused import statements in `__init__.py` (RJ722, #192). +- Report first decorator's line number for unused decorated objects on Python 3.8+ (RJ722, #200). -* Check code with black and pyupgrade. +- Check code with black and pyupgrade. # 1.3 (2020-02-03) -* Detect redundant 'if' conditions without 'else' blocks. -* Add whitelist for `string.Formatter` (Joseph Bylund, #183). +- Detect redundant 'if' conditions without 'else' blocks. +- Add whitelist for `string.Formatter` (Joseph Bylund, #183). # 1.2 (2019-11-22) -* Fix tests for Python 3.8 (#166). -* Use new `Constant` AST node under Python 3.8+ (#175). -* Add test for f-strings (#177). -* Add whitelist for `logging` module. +- Fix tests for Python 3.8 (#166). +- Use new `Constant` AST node under Python 3.8+ (#175). +- Add test for f-strings (#177). +- Add whitelist for `logging` module. # 1.1 (2019-09-23) -* Add `sys.excepthook` to `sys` whitelist. -* Add whitelist for `ctypes` module. -* Check that type annotations are parsed and type comments are ignored +- Add `sys.excepthook` to `sys` whitelist. +- Add whitelist for `ctypes` module. +- Check that type annotations are parsed and type comments are ignored (thanks @kx-chen). -* Support checking files with BOM under Python 2.7 (#170). +- Support checking files with BOM under Python 2.7 (#170). # 1.0 (2018-10-23) -* Add `--ignore-decorators` flag (thanks @RJ722). -* Add whitelist for `threading` module (thanks @andrewhalle). +- Add `--ignore-decorators` flag (thanks @RJ722). +- Add whitelist for `threading` module (thanks @andrewhalle). # 0.29 (2018-07-31) -* Add `--ignore-names` flag for ignoring names matching the given glob +- Add `--ignore-names` flag for ignoring names matching the given glob patterns (thanks @RJ722). # 0.28 (2018-07-05) -* Add `--make-whitelist` flag for reporting output in whitelist format +- Add `--make-whitelist` flag for reporting output in whitelist format (thanks @RJ722). -* Ignore case of `--exclude` arguments on Windows. -* Add `*-test.py` to recognized test file patterns. -* Add `failureException`, `longMessage` and `maxDiff` to `unittest` +- Ignore case of `--exclude` arguments on Windows. +- Add `*-test.py` to recognized test file patterns. +- Add `failureException`, `longMessage` and `maxDiff` to `unittest` whitelist. -* Refer to actual objects rather than their mocks in default +- Refer to actual objects rather than their mocks in default whitelists (thanks @RJ722). -* Don't import any Vulture modules in setup.py (thanks @RJ722). +- Don't import any Vulture modules in setup.py (thanks @RJ722). # 0.27 (2018-06-05) -* Report `while (True): ... else: ...` as unreachable (thanks @RJ722). -* Use `argparse` instead of `optparse`. -* Whitelist Mock.return\_value and Mock.side\_effect in unittest.mock +- Report `while (True): ... else: ...` as unreachable (thanks @RJ722). +- Use `argparse` instead of `optparse`. +- Whitelist Mock.return_value and Mock.side_effect in unittest.mock module. -* Drop support for Python 2.6 and 3.3. -* Improve documentation and test coverage (thanks @RJ722). +- Drop support for Python 2.6 and 3.3. +- Improve documentation and test coverage (thanks @RJ722). # 0.26 (2017-08-28) -* Detect `async` function definitions (thanks @RJ722). -* Add `Item.get_report()` method (thanks @RJ722). -* Move method for finding Python modules out of Vulture class. +- Detect `async` function definitions (thanks @RJ722). +- Add `Item.get_report()` method (thanks @RJ722). +- Move method for finding Python modules out of Vulture class. # 0.25 (2017-08-15) -* Detect unsatisfiable statements containing `and`, `or` and `not`. -* Use filenames and line numbers as tie-breakers when sorting by size. -* Store first and last line numbers in Item objects. -* Pass relevant options directly to `scavenge()` and `report()`. +- Detect unsatisfiable statements containing `and`, `or` and `not`. +- Use filenames and line numbers as tie-breakers when sorting by size. +- Store first and last line numbers in Item objects. +- Pass relevant options directly to `scavenge()` and `report()`. # 0.24 (2017-08-14) -* Detect unsatisfiable `while`-conditions (thanks @RJ722). -* Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). -* Handle null bytes in source code. +- Detect unsatisfiable `while`-conditions (thanks @RJ722). +- Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). +- Handle null bytes in source code. # 0.23 (2017-08-10) -* Add `--min-confidence` flag (thanks @RJ722). +- Add `--min-confidence` flag (thanks @RJ722). # 0.22 (2017-08-04) -* Detect unreachable code after `return`, `break`, `continue` and +- Detect unreachable code after `return`, `break`, `continue` and `raise` (thanks @RJ722). -* Parse all variable and attribute names in new format strings. -* Extend ast whitelist. +- Parse all variable and attribute names in new format strings. +- Extend ast whitelist. # 0.21 (2017-07-26) -* If an unused item is defined multiple times, report it multiple +- If an unused item is defined multiple times, report it multiple times. -* Make size estimates for function calls more accurate. -* Create wheel files for Vulture (thanks @RJ722). +- Make size estimates for function calls more accurate. +- Create wheel files for Vulture (thanks @RJ722). # 0.20 (2017-07-26) -* Report unused tuple assignments as dead code. -* Report attribute names that have the same names as variables as dead +- Report unused tuple assignments as dead code. +- Report attribute names that have the same names as variables as dead code. -* Let Item class inherit from `object` (thanks @RJ722). -* Handle names imported as aliases like all other used variable names. -* Rename Vulture.used\_vars to Vulture.used\_names. -* Use function for determining which imports to ignore. -* Only try to import each whitelist file once. -* Store used names and used attributes in sets instead of lists. -* Fix estimating the size of code containing ellipses (...). -* Refactor and simplify code. +- Let Item class inherit from `object` (thanks @RJ722). +- Handle names imported as aliases like all other used variable names. +- Rename Vulture.used_vars to Vulture.used_names. +- Use function for determining which imports to ignore. +- Only try to import each whitelist file once. +- Store used names and used attributes in sets instead of lists. +- Fix estimating the size of code containing ellipses (...). +- Refactor and simplify code. # 0.19 (2017-07-20) -* Don't ignore \_\_foo variable names. -* Use separate methods for determining whether to ignore classes and +- Don't ignore \_\_foo variable names. +- Use separate methods for determining whether to ignore classes and functions. -* Only try to find a whitelist for each defined import once (thanks +- Only try to find a whitelist for each defined import once (thanks @roivanov). -* Fix finding the last child for many types of AST nodes. +- Fix finding the last child for many types of AST nodes. # 0.18 (2017-07-17) -* Make --sort-by-size faster and more +- Make --sort-by-size faster and more accurate (thanks @RJ722). # 0.17 (2017-07-17) -* Add get\_unused\_code() method. -* Return with exit code 1 when syntax errors are found or files can't +- Add get_unused_code() method. +- Return with exit code 1 when syntax errors are found or files can't be read. # 0.16 (2017-07-12) -* Differentiate between unused classes and functions (thanks @RJ722). -* Add --sort-by-size option (thanks @jackric and @RJ722). -* Count imports as used if they are accessed as module attributes. +- Differentiate between unused classes and functions (thanks @RJ722). +- Add --sort-by-size option (thanks @jackric and @RJ722). +- Count imports as used if they are accessed as module attributes. # 0.15 (2017-07-04) -* Automatically include whitelists based on imported modules (thanks +- Automatically include whitelists based on imported modules (thanks @RJ722). -* Add --version parameter (thanks @RJ722). -* Add appveyor tests for testing on Windows (thanks @RJ722). +- Add --version parameter (thanks @RJ722). +- Add appveyor tests for testing on Windows (thanks @RJ722). # 0.14 (2017-04-06) -* Add stub whitelist file for Python standard library (thanks @RJ722) -* Ignore class names starting with "Test" in "test\_" files (thanks +- Add stub whitelist file for Python standard library (thanks @RJ722) +- Ignore class names starting with "Test" in "test\_" files (thanks @thisch). -* Ignore "test\_" functions only in "test\_" files. +- Ignore "test\_" functions only in "test\_" files. # 0.13 (2017-03-06) -* Ignore star-imported names since we cannot detect whether they are +- Ignore star-imported names since we cannot detect whether they are used. -* Move repository to GitHub. +- Move repository to GitHub. # 0.12 (2017-01-05) -* Detect unused imports. -* Use tokenize.open() on Python \>= 3.2 for reading input files, +- Detect unused imports. +- Use tokenize.open() on Python \>= 3.2 for reading input files, assume UTF-8 encoding on older Python versions. # 0.11 (2016-11-27) -* Use the system's default encoding when reading files. -* Report syntax errors instead of aborting. +- Use the system's default encoding when reading files. +- Report syntax errors instead of aborting. # 0.10 (2016-07-14) -* Detect unused function and method arguments (issue #15). -* Detect unused \*args and \*\*kwargs parameters. -* Change license from GPL to MIT. +- Detect unused function and method arguments (issue #15). +- Detect unused \*args and \*\*kwargs parameters. +- Change license from GPL to MIT. # 0.9 (2016-06-29) -* Don't flag attributes as unused if they are used as global variables +- Don't flag attributes as unused if they are used as global variables in another module (thanks Florian Bruhin). -* Don't consider "True" and "False" variable names. -* Abort with error message when invoked on .pyc files. +- Don't consider "True" and "False" variable names. +- Abort with error message when invoked on .pyc files. # 0.8.1 (2015-09-28) -* Fix code for Python 3. +- Fix code for Python 3. # 0.8 (2015-09-28) -* Do not flag names imported with "import as" as dead code (thanks Tom +- Do not flag names imported with "import as" as dead code (thanks Tom Terrace). # 0.7 (2015-09-26) -* Exit with exitcode 1 if path on commandline can't be found. -* Test vulture with vulture using a whitelist module for false +- Exit with exitcode 1 if path on commandline can't be found. +- Test vulture with vulture using a whitelist module for false positives. -* Add tests that run vulture as a script. -* Add "python setup.py test" command for running tests. -* Add support for tox. -* Raise test coverage to 100%. -* Remove ez\_setup.py. +- Add tests that run vulture as a script. +- Add "python setup.py test" command for running tests. +- Add support for tox. +- Raise test coverage to 100%. +- Remove ez_setup.py. # 0.6 (2014-09-06) -* Ignore function names starting with "test\_". -* Parse variable names in new format strings (e.g. "This is +- Ignore function names starting with "test\_". +- Parse variable names in new format strings (e.g. "This is {x}".format(x="nice")). -* Only parse alphanumeric variable names in format strings and ignore +- Only parse alphanumeric variable names in format strings and ignore types. -* Abort with exit code 1 on syntax errors. -* Support installation under Windows by using setuptools (thanks +- Abort with exit code 1 on syntax errors. +- Support installation under Windows by using setuptools (thanks Reuben Fletcher-Costin). # 0.5 (2014-05-09) -* If dead code is found, exit with 1. +- If dead code is found, exit with 1. # 0.4.1 (2013-09-17) -* Only warn if a path given on the command line cannot be found. +- Only warn if a path given on the command line cannot be found. # 0.4 (2013-06-23) -* Ignore unused variables starting with an underscore. -* Show warning for syntax errors instead of aborting directly. -* Print warning if a file cannot be found. +- Ignore unused variables starting with an underscore. +- Show warning for syntax errors instead of aborting directly. +- Print warning if a file cannot be found. # 0.3 (2012-03-19) -* Add support for python3 -* Report unused attributes -* Find tuple assignments in comprehensions -* Scan files given on the command line even if they don't end with .py +- Add support for python3 +- Report unused attributes +- Find tuple assignments in comprehensions +- Scan files given on the command line even if they don't end with .py # 0.2 (2012-03-18) -* Only format nodes in verbose mode (gives 4x speedup). +- Only format nodes in verbose mode (gives 4x speedup). # 0.1 (2012-03-17) -* First release. \ No newline at end of file +- First release. From 0ffb902a12b8267f5d6d363e4c9cf3e6159cb82d Mon Sep 17 00:00:00 2001 From: Anuda Weerasinghe Date: Sun, 7 May 2023 00:03:27 -0400 Subject: [PATCH 13/14] fixes changelog --- CHANGELOG.md | 272 +++++++++++++++++++++++++-------------------------- 1 file changed, 136 insertions(+), 136 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 627cdd87..8e7a0b4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,305 +1,305 @@ -- Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). -- Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). -- Fix false positive when iterating over `Enum` (anudaweerasinghe, pm3512, addykan, #304) +* Add `UnicodeEncodeError` exception handling to `core.py` (milanbalazs, #299). +* Add whitelist for `Enum` attributes `_name_` and `_value_` (Eugene Toder, #305). +* Fix false positive when iterating over `Enum` (anudaweerasinghe, pm3512, addykan, #304) # 2.7 (2023-01-08) -- Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). -- Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). -- Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). -- Fix example in README file (Jendrik Seipp, #272). +* Ignore `setup_module()`, `teardown_module()`, etc. in pytest `test_*.py` files (Jendrik Seipp). +* Add whitelist for `socketserver.TCPServer.allow_reuse_address` (Ben Elliston). +* Clarify that `--exclude` patterns are matched against absolute paths (Jendrik Seipp, #260). +* Fix example in README file (Jendrik Seipp, #272). # 2.6 (2022-09-19) -- Add basic `match` statement support (kreathon, #276, #291). +* Add basic `match` statement support (kreathon, #276, #291). # 2.5 (2022-07-03) -- Mark imports in `__all__` as used (kreathon, #172, #282). -- Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). +* Mark imports in `__all__` as used (kreathon, #172, #282). +* Add whitelist for `pint.UnitRegistry.default_formatter` (Ben Elliston, #258). # 2.4 (2022-05-19) -- Print absolute filepaths as relative again (as in version 2.1 and before) +* Print absolute filepaths as relative again (as in version 2.1 and before) if they are below the current directory (The-Compiler, #246). -- Run tests and add PyPI trove for Python 3.10 (chayim, #266). -- Allow using the `del` keyword to mark unused variables (sshishov, #279). +* Run tests and add PyPI trove for Python 3.10 (chayim, #266). +* Allow using the `del` keyword to mark unused variables (sshishov, #279). # 2.3 (2021-01-16) -- Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). +* Add [pre-commit](https://pre-commit.com) hook (Clément Robert, #244). # 2.2 (2021-01-15) -- Only parse format strings when being used with `locals()` (jingw, #225). -- Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). -- Run continuous integration tests for Python 3.9 (ju-sh, #232). -- Use pathlib internally (ju-sh, #226). +* Only parse format strings when being used with `locals()` (jingw, #225). +* Don't override paths in pyproject.toml with empty CLI paths (bcbnz, #228). +* Run continuous integration tests for Python 3.9 (ju-sh, #232). +* Use pathlib internally (ju-sh, #226). # 2.1 (2020-08-19) -- Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to +* Treat `getattr/hasattr(obj, "constant_string", ...)` as a reference to `obj.constant_string` (jingw, #219). -- Fix false positives when assigning to `x.some_name` but reading via +* Fix false positives when assigning to `x.some_name` but reading via `some_name`, at the cost of potential false negatives (jingw, #221). -- Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). +* Allow reading options from `pyproject.toml` (Michel Albert, #164, #215). # 2.0 (2020-08-11) -- Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). -- Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last +* Parse `# type: ...` comments if on Python 3.8+ (jingw, #220). +* Bump minimum Python version to 3.6 (Jendrik Seipp, #218). The last Vulture release that supports Python 2.7 and Python 3.5 is version 1.6. -- Consider all files under `test` or `tests` directories test files +* Consider all files under `test` or `tests` directories test files (Jendrik Seipp). -- Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). +* Ignore `logging.Logger.propagate` attribute (Jendrik Seipp). # 1.6 (2020-07-28) -- Differentiate between functions and methods (Jendrik Seipp, #112, #209). -- Move from Travis to GitHub actions (RJ722, #211). +* Differentiate between functions and methods (Jendrik Seipp, #112, #209). +* Move from Travis to GitHub actions (RJ722, #211). # 1.5 (2020-05-24) -- Support flake8 "noqa" error codes F401 (unused import) and F841 (unused +* Support flake8 "noqa" error codes F401 (unused import) and F841 (unused local variable) (RJ722, #195). -- Detect unreachable code in conditional expressions +* Detect unreachable code in conditional expressions (Agathiyan Bragadeesh, #178). # 1.4 (2020-03-30) -- Ignore unused import statements in `__init__.py` (RJ722, #192). -- Report first decorator's line number for unused decorated objects on +* Ignore unused import statements in `__init__.py` (RJ722, #192). +* Report first decorator's line number for unused decorated objects on Python 3.8+ (RJ722, #200). -- Check code with black and pyupgrade. +* Check code with black and pyupgrade. # 1.3 (2020-02-03) -- Detect redundant 'if' conditions without 'else' blocks. -- Add whitelist for `string.Formatter` (Joseph Bylund, #183). +* Detect redundant 'if' conditions without 'else' blocks. +* Add whitelist for `string.Formatter` (Joseph Bylund, #183). # 1.2 (2019-11-22) -- Fix tests for Python 3.8 (#166). -- Use new `Constant` AST node under Python 3.8+ (#175). -- Add test for f-strings (#177). -- Add whitelist for `logging` module. +* Fix tests for Python 3.8 (#166). +* Use new `Constant` AST node under Python 3.8+ (#175). +* Add test for f-strings (#177). +* Add whitelist for `logging` module. # 1.1 (2019-09-23) -- Add `sys.excepthook` to `sys` whitelist. -- Add whitelist for `ctypes` module. -- Check that type annotations are parsed and type comments are ignored +* Add `sys.excepthook` to `sys` whitelist. +* Add whitelist for `ctypes` module. +* Check that type annotations are parsed and type comments are ignored (thanks @kx-chen). -- Support checking files with BOM under Python 2.7 (#170). +* Support checking files with BOM under Python 2.7 (#170). # 1.0 (2018-10-23) -- Add `--ignore-decorators` flag (thanks @RJ722). -- Add whitelist for `threading` module (thanks @andrewhalle). +* Add `--ignore-decorators` flag (thanks @RJ722). +* Add whitelist for `threading` module (thanks @andrewhalle). # 0.29 (2018-07-31) -- Add `--ignore-names` flag for ignoring names matching the given glob +* Add `--ignore-names` flag for ignoring names matching the given glob patterns (thanks @RJ722). # 0.28 (2018-07-05) -- Add `--make-whitelist` flag for reporting output in whitelist format +* Add `--make-whitelist` flag for reporting output in whitelist format (thanks @RJ722). -- Ignore case of `--exclude` arguments on Windows. -- Add `*-test.py` to recognized test file patterns. -- Add `failureException`, `longMessage` and `maxDiff` to `unittest` +* Ignore case of `--exclude` arguments on Windows. +* Add `*-test.py` to recognized test file patterns. +* Add `failureException`, `longMessage` and `maxDiff` to `unittest` whitelist. -- Refer to actual objects rather than their mocks in default +* Refer to actual objects rather than their mocks in default whitelists (thanks @RJ722). -- Don't import any Vulture modules in setup.py (thanks @RJ722). +* Don't import any Vulture modules in setup.py (thanks @RJ722). # 0.27 (2018-06-05) -- Report `while (True): ... else: ...` as unreachable (thanks @RJ722). -- Use `argparse` instead of `optparse`. -- Whitelist Mock.return_value and Mock.side_effect in unittest.mock +* Report `while (True): ... else: ...` as unreachable (thanks @RJ722). +* Use `argparse` instead of `optparse`. +* Whitelist Mock.return\_value and Mock.side\_effect in unittest.mock module. -- Drop support for Python 2.6 and 3.3. -- Improve documentation and test coverage (thanks @RJ722). +* Drop support for Python 2.6 and 3.3. +* Improve documentation and test coverage (thanks @RJ722). # 0.26 (2017-08-28) -- Detect `async` function definitions (thanks @RJ722). -- Add `Item.get_report()` method (thanks @RJ722). -- Move method for finding Python modules out of Vulture class. +* Detect `async` function definitions (thanks @RJ722). +* Add `Item.get_report()` method (thanks @RJ722). +* Move method for finding Python modules out of Vulture class. # 0.25 (2017-08-15) -- Detect unsatisfiable statements containing `and`, `or` and `not`. -- Use filenames and line numbers as tie-breakers when sorting by size. -- Store first and last line numbers in Item objects. -- Pass relevant options directly to `scavenge()` and `report()`. +* Detect unsatisfiable statements containing `and`, `or` and `not`. +* Use filenames and line numbers as tie-breakers when sorting by size. +* Store first and last line numbers in Item objects. +* Pass relevant options directly to `scavenge()` and `report()`. # 0.24 (2017-08-14) -- Detect unsatisfiable `while`-conditions (thanks @RJ722). -- Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). -- Handle null bytes in source code. +* Detect unsatisfiable `while`-conditions (thanks @RJ722). +* Detect unsatisfiable `if`- and `else`-conditions (thanks @RJ722). +* Handle null bytes in source code. # 0.23 (2017-08-10) -- Add `--min-confidence` flag (thanks @RJ722). +* Add `--min-confidence` flag (thanks @RJ722). # 0.22 (2017-08-04) -- Detect unreachable code after `return`, `break`, `continue` and +* Detect unreachable code after `return`, `break`, `continue` and `raise` (thanks @RJ722). -- Parse all variable and attribute names in new format strings. -- Extend ast whitelist. +* Parse all variable and attribute names in new format strings. +* Extend ast whitelist. # 0.21 (2017-07-26) -- If an unused item is defined multiple times, report it multiple +* If an unused item is defined multiple times, report it multiple times. -- Make size estimates for function calls more accurate. -- Create wheel files for Vulture (thanks @RJ722). +* Make size estimates for function calls more accurate. +* Create wheel files for Vulture (thanks @RJ722). # 0.20 (2017-07-26) -- Report unused tuple assignments as dead code. -- Report attribute names that have the same names as variables as dead +* Report unused tuple assignments as dead code. +* Report attribute names that have the same names as variables as dead code. -- Let Item class inherit from `object` (thanks @RJ722). -- Handle names imported as aliases like all other used variable names. -- Rename Vulture.used_vars to Vulture.used_names. -- Use function for determining which imports to ignore. -- Only try to import each whitelist file once. -- Store used names and used attributes in sets instead of lists. -- Fix estimating the size of code containing ellipses (...). -- Refactor and simplify code. +* Let Item class inherit from `object` (thanks @RJ722). +* Handle names imported as aliases like all other used variable names. +* Rename Vulture.used\_vars to Vulture.used\_names. +* Use function for determining which imports to ignore. +* Only try to import each whitelist file once. +* Store used names and used attributes in sets instead of lists. +* Fix estimating the size of code containing ellipses (...). +* Refactor and simplify code. # 0.19 (2017-07-20) -- Don't ignore \_\_foo variable names. -- Use separate methods for determining whether to ignore classes and +* Don't ignore \_\_foo variable names. +* Use separate methods for determining whether to ignore classes and functions. -- Only try to find a whitelist for each defined import once (thanks +* Only try to find a whitelist for each defined import once (thanks @roivanov). -- Fix finding the last child for many types of AST nodes. +* Fix finding the last child for many types of AST nodes. # 0.18 (2017-07-17) -- Make --sort-by-size faster and more +* Make --sort-by-size faster and more accurate (thanks @RJ722). # 0.17 (2017-07-17) -- Add get_unused_code() method. -- Return with exit code 1 when syntax errors are found or files can't +* Add get\_unused\_code() method. +* Return with exit code 1 when syntax errors are found or files can't be read. # 0.16 (2017-07-12) -- Differentiate between unused classes and functions (thanks @RJ722). -- Add --sort-by-size option (thanks @jackric and @RJ722). -- Count imports as used if they are accessed as module attributes. +* Differentiate between unused classes and functions (thanks @RJ722). +* Add --sort-by-size option (thanks @jackric and @RJ722). +* Count imports as used if they are accessed as module attributes. # 0.15 (2017-07-04) -- Automatically include whitelists based on imported modules (thanks +* Automatically include whitelists based on imported modules (thanks @RJ722). -- Add --version parameter (thanks @RJ722). -- Add appveyor tests for testing on Windows (thanks @RJ722). +* Add --version parameter (thanks @RJ722). +* Add appveyor tests for testing on Windows (thanks @RJ722). # 0.14 (2017-04-06) -- Add stub whitelist file for Python standard library (thanks @RJ722) -- Ignore class names starting with "Test" in "test\_" files (thanks +* Add stub whitelist file for Python standard library (thanks @RJ722) +* Ignore class names starting with "Test" in "test\_" files (thanks @thisch). -- Ignore "test\_" functions only in "test\_" files. +* Ignore "test\_" functions only in "test\_" files. # 0.13 (2017-03-06) -- Ignore star-imported names since we cannot detect whether they are +* Ignore star-imported names since we cannot detect whether they are used. -- Move repository to GitHub. +* Move repository to GitHub. # 0.12 (2017-01-05) -- Detect unused imports. -- Use tokenize.open() on Python \>= 3.2 for reading input files, +* Detect unused imports. +* Use tokenize.open() on Python \>= 3.2 for reading input files, assume UTF-8 encoding on older Python versions. # 0.11 (2016-11-27) -- Use the system's default encoding when reading files. -- Report syntax errors instead of aborting. +* Use the system's default encoding when reading files. +* Report syntax errors instead of aborting. # 0.10 (2016-07-14) -- Detect unused function and method arguments (issue #15). -- Detect unused \*args and \*\*kwargs parameters. -- Change license from GPL to MIT. +* Detect unused function and method arguments (issue #15). +* Detect unused \*args and \*\*kwargs parameters. +* Change license from GPL to MIT. # 0.9 (2016-06-29) -- Don't flag attributes as unused if they are used as global variables +* Don't flag attributes as unused if they are used as global variables in another module (thanks Florian Bruhin). -- Don't consider "True" and "False" variable names. -- Abort with error message when invoked on .pyc files. +* Don't consider "True" and "False" variable names. +* Abort with error message when invoked on .pyc files. # 0.8.1 (2015-09-28) -- Fix code for Python 3. +* Fix code for Python 3. # 0.8 (2015-09-28) -- Do not flag names imported with "import as" as dead code (thanks Tom +* Do not flag names imported with "import as" as dead code (thanks Tom Terrace). # 0.7 (2015-09-26) -- Exit with exitcode 1 if path on commandline can't be found. -- Test vulture with vulture using a whitelist module for false +* Exit with exitcode 1 if path on commandline can't be found. +* Test vulture with vulture using a whitelist module for false positives. -- Add tests that run vulture as a script. -- Add "python setup.py test" command for running tests. -- Add support for tox. -- Raise test coverage to 100%. -- Remove ez_setup.py. +* Add tests that run vulture as a script. +* Add "python setup.py test" command for running tests. +* Add support for tox. +* Raise test coverage to 100%. +* Remove ez\_setup.py. # 0.6 (2014-09-06) -- Ignore function names starting with "test\_". -- Parse variable names in new format strings (e.g. "This is +* Ignore function names starting with "test\_". +* Parse variable names in new format strings (e.g. "This is {x}".format(x="nice")). -- Only parse alphanumeric variable names in format strings and ignore +* Only parse alphanumeric variable names in format strings and ignore types. -- Abort with exit code 1 on syntax errors. -- Support installation under Windows by using setuptools (thanks +* Abort with exit code 1 on syntax errors. +* Support installation under Windows by using setuptools (thanks Reuben Fletcher-Costin). # 0.5 (2014-05-09) -- If dead code is found, exit with 1. +* If dead code is found, exit with 1. # 0.4.1 (2013-09-17) -- Only warn if a path given on the command line cannot be found. +* Only warn if a path given on the command line cannot be found. # 0.4 (2013-06-23) -- Ignore unused variables starting with an underscore. -- Show warning for syntax errors instead of aborting directly. -- Print warning if a file cannot be found. +* Ignore unused variables starting with an underscore. +* Show warning for syntax errors instead of aborting directly. +* Print warning if a file cannot be found. # 0.3 (2012-03-19) -- Add support for python3 -- Report unused attributes -- Find tuple assignments in comprehensions -- Scan files given on the command line even if they don't end with .py +* Add support for python3 +* Report unused attributes +* Find tuple assignments in comprehensions +* Scan files given on the command line even if they don't end with .py # 0.2 (2012-03-18) -- Only format nodes in verbose mode (gives 4x speedup). +* Only format nodes in verbose mode (gives 4x speedup). # 0.1 (2012-03-17) -- First release. +* First release. \ No newline at end of file From f3fb62433eb1717cb1688fbcd739bec7d3406049 Mon Sep 17 00:00:00 2001 From: pm3512 Date: Sun, 7 May 2023 00:19:17 -0400 Subject: [PATCH 14/14] replaced class check with assertion --- vulture/core.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vulture/core.py b/vulture/core.py index 17ea7b93..523a3dbc 100644 --- a/vulture/core.py +++ b/vulture/core.py @@ -600,8 +600,7 @@ def _is_locals_call(node): @staticmethod def _is_subclass(node, class_name): """Return True if the node is a subclass of the given class.""" - if not isinstance(node, ast.ClassDef): - return False + assert isinstance(node, ast.ClassDef) for superclass in node.bases: if ( isinstance(superclass, ast.Name)