Skip to content

Commit

Permalink
moved class-level constants to constants.py (#1234)
Browse files Browse the repository at this point in the history
* moved class-level constants to constants.py

* added documentation

* Removed self from new constants

* Removed unused imports and formatted code

* Update test_condition_counts.py

Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
  • Loading branch information
JazabC and sobolevn committed Mar 6, 2020
1 parent cf3aef9 commit fe020a9
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,35 +89,6 @@ def test_module_condition_counts_normal(
assert_errors(visitor, [])


@pytest.mark.parametrize('code', [
assignment,
condition_with_single_if,
condition_with_single_if_multiline,
condition_with_several_ifs,
condition_with_several_elifs,
condition_inline,
condition_with_inline_for,
while_with_condition,
])
def test_module_condition_counts_violation(
monkeypatch,
assert_errors,
assert_error_text,
parse_ast_tree,
code,
default_options,
):
"""Testing that violations are raised when reaching max value."""
tree = parse_ast_tree(code)

monkeypatch.setattr(ConditionsVisitor, '_max_conditions', 1)
visitor = ConditionsVisitor(default_options, tree=tree)
visitor.run()

assert_errors(visitor, [TooManyConditionsViolation])
assert_error_text(visitor, '2', baseline=1)


@pytest.mark.parametrize('code', [
complex_assignment,
complex_condition,
Expand Down
12 changes: 12 additions & 0 deletions wemake_python_styleguide/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,18 @@
#: Maximum length of ``yield`` ``tuple`` expressions.
MAX_LEN_YIELD_TUPLE: Final = 5

#: Maximum number of compare nodes in a single expression.
MAX_COMPARES: Final = 2

#: Maximum number of conditions in a single ``if`` or ``while`` statement.
MAX_CONDITIONS: Final = 4

#: Maximum number of `elif` blocks in a single `if` condition:
MAX_ELIFS: Final = 3

#: Maximum number of ``except`` cases in a single ``try`` clause.
MAX_EXCEPT_CASES: Final = 3

#: Approximate constants which real values should be imported from math module.
MATH_APPROXIMATE_CONSTANTS: Final = frozenset((
math.pi,
Expand Down
9 changes: 9 additions & 0 deletions wemake_python_styleguide/violations/complexity.py
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,9 @@ class TooManyConditionsViolation(ASTViolation):
"""
Forbids to have conditions with too many logical operators.
We use :str:`wemake_python_styleguide.constants.MAX_CONDITIONS`
as a default value.
Reasoning:
When reading through the complex conditions you will fail
to understand all the possible branches. And you will end up putting
Expand All @@ -758,6 +761,9 @@ class TooManyElifsViolation(ASTViolation):
"""
Forbids to use many ``elif`` branches.
We use :str:`wemake_python_styleguide.constants.MAX_ELIFS`
as a default value.
Reasoning:
This rule is specifically important because of many ``elif``
branches indicate a complex flow in your design:
Expand Down Expand Up @@ -815,6 +821,9 @@ class TooManyExceptCasesViolation(ASTViolation):
"""
Forbids to have too many ``except`` cases in a single ``try`` clause.
We use :str:`wemake_python_styleguide.constants.MAX_EXCEPT_CASES`
as a default value.
Reasoning:
Handling too many exceptions in a single place
is a good indicator of a bad design.
Expand Down
36 changes: 15 additions & 21 deletions wemake_python_styleguide/visitors/ast/complexity/counts.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import ast
from collections import defaultdict
from typing import Callable, ClassVar, DefaultDict, List, Union
from typing import Callable, DefaultDict, List, Union

from typing_extensions import final

from wemake_python_styleguide.constants import MAX_LEN_YIELD_TUPLE
from wemake_python_styleguide.constants import (
MAX_COMPARES,
MAX_CONDITIONS,
MAX_ELIFS,
MAX_EXCEPT_CASES,
MAX_LEN_YIELD_TUPLE,
)
from wemake_python_styleguide.logic.nodes import get_parent
from wemake_python_styleguide.logic.tree.functions import is_method
from wemake_python_styleguide.types import (
Expand Down Expand Up @@ -173,12 +179,6 @@ def _post_visit(self) -> None:
class ConditionsVisitor(BaseNodeVisitor):
"""Checks booleans for condition counts."""

#: Maximum number of conditions in a single ``if`` or ``while`` statement.
_max_conditions: ClassVar[int] = 4

#: Maximum number of compare nodes in a single expression.
_max_compares: ClassVar[int] = 2

def visit_BoolOp(self, node: ast.BoolOp) -> None:
"""
Counts the number of conditions.
Expand Down Expand Up @@ -212,12 +212,12 @@ def _count_conditions(self, node: ast.BoolOp) -> int:

def _check_conditions(self, node: ast.BoolOp) -> None:
conditions_count = self._count_conditions(node)
if conditions_count > self._max_conditions:
if conditions_count > MAX_CONDITIONS:
self.add_violation(
complexity.TooManyConditionsViolation(
node,
text=str(conditions_count),
baseline=self._max_conditions,
baseline=MAX_CONDITIONS,
),
)

Expand All @@ -226,7 +226,7 @@ def _check_compares(self, node: ast.Compare) -> None:
is_all_notequals = all(isinstance(op, ast.NotEq) for op in node.ops)
can_be_longer = is_all_notequals or is_all_equals

threshold = self._max_compares
threshold = MAX_COMPARES
if can_be_longer:
threshold += 1

Expand All @@ -244,9 +244,6 @@ def _check_compares(self, node: ast.Compare) -> None:
class ElifVisitor(BaseNodeVisitor):
"""Checks the number of ``elif`` cases inside conditions."""

#: Maximum number of `elif` blocks in a single `if` condition:
_max_elifs: ClassVar[int] = 3

def __init__(self, *args, **kwargs) -> None:
"""Creates internal ``elif`` counter."""
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -288,12 +285,12 @@ def _check_elifs(self, node: ast.If) -> None:
def _post_visit(self):
for root, children in self._if_children.items():
real_children_length = len(set(children))
if real_children_length > self._max_elifs:
if real_children_length > MAX_ELIFS:
self.add_violation(
complexity.TooManyElifsViolation(
root,
text=str(real_children_length),
baseline=self._max_elifs,
baseline=MAX_ELIFS,
),
)

Expand All @@ -302,9 +299,6 @@ def _post_visit(self):
class TryExceptVisitor(BaseNodeVisitor):
"""Visits all try/except nodes to ensure that they are not too complex."""

#: Maximum number of ``except`` cases in a single ``try`` clause.
_max_except_cases: ClassVar[int] = 3

def visit_Try(self, node: ast.Try) -> None:
"""
Ensures that try/except is correct.
Expand All @@ -319,12 +313,12 @@ def visit_Try(self, node: ast.Try) -> None:
self.generic_visit(node)

def _check_except_count(self, node: ast.Try) -> None:
if len(node.handlers) > self._max_except_cases:
if len(node.handlers) > MAX_EXCEPT_CASES:
self.add_violation(
complexity.TooManyExceptCasesViolation(
node,
text=str(len(node.handlers)),
baseline=self._max_except_cases,
baseline=MAX_EXCEPT_CASES,
),
)

Expand Down

0 comments on commit fe020a9

Please sign in to comment.