Skip to content

Commit

Permalink
Merge aca9856 into 2971677
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Sep 10, 2018
2 parents 2971677 + aca9856 commit 309349d
Show file tree
Hide file tree
Showing 77 changed files with 1,447 additions and 696 deletions.
26 changes: 25 additions & 1 deletion CHANGELOG.md
Expand Up @@ -3,6 +3,30 @@
We follow Semantic Versions since the `0.1.0` release.


## Version 0.0.10 aka The Module Reaper

### Features

- Adds `WrongModuleNameViolation`, `WrongModuleMagicNameViolation`,
and `TooShortModuleNameViolation`
- Adds `--min-module-name-length` config option
- Adds a blacklist of module names
- Adds `InitModuleHasLogicsViolation`
- Adds `EmptyModuleViolation`
- Adds a whitelist of magic module names

### Bugfixes

- Fixes `Option` class to have have incorrect `type` field, now using strings
- Fixes that `WrongStringVisitor` was not activated

### Misc

- Improved typing support
- Now each error has a link to the corresponding constant (if any)
- Improved docs with links to the corresponding configuration flags


## Version 0.0.9

This is just a supporting release.
Expand Down Expand Up @@ -58,7 +82,7 @@ There are no new features introduced.
- 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
- Changed how visitors are initialized in tests
- Tests now cover nested classes' explicit bases
- Tests now cover nested classes and functions `noqa` comment

Expand Down
24 changes: 24 additions & 0 deletions README.md
Expand Up @@ -13,6 +13,30 @@ Welcome to the most opinionated linter ever.
`wemake-python-styleguide` is actually just a `flake8` plugin.
The main goal of this tool is to make our `python` code consistent.

```
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
```


## Installation

Expand Down
3 changes: 3 additions & 0 deletions docs/_pages/errors.rst
Expand Up @@ -15,3 +15,6 @@ Errors

.. automodule:: wemake_python_styleguide.errors.complexity
:members:

.. automodule:: wemake_python_styleguide.errors.modules
:members:
4 changes: 2 additions & 2 deletions pyproject.toml
@@ -1,7 +1,7 @@
[tool.poetry]
name = "wemake-python-styleguide"
version = "0.0.9"
description = "Opinionated styleguide that we use in wemake.services"
version = "0.0.10"
description = "The most opinionated linter ever, used by wemake.services"

