Skip to content

Commit

Permalink
Adds "raises" policy
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Sep 3, 2018
1 parent 7673dd2 commit cf457d4
Show file tree
Hide file tree
Showing 45 changed files with 460 additions and 212 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 13 additions & 1 deletion docs/_pages/errors.rst
Original file line number Diff line number Diff line change
@@ -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:
9 changes: 5 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
)

Expand Down
4 changes: 4 additions & 0 deletions tests/fixtures/noqa.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -25,3 +27,5 @@ class BadClass: # noqa: Z302
def some_static(): ...

def __del__(self, *args, **kwargs): ... # noqa: Z301

class Nested(object): ... # noqa: Z201
5 changes: 3 additions & 2 deletions tests/test_checkers/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion tests/test_checkers/test_noqa.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@ def test_noqa_fixture(absolute_path):
)
stdout, _ = process.communicate()

print(stdout)
assert stdout.count(b'Z') == 0
34 changes: 34 additions & 0 deletions tests/test_visitors/conftest.py
Original file line number Diff line number Diff line change
@@ -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():
Expand All @@ -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()
36 changes: 0 additions & 36 deletions tests/test_visitors/test_complexity/conftest.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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, [])
Expand All @@ -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])
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand All @@ -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, [])
Expand All @@ -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, [])
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand All @@ -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.
Expand All @@ -75,21 +77,21 @@ 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:
def container(self):
lazy_value = lambda: 12
""")

visiter = NestedComplexityVisitor()
visiter = NestedComplexityVisitor(default_options)
visiter.visit(tree)

assert_errors(visiter, [])
Loading

0 comments on commit cf457d4

Please sign in to comment.