Skip to content

Commit

Permalink
Remove --i-control-code config option
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Dec 26, 2024
1 parent 7d6bc09 commit be53355
Show file tree
Hide file tree
Showing 28 changed files with 171 additions and 587 deletions.
2 changes: 1 addition & 1 deletion .importlinter
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ source_modules =

forbidden_modules =
# Our sub-API parts:
wemake_python_styleguide.options
wemake_python_styleguide.options.config
wemake_python_styleguide.transformations
wemake_python_styleguide.presets

Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ Semantic versioning in our case means:
- **Breaking**: Removes `WPS526`, because is covered by `ruff` linter
- **Breaking**: Removes `WPS521`, because is covered by `ruff` linter
- **Breaking**: Removes `WPS609`, because is covered by `pylint` linter
- **Breaking**: Removes `--i-control-code` setting,
if you want to disable some violations, just use `# noqa` or `--ignore`
with code that you want to exclude, there's no need
to create one more way of disabling some specific violations

## Features

Expand All @@ -111,6 +115,7 @@ Semantic versioning in our case means:
- Allows any number of function parameters
in `@overload` definitions for `WPS211`, #1957
- Allows using multiline strings when placed on separate lines, #3056
- Allows using `hasattr` builtin function, #2228
- Disallows using `is not` and `not in` as negated conditions in `WPS504`, #2617
- Allows all branches in `if/elif/else` to be negated in `WPS504`, #2617
- Adds a new rule to forbid `lambda` assigns to special attributes, #1733
Expand All @@ -124,6 +129,8 @@ Semantic versioning in our case means:
- Adds a new rule to find useless ternary expressions, #1706
- Adds a new rule to forbid `raise SystemError`, use `sys.exit` instead, #1786
- Adds a new rule to forbid extra syntax in `match ...` subjects, #3217
- Adds new `--allowed-module-metadata` and `--forbidden-module-metadata`
configuration options for `WPS410`, #3060
- Adds support to run `wemake-python-styleguide` as a `pre-commit` hook, #2588
- GitHub Action can now use `cwd:` parameter to specify
where your configuration file is, #2474
Expand Down
19 changes: 4 additions & 15 deletions docs/pages/api/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,22 +187,11 @@ Writing end-to-end tests
In end-to-end tests we check that our visitor, violation and business logic
work correctly together all the way from flake8 config file to its output.

To check all supported violations, we have two modules containing code which
raises them: ``noqa.py`` and ``noqa_controlled.py``. The first is for all
possible violations while the second is only for those which may be tweaked
using ``i_control_code`` option. If violation may be ignored (or instead,
raised) with ``i_control_code``, the appropriate piece of code should be
added to both modules.
To check all supported violations, a module containing code which
raises them: ``noqa.py``. It is for all
possible violations.

The next thing is test itself which should reside in
``tests/test_checker/test_noqa.py`` module. The main test functions are
written already, so probably the only thing to do is to put the violation
code into either ``SHOULD_BE_RAISED``, or ``SHOULD_BE_RAISED_NO_CONTROL``
container, or into both. For example, if the violation is raised with
``i_control_code=True``, it must be placed into ``SHOULD_BE_RAISED``
with value ``1`` and into ``SHOULD_BE_RAISED_NO_CONTROL`` with value ``0``.
By doing this we check that the violation is raised in one situation and
is not raised in opposite one. If the violation is ignored when
``i_control_code=True``, swap ``0`` and ``1`` it containers. If the
violation cannot be tweaked with ``i_control_code`` it should only be
put into ``SHOULD_BE_RAISED`` container with appropriate value.
code into either ``SHOULD_BE_RAISED``.
15 changes: 3 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,9 @@ addopts = [
"--cov-fail-under=100",
# pytest-xdist
"-n=auto",
]

norecursedirs = [
"tests/fixtures",
"*.egg",
".eggs",
"dist",
"build",
"docs",
".tox",
".git",
"__pycache__",
# Custom ignored dirs with bad code:
"--ignore=tests/fixtures",
"--ignore=docs",
]

[tool.coverage.run]
Expand Down
12 changes: 0 additions & 12 deletions tests/fixtures/noqa/noqa_controlled.py

This file was deleted.

12 changes: 0 additions & 12 deletions tests/plugins/violations.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,6 @@ def all_violations():
return all_errors_container


@pytest.fixture(scope=_SESSION_SCOPE)
def all_controlled_violations():
"""Loads all violations which may be tweaked using `i_control_code`."""
return [
violation_class
for module_classes in _load_all_violation_classes().values()
for violation_class in module_classes
if '--i-control-code' in violation_class.__doc__
and not violation_class.disabled_since
]


@pytest.fixture(scope=_SESSION_SCOPE)
def all_module_violations():
"""Loads all violations from the package."""
Expand Down
35 changes: 0 additions & 35 deletions tests/test_checker/test_noqa.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,6 @@
},
)

# Violations which may be tweaked by `i_control_code` option:
SHOULD_BE_RAISED_NO_CONTROL = types.MappingProxyType(
{
'WPS412': 0,
'WPS413': 0,
},
)