license = "MIT"

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Expand Up @@ -24,7 +24,7 @@ accept-encodings = utf-8
[tool:pytest]
flake8-ignore =
# These function names are part of 3d party API:
wemake_python_styleguide/visitors/*.py N802
wemake_python_styleguide/visitors/ast/*.py N802
# These modules should contain a lot of classes:
wemake_python_styleguide/errors/*.py Z208
# Disable some pydocstyle checks:
Expand Down
13 changes: 11 additions & 2 deletions tests/conftest.py
Expand Up @@ -7,14 +7,22 @@
import pytest

from wemake_python_styleguide import errors
from wemake_python_styleguide.errors.base import BaseStyleViolation
from wemake_python_styleguide.errors.base import (
ASTStyleViolation,
BaseStyleViolation,
SimpleStyleViolation,
)


def _is_error_class(cls) -> bool:
base_classes = {
ASTStyleViolation, BaseStyleViolation, SimpleStyleViolation,
}

return (
inspect.isclass(cls) and
issubclass(cls, BaseStyleViolation) and
cls is not BaseStyleViolation
cls not in base_classes
)


Expand All @@ -26,6 +34,7 @@ def all_errors():
errors.general,
errors.classes,
errors.complexity,
errors.modules,
]

classes = []
Expand Down
4 changes: 2 additions & 2 deletions tests/test_errors.py
Expand Up @@ -5,12 +5,12 @@ def test_all_unique_error_codes(all_errors):
"""Ensures that all errors have unique error codes."""
codes = []
for error in all_errors:
codes.append(error._code)
codes.append(error.code)

assert len(set(codes)) == len(all_errors)


def test_all_errors_have_description_with_code(all_errors):
"""Ensures that all errors have description with error code."""
for error in all_errors:
assert error._code in error.__doc__
assert error.code in error.__doc__
7 changes: 6 additions & 1 deletion tests/test_version.py
Expand Up @@ -2,11 +2,16 @@

import subprocess

from wemake_python_styleguide.version import version


def test_call_flake8_version():
"""Checks that module is registered and visible in the meta data."""
output = subprocess.check_output(
['flake8', '--version'],
stderr=subprocess.STDOUT,
)
assert b'wemake-python-styleguide' in output

output_text = output.decode('utf-8')
assert 'wemake-python-styleguide' in output_text
assert version in output_text
13 changes: 7 additions & 6 deletions tests/test_visitors/conftest.py
Expand Up @@ -9,7 +9,7 @@

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
from wemake_python_styleguide.visitors.base import BaseNodeVisitor


@pytest.fixture(scope='session')
Expand All @@ -24,12 +24,12 @@ def factory(code: str) -> ast.AST:
@pytest.fixture(scope='session')
def assert_errors():
"""Helper function to assert visitor errors."""
def factory(visiter: BaseNodeVisitor, errors: Sequence[str]):
for index, error in enumerate(visiter.errors):
assert len(errors) > index, visiter.errors
assert error._code == errors[index]._code
def factory(visitor: BaseNodeVisitor, errors: Sequence[str]):
for index, error in enumerate(visitor.errors):
assert len(errors) > index, visitor.errors
assert error.code == errors[index].code

assert len(visiter.errors) == len(errors)
assert len(visitor.errors) == len(errors)

return factory

Expand All @@ -47,6 +47,7 @@ def options():
'max_elifs': defaults.MAX_ELIFS,
'max_module_members': defaults.MAX_MODULE_MEMBERS,
'max_methods': defaults.MAX_METHODS,
'min_module_name_length': defaults.MIN_MODULE_NAME_LENGTH,
}

Options = namedtuple('options', default_values.keys())
Expand Down
Expand Up @@ -2,7 +2,7 @@

import pytest

from wemake_python_styleguide.visitors.complexity.counts import (
from wemake_python_styleguide.visitors.ast.complexity.counts import (
MethodMembersVisitor,
TooManyMethodsViolation,
)
Expand Down Expand Up @@ -41,10 +41,10 @@ def test_method_counts_normal(
"""Testing that regular classes and functions work well."""
tree = parse_ast_tree(code)

visiter = MethodMembersVisitor(default_options)
visiter.visit(tree)
visitor = MethodMembersVisitor(default_options, tree=tree)
visitor.run()

assert_errors(visiter, [])
assert_errors(visitor, [])


@pytest.mark.parametrize('code', [
Expand All @@ -58,7 +58,7 @@ def test_method_counts_violation(
tree = parse_ast_tree(code)

option_values = options(max_methods=1)
visiter = MethodMembersVisitor(option_values)
visiter.visit(tree)
visitor = MethodMembersVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visiter, [TooManyMethodsViolation])
assert_errors(visitor, [TooManyMethodsViolation])
Expand Up @@ -2,7 +2,7 @@

import pytest

from wemake_python_styleguide.visitors.complexity.counts import (
from wemake_python_styleguide.visitors.ast.complexity.counts import (
ModuleMembersVisitor,
TooManyModuleMembersViolation,
)
Expand Down Expand Up @@ -32,10 +32,10 @@ def test_module_counts_normal(
"""Testing that classes and functions in a module work well."""
tree = parse_ast_tree(code)

visiter = ModuleMembersVisitor(default_options)
visiter.visit(tree)
visitor = ModuleMembersVisitor(default_options, None)
visitor.visit(tree)

assert_errors(visiter, [])
assert_errors(visitor, [])


@pytest.mark.parametrize('code', [
Expand All @@ -49,7 +49,7 @@ def test_module_counts_violation(
tree = parse_ast_tree(code)

option_values = options(max_module_members=1)
visiter = ModuleMembersVisitor(option_values)
visiter.visit(tree)
visitor = ModuleMembersVisitor(option_values, None)
visitor.visit(tree)

assert_errors(visiter, [TooManyModuleMembersViolation])
assert_errors(visitor, [TooManyModuleMembersViolation])
Expand Up @@ -2,7 +2,7 @@

import pytest

from wemake_python_styleguide.visitors.complexity.function import (
from wemake_python_styleguide.visitors.ast.complexity.function import (
FunctionComplexityVisitor,
TooManyElifsViolation,
)
Expand Down Expand Up @@ -45,18 +45,18 @@ def test_elif_correct_count(
"""Testing that all `if`/`elif`/`else` stuff is allowed."""
tree = parse_ast_tree(code)

visiter = FunctionComplexityVisitor(default_options)
visiter.visit(tree)
visitor = FunctionComplexityVisitor(default_options, tree=tree)
visitor.run()

assert_errors(visiter, [])
assert_errors(visitor, [])


def test_elif_incorrect_count(assert_errors, parse_ast_tree, options):
"""Testing that incorrect number of `elif` stuff is restricted."""
tree = parse_ast_tree(function_with_elifs)

option_values = options(max_elifs=1)
visiter = FunctionComplexityVisitor(option_values)
visiter.visit(tree)
visitor = FunctionComplexityVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visiter, [TooManyElifsViolation])
assert_errors(visitor, [TooManyElifsViolation])
Expand Up @@ -2,7 +2,7 @@

import pytest

from wemake_python_styleguide.visitors.complexity.function import (
from wemake_python_styleguide.visitors.ast.complexity.function import (
FunctionComplexityVisitor,
TooManyExpressionsViolation,
)
Expand All @@ -28,10 +28,10 @@ def test_expressions_correct_count(
"""Testing that expressions counted correctly."""
tree = parse_ast_tree(code)

visiter = FunctionComplexityVisitor(default_options)
visiter.visit(tree)
visitor = FunctionComplexityVisitor(default_options, tree=tree)
visitor.run()

assert_errors(visiter, [])
assert_errors(visitor, [])


@pytest.mark.parametrize('code', [
Expand All @@ -42,7 +42,7 @@ def test_expressions_wrong_count(assert_errors, parse_ast_tree, options, code):
tree = parse_ast_tree(code)

option_values = options(max_expressions=1)
visiter = FunctionComplexityVisitor(option_values)
visiter.visit(tree)
visitor = FunctionComplexityVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visiter, [TooManyExpressionsViolation])
assert_errors(visitor, [TooManyExpressionsViolation])
Expand Up @@ -2,7 +2,7 @@

import pytest

from wemake_python_styleguide.visitors.complexity.function import (
from wemake_python_styleguide.visitors.ast.complexity.function import (
FunctionComplexityVisitor,
TooManyLocalsViolation,
)
Expand Down Expand Up @@ -46,10 +46,10 @@ 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(option_values)
visiter.visit(tree)
visitor = FunctionComplexityVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visiter, [])
assert_errors(visitor, [])


@pytest.mark.parametrize('code', [
Expand All @@ -67,7 +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(option_values)
visiter.visit(tree)
visitor = FunctionComplexityVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visiter, [TooManyLocalsViolation])
assert_errors(visitor, [TooManyLocalsViolation])

0 comments on commit 309349d

Please sign in to comment.