From cf457d488b7c6745713d94ee89052d801a42c05d Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 3 Sep 2018 17:17:36 +0300 Subject: [PATCH] Adds "raises" policy --- CHANGELOG.md | 3 + docs/_pages/errors.rst | 14 +++- tests/conftest.py | 9 +-- tests/fixtures/noqa.py | 4 ++ tests/test_checkers/test_config.py | 5 +- tests/test_checkers/test_noqa.py | 1 - tests/test_visitors/conftest.py | 34 ++++++++++ .../test_visitors/test_complexity/conftest.py | 36 ---------- .../test_function/test_local_variables.py | 6 +- .../test_nested/test_nested_classes.py | 16 ++--- .../test_nested/test_nested_functions.py | 22 +++--- .../test_wrong_class/test_base_class.py | 42 ++++++++++-- .../test_wrong_class/test_magic_methods.py | 12 ++-- .../test_wrong_class/test_staticmethod.py | 10 +-- .../test_wrong_function_calls.py | 12 ++-- .../test_dotted_raw_import.py | 18 +++-- .../test_wrong_import/test_future_imports.py | 18 +++-- .../test_wrong_import/test_nested_imports.py | 8 +-- .../test_relative_imports.py | 14 ++-- .../test_same_alias_import.py | 12 ++-- .../test_wrong_keyword/test_bare_raise.py | 18 +++-- .../test_wrong_keyword/test_del.py | 4 +- .../test_wrong_keyword/test_global.py | 4 +- .../test_wrong_keyword/test_pass.py | 4 +- .../test_raise_notimplemented.py | 12 ++-- .../test_wrong_name/test_class_attributes.py | 16 ++--- .../test_function_args_names.py | 18 ++--- .../test_wrong_name/test_function_names.py | 16 ++--- .../test_wrong_name/test_import_alias.py | 16 ++--- .../test_wrong_name/test_module_metadata.py | 14 ++-- .../test_wrong_name/test_variable_names.py | 35 +++++++--- wemake_python_styleguide/checker.py | 3 +- wemake_python_styleguide/logics/variables.py | 2 +- wemake_python_styleguide/options/config.py | 11 ++- wemake_python_styleguide/options/defaults.py | 5 +- wemake_python_styleguide/temp.py | 0 wemake_python_styleguide/types.py | 2 +- .../visitors/base/visitor.py | 11 +-- .../visitors/complexity/function.py | 16 ++++- .../visitors/complexity/nested.py | 16 ++++- .../visitors/wrong_class.py | 7 ++ .../visitors/wrong_function_call.py | 8 ++- .../visitors/wrong_import.py | 21 +++++- .../visitors/wrong_keyword.py | 50 +++++++++++--- .../visitors/wrong_name.py | 67 ++++++++++++++++--- 45 files changed, 460 insertions(+), 212 deletions(-) delete mode 100644 tests/test_visitors/test_complexity/conftest.py create mode 100644 wemake_python_styleguide/temp.py diff --git a/CHANGELOG.md b/CHANGELOG.md index d61387bee..bdec4ef78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,9 @@ We follow Semantic Versions. - Refactored how errors are defined - Now each check has strict `Raises:` policy which lists all possible errors that this check can find and raise +- Changed how visiters are initialized in tests +- Tests now cover nested classes' explicit bases +- Tests now cover nested classes and functions `noqa` comment ## Version 0.0.6 diff --git a/docs/_pages/errors.rst b/docs/_pages/errors.rst index 01fda2455..4a5c9206e 100644 --- a/docs/_pages/errors.rst +++ b/docs/_pages/errors.rst @@ -1,5 +1,17 @@ Errors ------ -.. automodule:: wemake_python_styleguide.errors +.. automodule:: wemake_python_styleguide.errors.base + :members: + +.. automodule:: wemake_python_styleguide.errors.general + :members: + +.. automodule:: wemake_python_styleguide.errors.imports + :members: + +.. automodule:: wemake_python_styleguide.errors.classes + :members: + +.. automodule:: wemake_python_styleguide.errors.complexity :members: diff --git a/tests/conftest.py b/tests/conftest.py index 99240c820..f43ae3e9d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,20 +7,21 @@ import pytest from wemake_python_styleguide import errors +from wemake_python_styleguide.errors.base import BaseStyleViolation def _is_error_class(cls) -> bool: return ( inspect.isclass(cls) and - issubclass(cls, errors.BaseStyleViolation) and - cls is not errors.BaseStyleViolation + issubclass(cls, BaseStyleViolation) and + cls is not BaseStyleViolation ) -@pytest.fixture(scope='module') +@pytest.fixture(scope='session') def all_errors(): """Loads all errors from the package.""" - return list( + return list( # TODO: fix errors' checks map(itemgetter(1), inspect.getmembers(errors, _is_error_class)), ) diff --git a/tests/fixtures/noqa.py b/tests/fixtures/noqa.py index 3d910ad00..474248747 100644 --- a/tests/fixtures/noqa.py +++ b/tests/fixtures/noqa.py @@ -9,6 +9,8 @@ def some(): from my_module import some_function # noqa: Z101 + def nested(): ... # noqa: Z200 + del {'a': 1}['a'] # noqa: Z110 raise # noqa: Z111 @@ -25,3 +27,5 @@ class BadClass: # noqa: Z302 def some_static(): ... def __del__(self, *args, **kwargs): ... # noqa: Z301 + + class Nested(object): ... # noqa: Z201 diff --git a/tests/test_checkers/test_config.py b/tests/test_checkers/test_config.py index daa2784b2..363e2b950 100644 --- a/tests/test_checkers/test_config.py +++ b/tests/test_checkers/test_config.py @@ -8,8 +8,9 @@ @pytest.mark.parametrize('filename, option_flag, option_value, error_code', [ ('wrong_variables.py', '--max-local-variables', '100', b'Z150'), ('wrong_arguments.py', '--max-arguments', '100', b'Z151'), - ('wrong_returns.py', '--max-returns', '100', b'153'), - ('wrong_expressions.py', '--max-expressions', '100', b'154'), + ('wrong_returns.py', '--max-returns', '100', b'Z153'), + ('wrong_expressions.py', '--max-expressions', '100', b'Z154'), + ('wrong_variables.py', '--min-variable-length', '0', b'Z115'), ]) def test_max_variables_cli_option( absolute_path, diff --git a/tests/test_checkers/test_noqa.py b/tests/test_checkers/test_noqa.py index 45471a0e3..eb0ccc97d 100644 --- a/tests/test_checkers/test_noqa.py +++ b/tests/test_checkers/test_noqa.py @@ -26,5 +26,4 @@ def test_noqa_fixture(absolute_path): ) stdout, _ = process.communicate() - print(stdout) assert stdout.count(b'Z') == 0 diff --git a/tests/test_visitors/conftest.py b/tests/test_visitors/conftest.py index 7358ab1ea..9f712bda6 100644 --- a/tests/test_visitors/conftest.py +++ b/tests/test_visitors/conftest.py @@ -1,14 +1,24 @@ # -*- coding: utf-8 -*- import ast +from collections import namedtuple from textwrap import dedent from typing import Sequence import pytest from wemake_python_styleguide.compat import maybe_set_parent +from wemake_python_styleguide.options import defaults from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor +Options = namedtuple('options', [ + 'max_arguments', + 'max_expressions', + 'max_local_variables', + 'max_returns', + 'min_variable_length', +]) + @pytest.fixture(scope='session') def parse_ast_tree(): @@ -30,3 +40,27 @@ def factory(visiter: BaseNodeVisitor, errors: Sequence[str]): assert len(visiter.errors) == len(errors) return factory + + +@pytest.fixture(scope='session') +def options(): + """Returns the options builder.""" + def factory(**kwargs): + default_values = { + 'max_arguments': defaults.MAX_ARGUMENTS, + 'max_expressions': defaults.MAX_EXPRESSIONS, + 'max_local_variables': defaults.MAX_LOCAL_VARIABLES, + 'max_returns': defaults.MAX_RETURNS, + 'min_variable_length': defaults.MIN_VARIABLE_LENGTH, + } + + default_values.update(kwargs) + return Options(**default_values) + + return factory + + +@pytest.fixture(scope='session') +def default_options(options): + """Returns the default options.""" + return options() diff --git a/tests/test_visitors/test_complexity/conftest.py b/tests/test_visitors/test_complexity/conftest.py deleted file mode 100644 index aeb61c866..000000000 --- a/tests/test_visitors/test_complexity/conftest.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- - -from collections import namedtuple - -import pytest - -from wemake_python_styleguide.options.defaults import ( - MAX_ARGUMENTS, - MAX_EXPRESSIONS, - MAX_LOCAL_VARIABLES, - MAX_RETURNS, -) - -Options = namedtuple('options', [ - 'max_arguments', - 'max_expressions', - 'max_local_variables', - 'max_returns', -]) - - -@pytest.fixture() -def options(): - """Returns the options builder.""" - def factory(**kwargs): - defaults = { - 'max_arguments': MAX_ARGUMENTS, - 'max_expressions': MAX_EXPRESSIONS, - 'max_local_variables': MAX_LOCAL_VARIABLES, - 'max_returns': MAX_RETURNS, - } - - defaults.update(kwargs) - return Options(**defaults) - - return factory diff --git a/tests/test_visitors/test_complexity/test_function/test_local_variables.py b/tests/test_visitors/test_complexity/test_function/test_local_variables.py index fe9ee03f9..392a00bf0 100644 --- a/tests/test_visitors/test_complexity/test_function/test_local_variables.py +++ b/tests/test_visitors/test_complexity/test_function/test_local_variables.py @@ -46,8 +46,7 @@ def test_locals_correct_count(assert_errors, parse_ast_tree, options, code): option_values = options(max_local_variables=2) tree = parse_ast_tree(code) - visiter = FunctionComplexityVisitor() - visiter.provide_options(option_values) + visiter = FunctionComplexityVisitor(option_values) visiter.visit(tree) assert_errors(visiter, []) @@ -68,8 +67,7 @@ def test_locals_wrong_count(assert_errors, parse_ast_tree, options, code): option_values = options(max_local_variables=1) tree = parse_ast_tree(code) - visiter = FunctionComplexityVisitor() - visiter.provide_options(option_values) + visiter = FunctionComplexityVisitor(option_values) visiter.visit(tree) assert_errors(visiter, [TooManyLocalsViolation]) diff --git a/tests/test_visitors/test_complexity/test_nested/test_nested_classes.py b/tests/test_visitors/test_complexity/test_nested/test_nested_classes.py index f84aea88e..a056857d8 100644 --- a/tests/test_visitors/test_complexity/test_nested/test_nested_classes.py +++ b/tests/test_visitors/test_complexity/test_nested/test_nested_classes.py @@ -30,11 +30,11 @@ class {0}: ... nested_class_in_method, nested_class_in_function, ]) -def test_nested_class(assert_errors, parse_ast_tree, code): +def test_nested_class(assert_errors, parse_ast_tree, code, default_options): """Testing that nested classes are restricted.""" tree = parse_ast_tree(code.format('NestedClass')) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [NestedClassViolation]) @@ -45,12 +45,12 @@ def test_nested_class(assert_errors, parse_ast_tree, code): nested_class, ]) def test_whitelist_nested_classes( - assert_errors, parse_ast_tree, whitelist_name, code, + assert_errors, parse_ast_tree, whitelist_name, code, default_options, ): """Testing that it is possible to nest whitelisted classes.""" tree = parse_ast_tree(code.format(whitelist_name)) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) @@ -65,25 +65,25 @@ def test_whitelist_nested_classes( nested_class_in_function, ]) def test_whitelist_nested_classes_in_functions( - assert_errors, parse_ast_tree, whitelist_name, code, + assert_errors, parse_ast_tree, whitelist_name, code, default_options, ): """Testing that it is restricted to nest any classes in functions.""" tree = parse_ast_tree(code.format(whitelist_name)) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [NestedClassViolation]) -def test_ordinary_class(assert_errors, parse_ast_tree): +def test_ordinary_class(assert_errors, parse_ast_tree, default_options): """Testing that it is possible to write basic classes.""" tree = parse_ast_tree(""" class Ordinary: def method(self): ... """) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_complexity/test_nested/test_nested_functions.py b/tests/test_visitors/test_complexity/test_nested/test_nested_functions.py index b9ba3f283..4a5f34ca9 100644 --- a/tests/test_visitors/test_complexity/test_nested/test_nested_functions.py +++ b/tests/test_visitors/test_complexity/test_nested/test_nested_functions.py @@ -24,11 +24,11 @@ def {0}(): ... nested_function, nested_method, ]) -def test_nested_function(assert_errors, parse_ast_tree, code): +def test_nested_function(assert_errors, parse_ast_tree, code, default_options): """Testing that nested functions are restricted.""" tree = parse_ast_tree(code.format('nested')) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [NestedFunctionViolation]) @@ -40,31 +40,33 @@ def test_nested_function(assert_errors, parse_ast_tree, code): nested_method, ]) def test_whitelist_nested_functions( - assert_errors, parse_ast_tree, whitelist_name, code, + assert_errors, parse_ast_tree, whitelist_name, code, default_options, ): """Testing that it is possible to nest whitelisted functions.""" tree = parse_ast_tree(code.format(whitelist_name)) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) -def test_lambda_nested_functions(assert_errors, parse_ast_tree): +def test_lambda_nested_functions( + assert_errors, parse_ast_tree, default_options, +): """Testing that it is possible to nest lambda inside functions.""" tree = parse_ast_tree(""" def container(): lazy_value = lambda: 12 """) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) -def test_lambda_nested_lambdas(assert_errors, parse_ast_tree): +def test_lambda_nested_lambdas(assert_errors, parse_ast_tree, default_options): """ Testing that it is restricted to nest lambdas. @@ -75,13 +77,13 @@ def container(): nested_lambda = lambda: lambda value: value + 12 """) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [NestedFunctionViolation]) -def test_lambda_nested_method(assert_errors, parse_ast_tree): +def test_lambda_nested_method(assert_errors, parse_ast_tree, default_options): """Testing that it is possible to nest lambda inside methods.""" tree = parse_ast_tree(""" class Raw: @@ -89,7 +91,7 @@ def container(self): lazy_value = lambda: 12 """) - visiter = NestedComplexityVisitor() + visiter = NestedComplexityVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_class/test_base_class.py b/tests/test_visitors/test_wrong_class/test_base_class.py index 9b7d74343..0e30ad4ef 100644 --- a/tests/test_visitors/test_wrong_class/test_base_class.py +++ b/tests/test_visitors/test_wrong_class/test_base_class.py @@ -8,18 +8,48 @@ ) -def test_wrong_base_class(assert_errors, parse_ast_tree): - """Testing that not using explicit base class with forbiden.""" +def test_wrong_base_class(assert_errors, parse_ast_tree, default_options): + """Testing that not using explicit base class is forbiden.""" tree = parse_ast_tree(""" class WithoutBase: ... """) - visiter = WrongClassVisitor() + visiter = WrongClassVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [RequiredBaseClassViolation]) +def test_wrong_base_class_nested( + assert_errors, parse_ast_tree, default_options, +): + """Testing that not using explicit base class on nested is forbiden.""" + tree = parse_ast_tree(""" + class Model(object): + class Meta: ... + """) + + visiter = WrongClassVisitor(default_options) + visiter.visit(tree) + + assert_errors(visiter, [RequiredBaseClassViolation]) + + +def test_correct_base_class_nested( + assert_errors, parse_ast_tree, default_options, +): + """Testing that using explicit base class on nested works.""" + tree = parse_ast_tree(""" + class Model(object): + class Meta(object): ... + """) + + visiter = WrongClassVisitor(default_options) + visiter.visit(tree) + + assert_errors(visiter, []) + + @pytest.mark.parametrize('base', [ 'object', 'dict', @@ -27,13 +57,15 @@ class WithoutBase: ... 'Multiple, Classes, Mixins', 'Custom, keyword=1', ]) -def test_regular_base_classes(assert_errors, parse_ast_tree, base): +def test_regular_base_classes( + assert_errors, parse_ast_tree, base, default_options, +): """Testing that regular base classes work.""" tree = parse_ast_tree(""" class Example({0}): ... """.format(base)) - visiter = WrongClassVisitor() + visiter = WrongClassVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_class/test_magic_methods.py b/tests/test_visitors/test_wrong_class/test_magic_methods.py index 721e9c583..2bda2a5d1 100644 --- a/tests/test_visitors/test_wrong_class/test_magic_methods.py +++ b/tests/test_visitors/test_wrong_class/test_magic_methods.py @@ -15,11 +15,13 @@ def {0}(): ... @pytest.mark.parametrize('method', BAD_MAGIC_METHODS) -def test_wrong_magic_used(assert_errors, parse_ast_tree, method): +def test_wrong_magic_used( + assert_errors, parse_ast_tree, method, default_options, +): """Testing that some magic methods are restricted.""" tree = parse_ast_tree(magic_method.format(method)) - visiter = WrongClassVisitor() + visiter = WrongClassVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [BadMagicMethodViolation]) @@ -31,11 +33,13 @@ def test_wrong_magic_used(assert_errors, parse_ast_tree, method): 'next', 'regular', ]) -def test_regular_method_used(assert_errors, parse_ast_tree, method): +def test_regular_method_used( + assert_errors, parse_ast_tree, method, default_options, +): """Testing that other methods are working fine.""" tree = parse_ast_tree(magic_method.format(method)) - visiter = WrongClassVisitor() + visiter = WrongClassVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_class/test_staticmethod.py b/tests/test_visitors/test_wrong_class/test_staticmethod.py index 6de48c91d..6a7474807 100644 --- a/tests/test_visitors/test_wrong_class/test_staticmethod.py +++ b/tests/test_visitors/test_wrong_class/test_staticmethod.py @@ -14,11 +14,11 @@ def should_fail(): ... """ -def test_staticmethod_used(assert_errors, parse_ast_tree): +def test_staticmethod_used(assert_errors, parse_ast_tree, default_options): """Testing that some built-in functions are restricted as decorators.""" tree = parse_ast_tree(decorated_method.format('staticmethod')) - visiter = WrongClassVisitor() + visiter = WrongClassVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [StaticMethodViolation]) @@ -29,11 +29,13 @@ def test_staticmethod_used(assert_errors, parse_ast_tree): 'custom', 'with_params(12, 100)', ]) -def test_regular_decorator_used(assert_errors, parse_ast_tree, decorator): +def test_regular_decorator_used( + assert_errors, parse_ast_tree, decorator, default_options, +): """Testing that other decorators are allowed.""" tree = parse_ast_tree(decorated_method.format(decorator)) - visiter = WrongClassVisitor() + visiter = WrongClassVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_function_call/test_wrong_function_calls.py b/tests/test_visitors/test_wrong_function_call/test_wrong_function_calls.py index a476b7b41..e1a194862 100644 --- a/tests/test_visitors/test_wrong_function_call/test_wrong_function_calls.py +++ b/tests/test_visitors/test_wrong_function_call/test_wrong_function_calls.py @@ -29,24 +29,24 @@ def proxy(*args, **kwargs): nested_function_call, ]) def test_wrong_function_called( - assert_errors, parse_ast_tree, bad_function, code, + assert_errors, parse_ast_tree, bad_function, code, default_options, ): """Testing that some built-in functions are restricted.""" tree = parse_ast_tree(code.format(bad_function)) - visiter = WrongFunctionCallVisitor() + visiter = WrongFunctionCallVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongFunctionCallViolation]) -def test_wrong_decorator_used(assert_errors, parse_ast_tree): +def test_wrong_decorator_used(assert_errors, parse_ast_tree, default_options): """Testing that some built-in functions are restricted as decorators.""" tree = parse_ast_tree(""" some_static = staticmethod(some_function) """) - visiter = WrongFunctionCallVisitor() + visiter = WrongFunctionCallVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongFunctionCallViolation]) @@ -59,12 +59,12 @@ def test_wrong_decorator_used(assert_errors, parse_ast_tree): nested_function_call, ]) def test_regular_function_called( - assert_errors, parse_ast_tree, good_function, code, + assert_errors, parse_ast_tree, good_function, code, default_options, ): """Testing that other functions are not restricted.""" tree = parse_ast_tree(code.format(good_function)) - visiter = WrongFunctionCallVisitor() + visiter = WrongFunctionCallVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_import/test_dotted_raw_import.py b/tests/test_visitors/test_wrong_import/test_dotted_raw_import.py index 7a49e5f27..d1781972b 100644 --- a/tests/test_visitors/test_wrong_import/test_dotted_raw_import.py +++ b/tests/test_visitors/test_wrong_import/test_dotted_raw_import.py @@ -32,11 +32,13 @@ 'dotted.path' 'nested.dotted.path', ]) -def test_wrong_dotted_import(assert_errors, parse_ast_tree, code, to_import): +def test_wrong_dotted_import( + assert_errors, parse_ast_tree, code, to_import, default_options, +): """Testing that dotted raw imports are restricted.""" tree = parse_ast_tree(code.format(to_import)) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [DottedRawImportViolation]) @@ -50,11 +52,13 @@ def test_wrong_dotted_import(assert_errors, parse_ast_tree, code, to_import): 'os', 'sys', ]) -def test_correct_flat_import(assert_errors, parse_ast_tree, code, to_import): +def test_correct_flat_import( + assert_errors, parse_ast_tree, code, to_import, default_options, +): """Testing that flat raw imports are allowed.""" tree = parse_ast_tree(code.format(to_import)) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) @@ -69,11 +73,13 @@ def test_correct_flat_import(assert_errors, parse_ast_tree, code, to_import): 'dotted.path' 'nested.dotted.path', ]) -def test_regular_from_import(assert_errors, parse_ast_tree, code, to_import): +def test_regular_from_import( + assert_errors, parse_ast_tree, code, to_import, default_options, +): """Testing that dotted `from` imports are allowed.""" tree = parse_ast_tree(code.format(to_import)) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_import/test_future_imports.py b/tests/test_visitors/test_wrong_import/test_future_imports.py index efdf1ae32..dc0d6be35 100644 --- a/tests/test_visitors/test_wrong_import/test_future_imports.py +++ b/tests/test_visitors/test_wrong_import/test_future_imports.py @@ -25,23 +25,27 @@ 'print_function' 'custom_value', ]) -def test_wrong_future_import(assert_errors, parse_ast_tree, code, to_import): +def test_wrong_future_import( + assert_errors, parse_ast_tree, code, to_import, default_options, +): """Testing that future imports are restricted.""" tree = parse_ast_tree(code.format(to_import)) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [FutureImportViolation]) -def test_wrong_multiple_future_import(assert_errors, parse_ast_tree): +def test_wrong_multiple_future_import( + assert_errors, parse_ast_tree, default_options, +): """Testing that multiple future imports are restricted.""" tree = parse_ast_tree(""" from __future__ import print_function, unicode_literals """) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [FutureImportViolation, FutureImportViolation]) @@ -52,11 +56,13 @@ def test_wrong_multiple_future_import(assert_errors, parse_ast_tree): future_import_alias, ]) @pytest.mark.parametrize('to_import', FUTURE_IMPORTS_WHITELIST) -def test_correct_future_import(assert_errors, parse_ast_tree, code, to_import): +def test_correct_future_import( + assert_errors, parse_ast_tree, code, to_import, default_options, +): """Testing that some future imports are not restricted.""" tree = parse_ast_tree(code.format(to_import)) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_import/test_nested_imports.py b/tests/test_visitors/test_wrong_import/test_nested_imports.py index 66b4755b1..987cd6c96 100644 --- a/tests/test_visitors/test_wrong_import/test_nested_imports.py +++ b/tests/test_visitors/test_wrong_import/test_nested_imports.py @@ -62,11 +62,11 @@ def with_import(self): nested_conditional_import, nested_try_import, ]) -def test_nested_import(assert_errors, parse_ast_tree, code): +def test_nested_import(assert_errors, parse_ast_tree, code, default_options): """Testing that nested imports are restricted.""" tree = parse_ast_tree(code) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [NestedImportViolation]) @@ -76,11 +76,11 @@ def test_nested_import(assert_errors, parse_ast_tree, code): regular_import, regular_from_import, ]) -def test_regular_imports(assert_errors, parse_ast_tree, code): +def test_regular_imports(assert_errors, parse_ast_tree, code, default_options): """Testing that regular imports are allowed.""" tree = parse_ast_tree(code) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_import/test_relative_imports.py b/tests/test_visitors/test_wrong_import/test_relative_imports.py index 403a4b340..4bf8daff5 100644 --- a/tests/test_visitors/test_wrong_import/test_relative_imports.py +++ b/tests/test_visitors/test_wrong_import/test_relative_imports.py @@ -30,31 +30,33 @@ parent_level_relative_import, parent_level_relative_import_sibling, ]) -def test_local_folder_import(assert_errors, parse_ast_tree, code): +def test_local_folder_import( + assert_errors, parse_ast_tree, code, default_options, +): """Testing that relative to local folder imports are restricted.""" tree = parse_ast_tree(code) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [LocalFolderImportViolation]) -def test_regular_import(assert_errors, parse_ast_tree): +def test_regular_import(assert_errors, parse_ast_tree, default_options): """Testing that regular imports are allowed.""" tree = parse_ast_tree('import os') - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) -def test_regular_from_import(assert_errors, parse_ast_tree): +def test_regular_from_import(assert_errors, parse_ast_tree, default_options): """Testing that regular from imports are allowed.""" tree = parse_ast_tree('from os import path') - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_import/test_same_alias_import.py b/tests/test_visitors/test_wrong_import/test_same_alias_import.py index d8396ec83..1238508c4 100644 --- a/tests/test_visitors/test_wrong_import/test_same_alias_import.py +++ b/tests/test_visitors/test_wrong_import/test_same_alias_import.py @@ -20,11 +20,13 @@ regular_import, from_import, ]) -def test_same_alias_import(assert_errors, parse_ast_tree, code): +def test_same_alias_import( + assert_errors, parse_ast_tree, code, default_options, +): """Testing that imports with the same aliases are restricted.""" tree = parse_ast_tree(code.format('os')) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [SameAliasImportViolation]) @@ -39,11 +41,13 @@ def test_same_alias_import(assert_errors, parse_ast_tree, code): 'names', 'sys', ]) -def test_other_alias_name(assert_errors, parse_ast_tree, code, to_import): +def test_other_alias_name( + assert_errors, parse_ast_tree, code, to_import, default_options, +): """Testing that imports with other aliases are allowed.""" tree = parse_ast_tree(code.format(to_import)) - visiter = WrongImportVisitor() + visiter = WrongImportVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_keyword/test_bare_raise.py b/tests/test_visitors/test_wrong_keyword/test_bare_raise.py index d36fdcab6..294a2d5a6 100644 --- a/tests/test_visitors/test_wrong_keyword/test_bare_raise.py +++ b/tests/test_visitors/test_wrong_keyword/test_bare_raise.py @@ -21,29 +21,35 @@ def function(): bare_raise_module, bare_raise_function, ]) -def test_bare_raise_keyword(assert_errors, parse_ast_tree, code): +def test_bare_raise_keyword( + assert_errors, parse_ast_tree, code, default_options, +): """Testing that bare raise keyword is restricted outside of except.""" tree = parse_ast_tree(code) - visiter = WrongRaiseVisitor() + visiter = WrongRaiseVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [BareRiseViolation]) -def test_normal_raise_keyword(assert_errors, parse_ast_tree): +def test_normal_raise_keyword( + assert_errors, parse_ast_tree, default_options, +): """Testing that regular bare raise keyword is allowed inside `except`.""" tree = parse_ast_tree(""" raise ValueError('Some error') """) - visiter = WrongRaiseVisitor() + visiter = WrongRaiseVisitor(default_options) visiter.visit(tree) assert visiter.errors == [] -def test_bare_raise_in_except_keyword(assert_errors, parse_ast_tree): +def test_bare_raise_in_except_keyword( + assert_errors, parse_ast_tree, default_options, +): """Testing that regular bare raise keyword is allowed inside `except`.""" tree = parse_ast_tree(""" try: @@ -52,7 +58,7 @@ def test_bare_raise_in_except_keyword(assert_errors, parse_ast_tree): raise """) - visiter = WrongRaiseVisitor() + visiter = WrongRaiseVisitor(default_options) visiter.visit(tree) assert visiter.errors == [] diff --git a/tests/test_visitors/test_wrong_keyword/test_del.py b/tests/test_visitors/test_wrong_keyword/test_del.py index baf02d59f..1a7e39425 100644 --- a/tests/test_visitors/test_wrong_keyword/test_del.py +++ b/tests/test_visitors/test_wrong_keyword/test_del.py @@ -6,7 +6,7 @@ ) -def test_del_keyword(assert_errors, parse_ast_tree): +def test_del_keyword(assert_errors, parse_ast_tree, default_options): """Testing that `del` keyword is restricted.""" tree = parse_ast_tree(""" def check_del(): @@ -15,7 +15,7 @@ def check_del(): del s """) - visiter = WrongKeywordVisitor() + visiter = WrongKeywordVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [ diff --git a/tests/test_visitors/test_wrong_keyword/test_global.py b/tests/test_visitors/test_wrong_keyword/test_global.py index c3b2b11ed..e498b49c2 100644 --- a/tests/test_visitors/test_wrong_keyword/test_global.py +++ b/tests/test_visitors/test_wrong_keyword/test_global.py @@ -27,11 +27,11 @@ def nested(): global_in_function, nonlocal_in_function, ]) -def test_global_keywords(assert_errors, parse_ast_tree, code): +def test_global_keywords(assert_errors, parse_ast_tree, code, default_options): """Testing that `global` and `nonlocal` keywords are restricted.""" tree = parse_ast_tree(code) - visiter = WrongKeywordVisitor() + visiter = WrongKeywordVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongKeywordViolation]) diff --git a/tests/test_visitors/test_wrong_keyword/test_pass.py b/tests/test_visitors/test_wrong_keyword/test_pass.py index 27cb11301..ce4973815 100644 --- a/tests/test_visitors/test_wrong_keyword/test_pass.py +++ b/tests/test_visitors/test_wrong_keyword/test_pass.py @@ -29,11 +29,11 @@ def method(self): pass_class, pass_method, ]) -def test_pass_keyword(assert_errors, parse_ast_tree, code): +def test_pass_keyword(assert_errors, parse_ast_tree, code, default_options): """Testing that pass keyword is restricted inside different definitions.""" tree = parse_ast_tree(code) - visiter = WrongKeywordVisitor() + visiter = WrongKeywordVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongKeywordViolation]) diff --git a/tests/test_visitors/test_wrong_keyword/test_raise_notimplemented.py b/tests/test_visitors/test_wrong_keyword/test_raise_notimplemented.py index 30bb6f1dd..50d5aeb68 100644 --- a/tests/test_visitors/test_wrong_keyword/test_raise_notimplemented.py +++ b/tests/test_visitors/test_wrong_keyword/test_raise_notimplemented.py @@ -24,23 +24,27 @@ def check_not_implemented_without_call(self): raise_not_implemented, raise_not_implemented_type, ]) -def test_raise_not_implemented(assert_errors, parse_ast_tree, code): +def test_raise_not_implemented( + assert_errors, parse_ast_tree, code, default_options, +): """Testing that `raise NotImplemented` is restricted.""" tree = parse_ast_tree(code) - visiter = WrongRaiseVisitor() + visiter = WrongRaiseVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [RaiseNotImplementedViolation]) -def test_raise_not_implemented_error(assert_errors, parse_ast_tree): +def test_raise_not_implemented_error( + assert_errors, parse_ast_tree, default_options, +): """Testing that `raise NotImplementedError` is allowed.""" tree = parse_ast_tree(""" raise NotImplementedError() """) - visiter = WrongRaiseVisitor() + visiter = WrongRaiseVisitor(default_options) visiter.visit(tree) assert visiter.errors == [] diff --git a/tests/test_visitors/test_wrong_name/test_class_attributes.py b/tests/test_visitors/test_wrong_name/test_class_attributes.py index 71727edac..82603d611 100644 --- a/tests/test_visitors/test_wrong_name/test_class_attributes.py +++ b/tests/test_visitors/test_wrong_name/test_class_attributes.py @@ -30,12 +30,12 @@ def __init__(self): instance_attribute, ]) def test_wrong_attributes_names( - assert_errors, parse_ast_tree, bad_name, code, + assert_errors, parse_ast_tree, bad_name, code, default_options, ): """Testing that attribute can not have blacklisted names.""" tree = parse_ast_tree(code.format(bad_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongVariableNameViolation]) @@ -47,12 +47,12 @@ def test_wrong_attributes_names( instance_attribute, ]) def test_too_short_attribute_names( - assert_errors, parse_ast_tree, short_name, code, + assert_errors, parse_ast_tree, short_name, code, default_options, ): """Testing that attribute can not have too short names.""" tree = parse_ast_tree(code.format(short_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [TooShortVariableNameViolation]) @@ -63,12 +63,12 @@ def test_too_short_attribute_names( instance_attribute, ]) def test_private_attribute_names( - assert_errors, parse_ast_tree, code, + assert_errors, parse_ast_tree, code, default_options, ): """Testing that attribute can not have private names.""" tree = parse_ast_tree(code.format('__private_name')) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [PrivateNameViolation]) @@ -86,12 +86,12 @@ def test_private_attribute_names( instance_attribute, ]) def test_correct_attribute_name( - assert_errors, parse_ast_tree, code, correct_name, + assert_errors, parse_ast_tree, code, correct_name, default_options, ): """Testing that attribute can have normal names.""" tree = parse_ast_tree(code.format(correct_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_name/test_function_args_names.py b/tests/test_visitors/test_wrong_name/test_function_args_names.py index 7b23b143f..4734cc4bf 100644 --- a/tests/test_visitors/test_wrong_name/test_function_args_names.py +++ b/tests/test_visitors/test_wrong_name/test_function_args_names.py @@ -50,12 +50,12 @@ def validate(self, *{0}, **{1}): ... method_args_kwargs_test, ]) def test_wrong_function_arguments( - assert_errors, parse_ast_tree, bad_name, code, + assert_errors, parse_ast_tree, bad_name, code, default_options, ): """Testing that function can not have blacklisted arguments.""" tree = parse_ast_tree(code.format('x', bad_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [ @@ -74,12 +74,12 @@ def test_wrong_function_arguments( method_args_kwargs_test, ]) def test_too_short_function_arguments( - assert_errors, parse_ast_tree, short_name, code, + assert_errors, parse_ast_tree, short_name, code, default_options, ): """Testing that function can not have too short arguments.""" tree = parse_ast_tree(code.format(short_name, 'data')) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [ @@ -97,12 +97,12 @@ def test_too_short_function_arguments( method_args_kwargs_test, ]) def test_private_function_arguments( - assert_errors, parse_ast_tree, code, + assert_errors, parse_ast_tree, code, default_options, ): """Testing that function can not have private arguments.""" tree = parse_ast_tree(code.format('__private', '__name')) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [ @@ -119,11 +119,13 @@ def test_private_function_arguments( function_args_kwargs_test, method_args_kwargs_test, ]) -def test_correct_function_arguments(assert_errors, parse_ast_tree, code): +def test_correct_function_arguments( + assert_errors, parse_ast_tree, code, default_options, +): """Testing that function can have normal arguments.""" tree = parse_ast_tree(code.format('xy', 'normal_name')) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_name/test_function_names.py b/tests/test_visitors/test_wrong_name/test_function_names.py index 0a9041f88..ea3fbc5f3 100644 --- a/tests/test_visitors/test_wrong_name/test_function_names.py +++ b/tests/test_visitors/test_wrong_name/test_function_names.py @@ -28,12 +28,12 @@ def {0}(self): ... method_bad_name, ]) def test_wrong_function_names( - assert_errors, parse_ast_tree, bad_name, code, + assert_errors, parse_ast_tree, bad_name, code, default_options, ): """Testing that function can not have blacklisted names.""" tree = parse_ast_tree(code.format(bad_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongVariableNameViolation]) @@ -45,12 +45,12 @@ def test_wrong_function_names( method_bad_name, ]) def test_too_short_function_names( - assert_errors, parse_ast_tree, short_name, code, + assert_errors, parse_ast_tree, short_name, code, default_options, ): """Testing that function can not have too short names.""" tree = parse_ast_tree(code.format(short_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [TooShortVariableNameViolation]) @@ -61,12 +61,12 @@ def test_too_short_function_names( method_bad_name, ]) def test_private_function_names( - assert_errors, parse_ast_tree, code, + assert_errors, parse_ast_tree, code, default_options, ): """Testing that function can not have private names.""" tree = parse_ast_tree(code.format('__hidden')) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [PrivateNameViolation]) @@ -84,12 +84,12 @@ def test_private_function_names( method_bad_name, ]) def test_correct_function_names( - assert_errors, parse_ast_tree, correct_name, code, + assert_errors, parse_ast_tree, correct_name, code, default_options, ): """Testing that function can have normal names.""" tree = parse_ast_tree(code.format(correct_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_name/test_import_alias.py b/tests/test_visitors/test_wrong_name/test_import_alias.py index 8100f7c72..d86706a87 100644 --- a/tests/test_visitors/test_wrong_name/test_import_alias.py +++ b/tests/test_visitors/test_wrong_name/test_import_alias.py @@ -27,12 +27,12 @@ from_import_alias, ]) def test_wrong_import_alias_names( - assert_errors, parse_ast_tree, bad_name, code, + assert_errors, parse_ast_tree, bad_name, code, default_options, ): """Testing that import aliases can not have blacklisted names.""" tree = parse_ast_tree(code.format(bad_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongVariableNameViolation]) @@ -44,12 +44,12 @@ def test_wrong_import_alias_names( from_import_alias, ]) def test_too_short_import_alias_names( - assert_errors, parse_ast_tree, short_name, code, + assert_errors, parse_ast_tree, short_name, code, default_options, ): """Testing that import aliases can not have too short names.""" tree = parse_ast_tree(code.format(short_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [TooShortVariableNameViolation]) @@ -60,12 +60,12 @@ def test_too_short_import_alias_names( from_import_alias, ]) def test_private_import_alias_names( - assert_errors, parse_ast_tree, code, + assert_errors, parse_ast_tree, code, default_options, ): """Testing that import aliases can not have too private names.""" tree = parse_ast_tree(code.format('__hidden')) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [PrivateNameViolation]) @@ -82,12 +82,12 @@ def test_private_import_alias_names( from_import_alias, ]) def test_correct_import_alias_names( - assert_errors, parse_ast_tree, correct_name, code, + assert_errors, parse_ast_tree, correct_name, code, default_options, ): """Testing that import aliases can have normal names.""" tree = parse_ast_tree(code.format(correct_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_name/test_module_metadata.py b/tests/test_visitors/test_wrong_name/test_module_metadata.py index 837100588..1d1553a5f 100644 --- a/tests/test_visitors/test_wrong_name/test_module_metadata.py +++ b/tests/test_visitors/test_wrong_name/test_module_metadata.py @@ -28,12 +28,12 @@ class ORM: module_metadata, ]) def test_wrong_metadata( - assert_errors, parse_ast_tree, bad_name, code, + assert_errors, parse_ast_tree, bad_name, code, default_options, ): """Testing that metadata can not have blacklisted names.""" tree = parse_ast_tree(code.format(bad_name)) - visiter = WrongModuleMetadataVisitor() + visiter = WrongModuleMetadataVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongModuleMetadataViolation]) @@ -49,22 +49,24 @@ def test_wrong_metadata( nested_metadata, ]) def test_correct_metadata( - assert_errors, parse_ast_tree, code, correct_name, + assert_errors, parse_ast_tree, code, correct_name, default_options, ): """Testing that metadata can have normal names.""" tree = parse_ast_tree(code.format(correct_name)) - visiter = WrongModuleMetadataVisitor() + visiter = WrongModuleMetadataVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) -def test_correct_startup_metadata(assert_errors, parse_ast_tree): +def test_correct_startup_metadata( + assert_errors, parse_ast_tree, default_options, +): """Testing that startup hook is allowed.""" tree = parse_ast_tree(startup_metadata) - visiter = WrongModuleMetadataVisitor() + visiter = WrongModuleMetadataVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/tests/test_visitors/test_wrong_name/test_variable_names.py b/tests/test_visitors/test_wrong_name/test_variable_names.py index 19952b7e0..1ced280d8 100644 --- a/tests/test_visitors/test_wrong_name/test_variable_names.py +++ b/tests/test_visitors/test_wrong_name/test_variable_names.py @@ -52,12 +52,12 @@ underscore_variable_test2, ]) def test_wrong_variable_names( - assert_errors, parse_ast_tree, bad_name, code, + assert_errors, parse_ast_tree, bad_name, code, default_options, ): """Testing that variable can not have blacklisted names.""" tree = parse_ast_tree(code.format(bad_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [WrongVariableNameViolation]) @@ -71,12 +71,31 @@ def test_wrong_variable_names( exception_test, ]) def test_too_short_variable_names( - assert_errors, parse_ast_tree, short_name, code, + assert_errors, parse_ast_tree, short_name, code, default_options, ): """Testing that variable can not have too short names.""" tree = parse_ast_tree(code.format(short_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) + visiter.visit(tree) + + assert_errors(visiter, [TooShortVariableNameViolation]) + + +@pytest.mark.parametrize('code', [ + variable_test, + for_variable_test, + with_variable_test, + exception_test, +]) +def test_too_short_variable_names_configured( + assert_errors, parse_ast_tree, code, options, +): + """Testing that variable length can be configured.""" + tree = parse_ast_tree(code.format('some')) + + option_values = options(min_variable_length=5) + visiter = WrongNameVisitor(option_values) visiter.visit(tree) assert_errors(visiter, [TooShortVariableNameViolation]) @@ -89,12 +108,12 @@ def test_too_short_variable_names( exception_test, ]) def test_private_variable_names( - assert_errors, parse_ast_tree, code, + assert_errors, parse_ast_tree, code, default_options, ): """Testing that variable can not have private names.""" tree = parse_ast_tree(code.format('__private_value')) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, [PrivateNameViolation]) @@ -110,12 +129,12 @@ def test_private_variable_names( underscore_variable_test2, ]) def test_correct_variable_name( - assert_errors, parse_ast_tree, code, correct_name, + assert_errors, parse_ast_tree, code, correct_name, default_options, ): """Testing that variable can have normal names.""" tree = parse_ast_tree(code.format(correct_name)) - visiter = WrongNameVisitor() + visiter = WrongNameVisitor(default_options) visiter.visit(tree) assert_errors(visiter, []) diff --git a/wemake_python_styleguide/checker.py b/wemake_python_styleguide/checker.py index 1d7f0758e..fe1b757bb 100644 --- a/wemake_python_styleguide/checker.py +++ b/wemake_python_styleguide/checker.py @@ -81,8 +81,7 @@ def run(self) -> Generator[CheckResult, None, None]: After all configuration is parsed and passed. """ for visitor_class in ENABLED_VISITORS: - visiter = visitor_class() - visiter.provide_options(self.options) + visiter = visitor_class(self.options) visiter.visit(self.tree) for error in visiter.errors: diff --git a/wemake_python_styleguide/logics/variables.py b/wemake_python_styleguide/logics/variables.py index 692247dc9..ae1579adb 100644 --- a/wemake_python_styleguide/logics/variables.py +++ b/wemake_python_styleguide/logics/variables.py @@ -34,7 +34,7 @@ def is_wrong_variable_name(name: str, to_check: Iterable[str]) -> bool: def is_too_short_variable_name( name: Optional[str], - min_length: int = 2, # TODO: config + min_length: int = 2, ) -> bool: """ Checks for too short variable names. diff --git a/wemake_python_styleguide/options/config.py b/wemake_python_styleguide/options/config.py index 6aa31568e..b32e798de 100644 --- a/wemake_python_styleguide/options/config.py +++ b/wemake_python_styleguide/options/config.py @@ -30,12 +30,13 @@ class Configuration(object): in one function, defaults to ``MAX_EXPRESSIONS`` - `max-arguments` - maximum allowed number of arguments in one function, defaults to ``MAX_ARGUMENTS`` + - `min-variable-length` - minimum number of chars to define a valid + variable name, defaults to ``MIN_VARIABLE_LENGTH`` """ def register_options(self, parser) -> None: # TODO: types """Registers options for our plugin.""" - # TODO: add min_variable_length option parser.add_option( '--max-returns', parse_from_config=True, @@ -67,3 +68,11 @@ def register_options(self, parser) -> None: # TODO: types default=defaults.MAX_ARGUMENTS, help='Maximum allowed number of arguments in one function.', ) + + parser.add_option( + '--min-variable-length', + parse_from_config=True, + type='int', + default=defaults.MIN_VARIABLE_LENGTH, + help='Minimum required length of the variable name.', + ) diff --git a/wemake_python_styleguide/options/defaults.py b/wemake_python_styleguide/options/defaults.py index a4bead6ba..2a9987259 100644 --- a/wemake_python_styleguide/options/defaults.py +++ b/wemake_python_styleguide/options/defaults.py @@ -14,8 +14,6 @@ too strict or too permissive. """ -# TODO: add min_variable_length value - #: Maximum number of `return` statements allowed in a single function: MAX_RETURNS = 5 @@ -27,3 +25,6 @@ #: Maximum number of arguments for functions or method, `self` is not counted: MAX_ARGUMENTS = 5 + +#: Minimum variable's name length: +MIN_VARIABLE_LENGTH = 2 diff --git a/wemake_python_styleguide/temp.py b/wemake_python_styleguide/temp.py new file mode 100644 index 000000000..e69de29bb diff --git a/wemake_python_styleguide/types.py b/wemake_python_styleguide/types.py index 25241d7f3..2de407a34 100644 --- a/wemake_python_styleguide/types.py +++ b/wemake_python_styleguide/types.py @@ -28,8 +28,8 @@ class or structure. See: https://mypy.readthedocs.io/en/latest/protocols.html """ - # TODO: add min_variable_length value max_arguments: int max_local_variables: int max_returns: int max_expressions: int + min_variable_length: int diff --git a/wemake_python_styleguide/visitors/base/visitor.py b/wemake_python_styleguide/visitors/base/visitor.py index bf25d7469..baa204697 100644 --- a/wemake_python_styleguide/visitors/base/visitor.py +++ b/wemake_python_styleguide/visitors/base/visitor.py @@ -19,19 +19,12 @@ class BaseNodeVisitor(NodeVisitor): options: ConfigurationOptions - def __init__(self) -> None: + def __init__(self, options: ConfigurationOptions) -> None: """Creates new visitor instance.""" super().__init__() + self.options = options self.errors: List[BaseStyleViolation] = [] def add_error(self, error: BaseStyleViolation) -> None: """Adds error to the visitor.""" self.errors.append(error) - - def provide_options(self, options: ConfigurationOptions) -> None: - """ - Provides options for checking. - - It is done separately to make testing easy. - """ - self.options = options diff --git a/wemake_python_styleguide/visitors/complexity/function.py b/wemake_python_styleguide/visitors/complexity/function.py index d94b6a416..4fa5721c9 100644 --- a/wemake_python_styleguide/visitors/complexity/function.py +++ b/wemake_python_styleguide/visitors/complexity/function.py @@ -12,6 +12,7 @@ ) from wemake_python_styleguide.logics.functions import is_method from wemake_python_styleguide.logics.limits import has_just_exceeded_limit +from wemake_python_styleguide.types import ConfigurationOptions from wemake_python_styleguide.visitors.base.visitor import BaseNodeVisitor @@ -26,9 +27,9 @@ class FunctionComplexityVisitor(BaseNodeVisitor): 4. Number of local variables """ - def __init__(self) -> None: + def __init__(self, options: ConfigurationOptions) -> None: """Creates config parser instance and counters for tracked metrics.""" - super().__init__() + super().__init__(options) self.expressions: DefaultDict[str, int] = defaultdict(int) self.variables: DefaultDict[str, List[str]] = defaultdict(list) @@ -124,7 +125,16 @@ def _check_function_complexity(self, node: ast.FunctionDef): self._update_expression(node) def visit_FunctionDef(self, node: ast.FunctionDef): - """Checks function's internal complexity.""" + """ + Checks function's internal complexity. + + Raises: + - TooManyExpressionsViolation + - TooManyReturnsViolation + - TooManyLocalsViolation + - TooManyArgumentsViolation + + """ self._check_arguments_count(node) self._check_function_complexity(node) self.generic_visit(node) diff --git a/wemake_python_styleguide/visitors/complexity/nested.py b/wemake_python_styleguide/visitors/complexity/nested.py index 6d6474578..53cb8afa8 100644 --- a/wemake_python_styleguide/visitors/complexity/nested.py +++ b/wemake_python_styleguide/visitors/complexity/nested.py @@ -28,6 +28,10 @@ def visit_ClassDef(self, node: ast.ClassDef): Used to find nested classes in other classes and functions. Uses ``NESTED_CLASSES_WHITELIST`` to respect some nested classes. + + Raises: + - NestedClassViolation + """ parent = getattr(node, 'parent', None) is_inside_class = isinstance(parent, ast.ClassDef) @@ -47,6 +51,10 @@ def visit_FunctionDef(self, node: ast.FunctionDef): Respected usecases for nested functions: 1. decorator 2. factory function + + Raises: + - NestedFunctionViolation + """ parent = getattr(node, 'parent', None) is_inside_function = isinstance(parent, ast.FunctionDef) @@ -56,7 +64,13 @@ def visit_FunctionDef(self, node: ast.FunctionDef): self.generic_visit(node) def visit_Lambda(self, node: ast.Lambda): - """Used to find nested ``lambda``s.""" + """ + Used to find nested ``lambda``s. + + Raises: + - NestedFunctionViolation + + """ parent = getattr(node, 'parent', None) if isinstance(parent, ast.Lambda): self.add_error(NestedFunctionViolation(node)) diff --git a/wemake_python_styleguide/visitors/wrong_class.py b/wemake_python_styleguide/visitors/wrong_class.py index 9af5e8e25..588d6c445 100644 --- a/wemake_python_styleguide/visitors/wrong_class.py +++ b/wemake_python_styleguide/visitors/wrong_class.py @@ -40,6 +40,9 @@ def visit_ClassDef(self, node: ast.ClassDef): Used to find: 1. Base class violations + Raises: + - RequiredBaseClassViolation + """ self._check_base_class(node) self.generic_visit(node) @@ -52,6 +55,10 @@ def visit_FunctionDef(self, node: ast.FunctionDef): 1. `@staticmethod` decorators 2. Detect forbiden magic methods + Raises: + - StaticMethodViolation + - BadMagicMethodViolation + """ self._check_decorators(node) self._check_magic_methods(node) diff --git a/wemake_python_styleguide/visitors/wrong_function_call.py b/wemake_python_styleguide/visitors/wrong_function_call.py index f8fb31d08..d1710450f 100644 --- a/wemake_python_styleguide/visitors/wrong_function_call.py +++ b/wemake_python_styleguide/visitors/wrong_function_call.py @@ -16,7 +16,13 @@ class WrongFunctionCallVisitor(BaseNodeVisitor): """ def visit_Call(self, node: ast.Call): - """Used to find `BAD_FUNCTIONS` calls.""" + """ + Used to find `BAD_FUNCTIONS` calls. + + Raises: + - WrongFunctionCallViolation + + """ function_name = given_function_called(node, BAD_FUNCTIONS) if function_name: self.add_error(WrongFunctionCallViolation( diff --git a/wemake_python_styleguide/visitors/wrong_import.py b/wemake_python_styleguide/visitors/wrong_import.py index bebe5babe..901bc5fbc 100644 --- a/wemake_python_styleguide/visitors/wrong_import.py +++ b/wemake_python_styleguide/visitors/wrong_import.py @@ -56,14 +56,31 @@ def _check_alias(self, node: AnyImport): self.add_error(SameAliasImportViolation(node, text=alias.name)) def visit_Import(self, node: ast.Import): - """Used to find wrong `import` statements.""" + """ + Used to find wrong `import` statements. + + Raises: + - SameAliasImportViolation + - DottedRawImportViolation + - NestedImportViolation + + """ self._check_nested_import(node) self._check_dotted_raw_import(node) self._check_alias(node) self.generic_visit(node) def visit_ImportFrom(self, node: ast.ImportFrom): - """Used to find wrong `from import` statements.""" + """ + Used to find wrong `from import` statements. + + Raises: + - SameAliasImportViolation + - NestedImportViolation + - LocalFolderImportViolation + - FutureImportViolation + + """ self._check_local_import(node) self._check_nested_import(node) self._check_future_import(node) diff --git a/wemake_python_styleguide/visitors/wrong_keyword.py b/wemake_python_styleguide/visitors/wrong_keyword.py index 15c19e256..ff5774603 100644 --- a/wemake_python_styleguide/visitors/wrong_keyword.py +++ b/wemake_python_styleguide/visitors/wrong_keyword.py @@ -24,13 +24,23 @@ def _check_exception_type(self, node: ast.Raise, exception) -> None: RaiseNotImplementedViolation(node, text=exception_name), ) + def _check_bare_raise(self, node: ast.Raise) -> None: + parent = getattr(node, 'parent', None) + if not isinstance(parent, ast.ExceptHandler): + self.add_error(BareRiseViolation(node)) + def visit_Raise(self, node: ast.Raise) -> None: - """Checks how `raise` keyword is used.""" + """ + Checks how `raise` keyword is used. + + Raises: + - RaiseNotImplementedViolation + - BareRiseViolation + + """ exception = getattr(node, 'exc', None) if not exception: - parent = getattr(node, 'parent', None) - if not isinstance(parent, ast.ExceptHandler): - self.add_error(BareRiseViolation(node)) + self._check_bare_raise(node) else: self._check_exception_type(node, exception) @@ -41,21 +51,45 @@ class WrongKeywordVisitor(BaseNodeVisitor): """This class is responsible for finding wrong keywords.""" def visit_Global(self, node: ast.Global): - """Used to find `global` keyword.""" + """ + Used to find `global` keyword. + + Raises: + - WrongKeywordViolation + + """ self.add_error(WrongKeywordViolation(node)) self.generic_visit(node) def visit_Nonlocal(self, node: ast.Nonlocal): - """Used to find `nonlocal` keyword.""" + """ + Used to find `nonlocal` keyword. + + Raises: + - WrongKeywordViolation + + """ self.add_error(WrongKeywordViolation(node)) self.generic_visit(node) def visit_Delete(self, node: ast.Delete): - """Used to find `del` keyword.""" + """ + Used to find `del` keyword. + + Raises: + - WrongKeywordViolation + + """ self.add_error(WrongKeywordViolation(node, text='del')) self.generic_visit(node) def visit_Pass(self, node: ast.Pass): - """Used to find `pass` keyword.""" + """ + Used to find `pass` keyword. + + Raises: + - WrongKeywordViolation + + """ self.add_error(WrongKeywordViolation(node)) self.generic_visit(node) diff --git a/wemake_python_styleguide/visitors/wrong_name.py b/wemake_python_styleguide/visitors/wrong_name.py index 0e3fabf0a..6f99ebed9 100644 --- a/wemake_python_styleguide/visitors/wrong_name.py +++ b/wemake_python_styleguide/visitors/wrong_name.py @@ -33,7 +33,8 @@ def _check_name(self, node: ast.AST, arg: str) -> None: if is_wrong_variable_name(arg, BAD_VARIABLE_NAMES): self.add_error(WrongVariableNameViolation(node, text=arg)) - if is_too_short_variable_name(arg): + min_length = self.options.min_variable_length + if is_too_short_variable_name(arg, min_length=min_length): self.add_error(TooShortVariableNameViolation(node, text=arg)) if is_private_variable(arg): @@ -53,7 +54,15 @@ def _check_function_signature(self, node: ast.FunctionDef) -> None: self._check_name(node, node.args.kwarg.arg) def visit_Attribute(self, node: ast.Attribute): - """Used to find wrong attribute names inside classes.""" + """ + Used to find wrong attribute names inside classes. + + Raises: + - WrongVariableNameViolation + - TooShortVariableNameViolation + - PrivateNameViolation + + """ context = getattr(node, 'ctx', None) if isinstance(context, ast.Store): @@ -62,20 +71,44 @@ def visit_Attribute(self, node: ast.Attribute): self.generic_visit(node) def visit_FunctionDef(self, node: ast.FunctionDef): - """Used to find wrong function and method parameters.""" + """ + Used to find wrong function and method parameters. + + Raises: + - WrongVariableNameViolation + - TooShortVariableNameViolation + - PrivateNameViolation + + """ name = getattr(node, 'name', None) self._check_name(node, name) self._check_function_signature(node) self.generic_visit(node) def visit_ExceptHandler(self, node: ast.ExceptHandler): - """Used to find wrong exception instances in `try/except`.""" + """ + Used to find wrong exception instances in ``try``/``except``. + + Raises: + - WrongVariableNameViolation + - TooShortVariableNameViolation + - PrivateNameViolation + + """ name = getattr(node, 'name', None) self._check_name(node, name) self.generic_visit(node) def visit_Name(self, node: ast.Name): - """Used to find wrong regular variables.""" + """ + Used to find wrong regular variables. + + Raises: + - WrongVariableNameViolation + - TooShortVariableNameViolation + - PrivateNameViolation + + """ context = getattr(node, 'ctx', None) if isinstance(context, ast.Store): self._check_name(node, node.id) @@ -83,7 +116,15 @@ def visit_Name(self, node: ast.Name): self.generic_visit(node) def visit_Import(self, node: AnyImport): - """Used to check wrong import alias names.""" + """ + Used to check wrong import alias names. + + Raises: + - WrongVariableNameViolation + - TooShortVariableNameViolation + - PrivateNameViolation + + """ for alias in node.names: if alias.asname: self._check_name(node, alias.asname) @@ -96,8 +137,7 @@ def visit_Import(self, node: AnyImport): class WrongModuleMetadataVisitor(BaseNodeVisitor): """This class finds wrong metadata information of a module.""" - def visit_Assign(self, node: ast.Assign): - """Used to find the bad metadata variable names.""" + def _check_metadata(self, node: ast.Assign): node_parent = getattr(node, 'parent', None) if not isinstance(node_parent, ast.Module): return @@ -108,3 +148,14 @@ def visit_Assign(self, node: ast.Assign): self.add_error( WrongModuleMetadataViolation(node, text=target_node_id), ) + + def visit_Assign(self, node: ast.Assign): + """ + Used to find the bad metadata variable names. + + Raises: + - WrongModuleMetadataViolation + + """ + self._check_metadata(node) + self.generic_visit(node)