def _assert_errors_count_in_output(
output,
Expand Down Expand Up @@ -368,33 +360,6 @@ def test_noqa_fixture_disabled(
)


def test_noqa_fixture_disabled_no_control(
absolute_path,
all_controlled_violations,
):
"""End-to-End test to check rules controlled by `i_control_code` option."""
process = subprocess.Popen(
[
'flake8',
'--i-dont-control-code',
'--disable-noqa',
'--isolated',
'--select',
'WPS',
absolute_path('fixtures', 'noqa', 'noqa_controlled.py'),
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
encoding='utf8',
)
stdout, stderr = process.communicate()

assert not stderr
assert not stdout
assert len(SHOULD_BE_RAISED_NO_CONTROL) == len(all_controlled_violations)


def test_noqa_fixture(absolute_path):
"""End-to-End test to check that `noqa` works."""
process = subprocess.Popen(
Expand Down
30 changes: 0 additions & 30 deletions tests/test_options/test_option_values/test_i_control_code.py

This file was deleted.

28 changes: 0 additions & 28 deletions tests/test_visitors/test_ast/test_modules/test_empty_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,31 +86,3 @@ def test_init_with_logic(
visitor.run()

assert_errors(visitor, [InitModuleHasLogicViolation])


@pytest.mark.parametrize(
'code',
[
module_with_imports,
module_with_one_import,
module_with_logic,
],
)
def test_init_with_logic_without_control(
assert_errors,
parse_ast_tree,
code,
options,
):
"""Testing that `__init__` with logic is restricted."""
tree = parse_ast_tree(code)

option_values = options(i_control_code=False)
visitor = EmptyModuleContentsVisitor(
option_values,
tree=tree,
filename='__init__.py',
)
visitor.run()

assert_errors(visitor, [])
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,6 @@ def {0}(name):
"""


@pytest.mark.parametrize(
'code',
[
module_level_method,
class_level_method,
],
)
@pytest.mark.parametrize('function_names', MAGIC_MODULE_NAMES_BLACKLIST)
def test_right_magic_used(
assert_errors,
code,
parse_ast_tree,
options,
function_names,
):
"""Testing magic methods with logic is restricted."""
tree = parse_ast_tree(code.format(function_names))
option_values = options(i_control_code=False)

visitor = MagicModuleFunctionsVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visitor, [])


@pytest.mark.parametrize(
'code',
[
Expand Down
54 changes: 52 additions & 2 deletions tests/test_visitors/test_ast/test_naming/test_module_metadata.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import pytest

from wemake_python_styleguide.options.defaults import FORBIDDEN_MODULE_METADATA
from wemake_python_styleguide.violations.best_practices import (
WrongModuleMetadataViolation,
)
from wemake_python_styleguide.visitors.ast.naming.variables import (
MODULE_METADATA_VARIABLES_BLACKLIST,
WrongModuleMetadataVisitor,
)

Expand All @@ -27,7 +27,7 @@ class ORM:
"""


@pytest.mark.parametrize('bad_name', MODULE_METADATA_VARIABLES_BLACKLIST)
@pytest.mark.parametrize('bad_name', FORBIDDEN_MODULE_METADATA)
@pytest.mark.parametrize(
'code',
[
Expand Down Expand Up @@ -97,3 +97,53 @@ def test_correct_startup_metadata(
visitor.run()

assert_errors(visitor, [])


@pytest.mark.parametrize(
'code',
[
module_metadata,
module_type_metadata,
],
)
def test_module_metadata_allowed_list(
assert_errors,
parse_ast_tree,
code,
options,
):
"""Testing that configuration with allowed module has the priority."""
option_values = options(
forbidden_module_metadata=('__all__', '__author__'),
allowed_module_metadata=('__all__',),
)
tree = parse_ast_tree(code.format('__all__'))

visitor = WrongModuleMetadataVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visitor, [])


@pytest.mark.parametrize(
'code',
[
module_metadata,
module_type_metadata,
],
)
def test_module_metadata_forbidden_list(
assert_errors,
parse_ast_tree,
code,
options,
):
"""Testing that startup hook is allowed."""
option_values = options(forbidden_module_metadata=('custom',))
for metadata_value in ('__all__', 'custom'):
tree = parse_ast_tree(code.format(metadata_value))

visitor = WrongModuleMetadataVisitor(option_values, tree=tree)
visitor.run()

assert_errors(visitor, [WrongModuleMetadataViolation])
13 changes: 9 additions & 4 deletions wemake_python_styleguide/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@
"""

from __future__ import annotations

import ast
import tokenize
import traceback
from collections.abc import Iterator, Sequence
from typing import ClassVar, TypeAlias, final
from typing import TYPE_CHECKING, ClassVar, TypeAlias, final

from flake8.options.manager import OptionManager

Expand All @@ -55,6 +57,9 @@
from wemake_python_styleguide.violations import system
from wemake_python_styleguide.visitors import base

if TYPE_CHECKING:
from wemake_python_styleguide.options.validation import ValidatedOptions

VisitorClass: TypeAlias = type[base.BaseVisitor]


Expand All @@ -73,7 +78,7 @@ class Checker:
:class:`wemake_python_styleguide.options.config.Configuration`.
options: option structure passed by ``flake8``:
:class:`wemake_python_styleguide.types.ConfigurationOptions`.
:class:`wemake_python_styleguide.options.validation.ValidatedOptions`.
visitors: :term:`preset` of visitors that are run by this checker.
Expand All @@ -82,7 +87,7 @@ class Checker:
name: ClassVar[str] = pkg_version.pkg_name
version: ClassVar[str] = pkg_version.pkg_version

options: types.ConfigurationOptions
options: ValidatedOptions
config = Configuration()

_visitors: ClassVar[Sequence[VisitorClass]] = (
Expand Down Expand Up @@ -132,7 +137,7 @@ def add_options(cls, parser: OptionManager) -> None:
cls.config.register_options(parser)

@classmethod
def parse_options(cls, options: types.ConfigurationOptions) -> None:
def parse_options(cls, options: ValidatedOptions) -> None:
"""Parses registered options for providing them to each visitor."""
cls.options = validate_options(options)

Expand Down
Loading

0 comments on commit be53355

Please sign in to comment.