diff --git a/CHANGELOG.md b/CHANGELOG.md index 13b619c5d..9faa9a29d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ We used to have incremental versioning before `0.1.0`. - Adds `safety` and other dependency checks to CI process +## Version 0.6.1 + +### Bugfixes + +- Fixes a conflict between our plugin and `pyflakes` + + ## Version 0.6.0 ### Features diff --git a/pyproject.toml b/pyproject.toml index 745a0f12c..960b59699 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "poetry.masonry.api" [tool.poetry] name = "wemake-python-styleguide" -version = "0.6.0" +version = "0.6.1" description = "The strictest and most opinionated python linter ever" license = "MIT" diff --git a/setup.cfg b/setup.cfg index e1ce61478..2bf9b1d85 100644 --- a/setup.cfg +++ b/setup.cfg @@ -51,7 +51,6 @@ filterwarnings = # you an overhead. See `docs/template/development-process.rst`. addopts = --doctest-modules - --flake8 --cov=wemake_python_styleguide --cov-report=term:skip-covered --cov-report=html diff --git a/tests/test_regressions/test_regression_112.py b/tests/test_regressions/test_regression_112.py new file mode 100644 index 000000000..353523770 --- /dev/null +++ b/tests/test_regressions/test_regression_112.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- + +import ast + +from pyflakes.checker import Checker as PyFlakesChecker + +from wemake_python_styleguide.checker import Checker + + +code_that_brakes = ''' +def current_session( + telegram_id: int, + for_update: bool = True, +) -> TelegramSession: + """ + Was triggering `AttributeError`. + + See: https://github.com/wemake-services/wemake-python-styleguide/issues/112 + """ + try: + query = TelegramSession.objects.all() + if for_update: # Try to comment this `if` to fix everything + query = query.select_for_update() + + return query.get( + uid=telegram_id, + is_verified=True, + ) + + except TelegramSession.DoesNotExist: + raise AuthenticationException('Session is missing') +''' + + +def test_regression112(default_options): + """ + There was a conflict between ``pyflakes`` and our plugin. + + We were fighting for ``parent`` property. + Now we use a custom prefix. + + See: https://github.com/wemake-services/wemake-python-styleguide/issues/112 + """ + module = ast.parse(code_that_brakes) + Checker.parse_options(default_options) + checker = Checker(tree=module, file_tokens=[], filename='custom.py') + + # It was failing on this line: + # AttributeError: 'ExceptHandler' object has no attribute 'depth' + flakes = PyFlakesChecker(module) + + assert flakes.root diff --git a/wemake_python_styleguide/transformations/ast/bugfixes.py b/wemake_python_styleguide/transformations/ast/bugfixes.py index 9c59fb9f1..85acc8a2a 100644 --- a/wemake_python_styleguide/transformations/ast/bugfixes.py +++ b/wemake_python_styleguide/transformations/ast/bugfixes.py @@ -54,7 +54,7 @@ def fix_line_number(tree: ast.AST) -> ast.AST: for node in ast.walk(tree): if isinstance(node, affected): parent_lineno = getattr( - getattr(node, 'parent', None), 'lineno', None, + getattr(node, 'wps_parent', None), 'lineno', None, ) if parent_lineno and parent_lineno < node.lineno: node.lineno = node.lineno - 1 diff --git a/wemake_python_styleguide/transformations/ast_tree.py b/wemake_python_styleguide/transformations/ast_tree.py index ee06d2446..7464a60f0 100644 --- a/wemake_python_styleguide/transformations/ast_tree.py +++ b/wemake_python_styleguide/transformations/ast_tree.py @@ -29,14 +29,17 @@ def _set_parent(tree: ast.AST) -> ast.AST: This step is required due to how `flake8` works. It does not set the same properties as `ast` module. - This function was the cause of `issue-112`. + This function was the cause of `issue-112`. Twice. + Since the ``0.6.1`` we use ``'wps_parent'`` with a prefix. + This should fix the issue with conflicting plugins. .. versionchanged:: 0.0.11 + .. versionchanged:: 0.6.1 """ for statement in ast.walk(tree): for child in ast.iter_child_nodes(statement): - setattr(child, 'parent', statement) + setattr(child, 'wps_parent', statement) return tree diff --git a/wemake_python_styleguide/visitors/ast/builtins.py b/wemake_python_styleguide/visitors/ast/builtins.py index aa0ead567..a3f96447d 100644 --- a/wemake_python_styleguide/visitors/ast/builtins.py +++ b/wemake_python_styleguide/visitors/ast/builtins.py @@ -65,7 +65,7 @@ def _get_real_parent(self, node: Optional[ast.AST]) -> Optional[ast.AST]: so ``1`` has ``UnaryOp`` as parent, but should return ``Assign`` """ - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) if isinstance(parent, self._proxy_parents): return self._get_real_parent(parent) return parent diff --git a/wemake_python_styleguide/visitors/ast/complexity/counts.py b/wemake_python_styleguide/visitors/ast/complexity/counts.py index 371bbaf76..0345dab4b 100644 --- a/wemake_python_styleguide/visitors/ast/complexity/counts.py +++ b/wemake_python_styleguide/visitors/ast/complexity/counts.py @@ -37,7 +37,7 @@ def __init__(self, *args, **kwargs) -> None: def _check_members_count(self, node: ModuleMembers) -> None: """This method increases the number of module members.""" - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) is_real_method = is_method(getattr(node, 'function_type', None)) if isinstance(parent, ast.Module) and not is_real_method: @@ -118,7 +118,7 @@ def __init__(self, *args, **kwargs) -> None: self._methods: DefaultDict[ast.ClassDef, int] = defaultdict(int) def _check_method(self, node: AnyFunctionDef) -> None: - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) if isinstance(parent, ast.ClassDef): self._methods[parent] += 1 diff --git a/wemake_python_styleguide/visitors/ast/complexity/function.py b/wemake_python_styleguide/visitors/ast/complexity/function.py index 30c09c2a0..163fc7b3f 100644 --- a/wemake_python_styleguide/visitors/ast/complexity/function.py +++ b/wemake_python_styleguide/visitors/ast/complexity/function.py @@ -57,7 +57,7 @@ def _update_variables( if variable_def.id == UNUSED_VARIABLE: return - parent = getattr(variable_def, 'parent', None) + parent = getattr(variable_def, 'wps_parent', None) if isinstance(parent, self._not_contain_locals): return diff --git a/wemake_python_styleguide/visitors/ast/complexity/nested.py b/wemake_python_styleguide/visitors/ast/complexity/nested.py index 4a01ce51c..23de04511 100644 --- a/wemake_python_styleguide/visitors/ast/complexity/nested.py +++ b/wemake_python_styleguide/visitors/ast/complexity/nested.py @@ -37,14 +37,14 @@ class NestedComplexityVisitor(BaseNodeVisitor): ) def _check_nested_function(self, node: AnyFunctionDef) -> None: - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) is_inside_function = isinstance(parent, self._function_nodes) if is_inside_function and node.name not in NESTED_FUNCTIONS_WHITELIST: self.add_violation(NestedFunctionViolation(node, text=node.name)) def _check_nested_classes(self, node: ast.ClassDef) -> None: - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) is_inside_class = isinstance(parent, ast.ClassDef) is_inside_function = isinstance(parent, self._function_nodes) @@ -54,7 +54,7 @@ def _check_nested_classes(self, node: ast.ClassDef) -> None: self.add_violation(NestedClassViolation(node, text=node.name)) def _check_nested_lambdas(self, node: ast.Lambda) -> None: - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) if isinstance(parent, ast.Lambda): self.add_violation(NestedFunctionViolation(node)) diff --git a/wemake_python_styleguide/visitors/ast/imports.py b/wemake_python_styleguide/visitors/ast/imports.py index b10d5fb1d..89ef050dd 100644 --- a/wemake_python_styleguide/visitors/ast/imports.py +++ b/wemake_python_styleguide/visitors/ast/imports.py @@ -32,7 +32,7 @@ def __init__(self, error_callback: ErrorCallback) -> None: self._error_callback = error_callback def check_nested_import(self, node: AnyImport) -> None: - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) if parent is not None and not isinstance(parent, ast.Module): self._error_callback(NestedImportViolation(node)) diff --git a/wemake_python_styleguide/visitors/ast/keywords.py b/wemake_python_styleguide/visitors/ast/keywords.py index 1f187c751..9e337b7c4 100644 --- a/wemake_python_styleguide/visitors/ast/keywords.py +++ b/wemake_python_styleguide/visitors/ast/keywords.py @@ -103,11 +103,11 @@ def _check_ifs(self, node: ast.comprehension) -> None: if len(node.ifs) > self._max_ifs: # We are trying to fix line number in the report, # since `comprehension` does not have this property. - parent = getattr(node, 'parent', node) + parent = getattr(node, 'wps_parent', node) self.add_violation(MultipleIfsInComprehensionViolation(parent)) def _check_fors(self, node: ast.comprehension) -> None: - parent = getattr(node, 'parent', node) + parent = getattr(node, 'wps_parent', node) self._fors[parent] = len(parent.generators) def _post_visit(self) -> None: diff --git a/wemake_python_styleguide/visitors/ast/naming.py b/wemake_python_styleguide/visitors/ast/naming.py index 50b44af78..90313f961 100644 --- a/wemake_python_styleguide/visitors/ast/naming.py +++ b/wemake_python_styleguide/visitors/ast/naming.py @@ -226,7 +226,7 @@ class WrongModuleMetadataVisitor(BaseNodeVisitor): """Finds wrong metadata information of a module.""" def _check_metadata(self, node: ast.Assign) -> None: - node_parent = getattr(node, 'parent', None) + node_parent = getattr(node, 'wps_parent', None) if not isinstance(node_parent, ast.Module): return diff --git a/wemake_python_styleguide/visitors/ast/statements.py b/wemake_python_styleguide/visitors/ast/statements.py index 8392070b5..a9dab7aed 100644 --- a/wemake_python_styleguide/visitors/ast/statements.py +++ b/wemake_python_styleguide/visitors/ast/statements.py @@ -113,7 +113,7 @@ def _check_expression( return if is_first and is_doc_string(node): - parent = getattr(node, 'parent', None) + parent = getattr(node, 'wps_parent', None) if isinstance(parent, self._have_doc_strings): return