mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-08 14:04:16 +00:00
pregenerate the pycodestyle plugin to avoid call overhead
This commit is contained in:
parent
1e5f861c52
commit
4e56fc0f6a
5 changed files with 255 additions and 37 deletions
96
bin/gen-pycodestyle-plugin
Executable file
96
bin/gen-pycodestyle-plugin
Executable file
|
|
@ -0,0 +1,96 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import inspect
|
||||||
|
import os.path
|
||||||
|
from typing import Any
|
||||||
|
from typing import Callable
|
||||||
|
from typing import Generator
|
||||||
|
from typing import NamedTuple
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
import pycodestyle
|
||||||
|
|
||||||
|
|
||||||
|
def _too_long(s: str) -> str:
|
||||||
|
if len(s) >= 80:
|
||||||
|
return f"{s} # noqa: E501"
|
||||||
|
else:
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class Call(NamedTuple):
|
||||||
|
name: str
|
||||||
|
is_generator: bool
|
||||||
|
params: Tuple[str, ...]
|
||||||
|
|
||||||
|
def to_src(self) -> str:
|
||||||
|
params_s = ", ".join(self.params)
|
||||||
|
if self.is_generator:
|
||||||
|
return _too_long(f" yield from _{self.name}({params_s})")
|
||||||
|
else:
|
||||||
|
lines = (
|
||||||
|
_too_long(f" ret = _{self.name}({params_s})"),
|
||||||
|
" if ret is not None:",
|
||||||
|
" yield ret",
|
||||||
|
)
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_func(cls, func: Callable[..., Any]) -> "Call":
|
||||||
|
spec = inspect.getfullargspec(func)
|
||||||
|
params = tuple(spec.args)
|
||||||
|
return cls(func.__name__, inspect.isgeneratorfunction(func), params)
|
||||||
|
|
||||||
|
|
||||||
|
def lines() -> Generator[str, None, None]:
|
||||||
|
logical = []
|
||||||
|
physical = []
|
||||||
|
|
||||||
|
logical = [
|
||||||
|
Call.from_func(check) for check in pycodestyle._checks["logical_line"]
|
||||||
|
]
|
||||||
|
physical = [
|
||||||
|
Call.from_func(check) for check in pycodestyle._checks["physical_line"]
|
||||||
|
]
|
||||||
|
assert not pycodestyle._checks["tree"]
|
||||||
|
|
||||||
|
yield f'"""Generated using ./bin/{os.path.basename(__file__)}."""'
|
||||||
|
yield "# fmt: off"
|
||||||
|
yield "from typing import Any"
|
||||||
|
yield "from typing import Generator"
|
||||||
|
yield "from typing import Tuple"
|
||||||
|
yield ""
|
||||||
|
imports = sorted(call.name for call in logical + physical)
|
||||||
|
for name in imports:
|
||||||
|
yield _too_long(f"from pycodestyle import {name} as _{name}")
|
||||||
|
yield ""
|
||||||
|
yield ""
|
||||||
|
|
||||||
|
yield "def pycodestyle_logical("
|
||||||
|
logical_params = {param for call in logical for param in call.params}
|
||||||
|
for param in sorted(logical_params):
|
||||||
|
yield f" {param}: Any,"
|
||||||
|
yield ") -> Generator[Tuple[int, str], None, None]:"
|
||||||
|
yield ' """Run pycodestyle logical checks."""'
|
||||||
|
for call in sorted(logical):
|
||||||
|
yield call.to_src()
|
||||||
|
yield ""
|
||||||
|
yield ""
|
||||||
|
|
||||||
|
yield "def pycodestyle_physical("
|
||||||
|
physical_params = {param for call in physical for param in call.params}
|
||||||
|
for param in sorted(physical_params):
|
||||||
|
yield f" {param}: Any,"
|
||||||
|
yield ") -> Generator[Tuple[int, str], None, None]:"
|
||||||
|
yield ' """Run pycodestyle physical checks."""'
|
||||||
|
for call in sorted(physical):
|
||||||
|
yield call.to_src()
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
for line in lines():
|
||||||
|
print(line)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
38
setup.cfg
38
setup.cfg
|
|
@ -53,42 +53,8 @@ console_scripts =
|
||||||
flake8 = flake8.main.cli:main
|
flake8 = flake8.main.cli:main
|
||||||
flake8.extension =
|
flake8.extension =
|
||||||
F = flake8.plugins.pyflakes:FlakesChecker
|
F = flake8.plugins.pyflakes:FlakesChecker
|
||||||
pycodestyle.ambiguous_identifier = pycodestyle:ambiguous_identifier
|
E = flake8.plugins.pycodestyle:pycodestyle_logical
|
||||||
pycodestyle.bare_except = pycodestyle:bare_except
|
W = flake8.plugins.pycodestyle:pycodestyle_physical
|
||||||
pycodestyle.blank_lines = pycodestyle:blank_lines
|
|
||||||
pycodestyle.break_after_binary_operator = pycodestyle:break_after_binary_operator
|
|
||||||
pycodestyle.break_before_binary_operator = pycodestyle:break_before_binary_operator
|
|
||||||
pycodestyle.comparison_negative = pycodestyle:comparison_negative
|
|
||||||
pycodestyle.comparison_to_singleton = pycodestyle:comparison_to_singleton
|
|
||||||
pycodestyle.comparison_type = pycodestyle:comparison_type
|
|
||||||
pycodestyle.compound_statements = pycodestyle:compound_statements
|
|
||||||
pycodestyle.continued_indentation = pycodestyle:continued_indentation
|
|
||||||
pycodestyle.explicit_line_join = pycodestyle:explicit_line_join
|
|
||||||
pycodestyle.extraneous_whitespace = pycodestyle:extraneous_whitespace
|
|
||||||
pycodestyle.imports_on_separate_lines = pycodestyle:imports_on_separate_lines
|
|
||||||
pycodestyle.indentation = pycodestyle:indentation
|
|
||||||
pycodestyle.maximum_doc_length = pycodestyle:maximum_doc_length
|
|
||||||
pycodestyle.maximum_line_length = pycodestyle:maximum_line_length
|
|
||||||
pycodestyle.missing_whitespace = pycodestyle:missing_whitespace
|
|
||||||
pycodestyle.missing_whitespace_after_import_keyword = pycodestyle:missing_whitespace_after_import_keyword
|
|
||||||
pycodestyle.missing_whitespace_around_operator = pycodestyle:missing_whitespace_around_operator
|
|
||||||
pycodestyle.module_imports_on_top_of_file = pycodestyle:module_imports_on_top_of_file
|
|
||||||
pycodestyle.python_3000_async_await_keywords = pycodestyle:python_3000_async_await_keywords
|
|
||||||
pycodestyle.python_3000_backticks = pycodestyle:python_3000_backticks
|
|
||||||
pycodestyle.python_3000_has_key = pycodestyle:python_3000_has_key
|
|
||||||
pycodestyle.python_3000_invalid_escape_sequence = pycodestyle:python_3000_invalid_escape_sequence
|
|
||||||
pycodestyle.python_3000_not_equal = pycodestyle:python_3000_not_equal
|
|
||||||
pycodestyle.python_3000_raise_comma = pycodestyle:python_3000_raise_comma
|
|
||||||
pycodestyle.tabs_obsolete = pycodestyle:tabs_obsolete
|
|
||||||
pycodestyle.tabs_or_spaces = pycodestyle:tabs_or_spaces
|
|
||||||
pycodestyle.trailing_blank_lines = pycodestyle:trailing_blank_lines
|
|
||||||
pycodestyle.trailing_whitespace = pycodestyle:trailing_whitespace
|
|
||||||
pycodestyle.whitespace_around_comma = pycodestyle:whitespace_around_comma
|
|
||||||
pycodestyle.whitespace_around_keywords = pycodestyle:whitespace_around_keywords
|
|
||||||
pycodestyle.whitespace_around_named_parameter_equals = pycodestyle:whitespace_around_named_parameter_equals
|
|
||||||
pycodestyle.whitespace_around_operator = pycodestyle:whitespace_around_operator
|
|
||||||
pycodestyle.whitespace_before_comment = pycodestyle:whitespace_before_comment
|
|
||||||
pycodestyle.whitespace_before_parameters = pycodestyle:whitespace_before_parameters
|
|
||||||
flake8.report =
|
flake8.report =
|
||||||
default = flake8.formatting.default:Default
|
default = flake8.formatting.default:Default
|
||||||
pylint = flake8.formatting.default:Pylint
|
pylint = flake8.formatting.default:Pylint
|
||||||
|
|
|
||||||
123
src/flake8/plugins/pycodestyle.py
Normal file
123
src/flake8/plugins/pycodestyle.py
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
"""Generated using ./bin/gen-pycodestyle-plugin."""
|
||||||
|
# fmt: off
|
||||||
|
from typing import Any
|
||||||
|
from typing import Generator
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
from pycodestyle import ambiguous_identifier as _ambiguous_identifier
|
||||||
|
from pycodestyle import bare_except as _bare_except
|
||||||
|
from pycodestyle import blank_lines as _blank_lines
|
||||||
|
from pycodestyle import break_after_binary_operator as _break_after_binary_operator # noqa: E501
|
||||||
|
from pycodestyle import break_before_binary_operator as _break_before_binary_operator # noqa: E501
|
||||||
|
from pycodestyle import comparison_negative as _comparison_negative
|
||||||
|
from pycodestyle import comparison_to_singleton as _comparison_to_singleton
|
||||||
|
from pycodestyle import comparison_type as _comparison_type
|
||||||
|
from pycodestyle import compound_statements as _compound_statements
|
||||||
|
from pycodestyle import continued_indentation as _continued_indentation
|
||||||
|
from pycodestyle import explicit_line_join as _explicit_line_join
|
||||||
|
from pycodestyle import extraneous_whitespace as _extraneous_whitespace
|
||||||
|
from pycodestyle import imports_on_separate_lines as _imports_on_separate_lines
|
||||||
|
from pycodestyle import indentation as _indentation
|
||||||
|
from pycodestyle import maximum_doc_length as _maximum_doc_length
|
||||||
|
from pycodestyle import maximum_line_length as _maximum_line_length
|
||||||
|
from pycodestyle import missing_whitespace as _missing_whitespace
|
||||||
|
from pycodestyle import missing_whitespace_after_import_keyword as _missing_whitespace_after_import_keyword # noqa: E501
|
||||||
|
from pycodestyle import missing_whitespace_around_operator as _missing_whitespace_around_operator # noqa: E501
|
||||||
|
from pycodestyle import module_imports_on_top_of_file as _module_imports_on_top_of_file # noqa: E501
|
||||||
|
from pycodestyle import python_3000_async_await_keywords as _python_3000_async_await_keywords # noqa: E501
|
||||||
|
from pycodestyle import python_3000_backticks as _python_3000_backticks
|
||||||
|
from pycodestyle import python_3000_has_key as _python_3000_has_key
|
||||||
|
from pycodestyle import python_3000_invalid_escape_sequence as _python_3000_invalid_escape_sequence # noqa: E501
|
||||||
|
from pycodestyle import python_3000_not_equal as _python_3000_not_equal
|
||||||
|
from pycodestyle import python_3000_raise_comma as _python_3000_raise_comma
|
||||||
|
from pycodestyle import tabs_obsolete as _tabs_obsolete
|
||||||
|
from pycodestyle import tabs_or_spaces as _tabs_or_spaces
|
||||||
|
from pycodestyle import trailing_blank_lines as _trailing_blank_lines
|
||||||
|
from pycodestyle import trailing_whitespace as _trailing_whitespace
|
||||||
|
from pycodestyle import whitespace_around_comma as _whitespace_around_comma
|
||||||
|
from pycodestyle import whitespace_around_keywords as _whitespace_around_keywords # noqa: E501
|
||||||
|
from pycodestyle import whitespace_around_named_parameter_equals as _whitespace_around_named_parameter_equals # noqa: E501
|
||||||
|
from pycodestyle import whitespace_around_operator as _whitespace_around_operator # noqa: E501
|
||||||
|
from pycodestyle import whitespace_before_comment as _whitespace_before_comment
|
||||||
|
from pycodestyle import whitespace_before_parameters as _whitespace_before_parameters # noqa: E501
|
||||||
|
|
||||||
|
|
||||||
|
def pycodestyle_logical(
|
||||||
|
blank_before: Any,
|
||||||
|
blank_lines: Any,
|
||||||
|
checker_state: Any,
|
||||||
|
hang_closing: Any,
|
||||||
|
indent_char: Any,
|
||||||
|
indent_level: Any,
|
||||||
|
indent_size: Any,
|
||||||
|
line_number: Any,
|
||||||
|
lines: Any,
|
||||||
|
logical_line: Any,
|
||||||
|
max_doc_length: Any,
|
||||||
|
noqa: Any,
|
||||||
|
previous_indent_level: Any,
|
||||||
|
previous_logical: Any,
|
||||||
|
previous_unindented_logical_line: Any,
|
||||||
|
tokens: Any,
|
||||||
|
verbose: Any,
|
||||||
|
) -> Generator[Tuple[int, str], None, None]:
|
||||||
|
"""Run pycodestyle logical checks."""
|
||||||
|
yield from _ambiguous_identifier(logical_line, tokens)
|
||||||
|
yield from _bare_except(logical_line, noqa)
|
||||||
|
yield from _blank_lines(logical_line, blank_lines, indent_level, line_number, blank_before, previous_logical, previous_unindented_logical_line, previous_indent_level, lines) # noqa: E501
|
||||||
|
yield from _break_after_binary_operator(logical_line, tokens)
|
||||||
|
yield from _break_before_binary_operator(logical_line, tokens)
|
||||||
|
yield from _comparison_negative(logical_line)
|
||||||
|
yield from _comparison_to_singleton(logical_line, noqa)
|
||||||
|
yield from _comparison_type(logical_line, noqa)
|
||||||
|
yield from _compound_statements(logical_line)
|
||||||
|
yield from _continued_indentation(logical_line, tokens, indent_level, hang_closing, indent_char, indent_size, noqa, verbose) # noqa: E501
|
||||||
|
yield from _explicit_line_join(logical_line, tokens)
|
||||||
|
yield from _extraneous_whitespace(logical_line)
|
||||||
|
yield from _imports_on_separate_lines(logical_line)
|
||||||
|
yield from _indentation(logical_line, previous_logical, indent_char, indent_level, previous_indent_level, indent_size) # noqa: E501
|
||||||
|
yield from _maximum_doc_length(logical_line, max_doc_length, noqa, tokens)
|
||||||
|
yield from _missing_whitespace(logical_line)
|
||||||
|
yield from _missing_whitespace_after_import_keyword(logical_line)
|
||||||
|
yield from _missing_whitespace_around_operator(logical_line, tokens)
|
||||||
|
yield from _module_imports_on_top_of_file(logical_line, indent_level, checker_state, noqa) # noqa: E501
|
||||||
|
yield from _python_3000_async_await_keywords(logical_line, tokens)
|
||||||
|
yield from _python_3000_backticks(logical_line)
|
||||||
|
yield from _python_3000_has_key(logical_line, noqa)
|
||||||
|
yield from _python_3000_invalid_escape_sequence(logical_line, tokens, noqa)
|
||||||
|
yield from _python_3000_not_equal(logical_line)
|
||||||
|
yield from _python_3000_raise_comma(logical_line)
|
||||||
|
yield from _whitespace_around_comma(logical_line)
|
||||||
|
yield from _whitespace_around_keywords(logical_line)
|
||||||
|
yield from _whitespace_around_named_parameter_equals(logical_line, tokens)
|
||||||
|
yield from _whitespace_around_operator(logical_line)
|
||||||
|
yield from _whitespace_before_comment(logical_line, tokens)
|
||||||
|
yield from _whitespace_before_parameters(logical_line, tokens)
|
||||||
|
|
||||||
|
|
||||||
|
def pycodestyle_physical(
|
||||||
|
indent_char: Any,
|
||||||
|
line_number: Any,
|
||||||
|
lines: Any,
|
||||||
|
max_line_length: Any,
|
||||||
|
multiline: Any,
|
||||||
|
noqa: Any,
|
||||||
|
physical_line: Any,
|
||||||
|
total_lines: Any,
|
||||||
|
) -> Generator[Tuple[int, str], None, None]:
|
||||||
|
"""Run pycodestyle physical checks."""
|
||||||
|
ret = _maximum_line_length(physical_line, max_line_length, multiline, line_number, noqa) # noqa: E501
|
||||||
|
if ret is not None:
|
||||||
|
yield ret
|
||||||
|
ret = _tabs_obsolete(physical_line)
|
||||||
|
if ret is not None:
|
||||||
|
yield ret
|
||||||
|
ret = _tabs_or_spaces(physical_line, indent_char)
|
||||||
|
if ret is not None:
|
||||||
|
yield ret
|
||||||
|
ret = _trailing_blank_lines(physical_line, lines, line_number, total_lines)
|
||||||
|
if ret is not None:
|
||||||
|
yield ret
|
||||||
|
ret = _trailing_whitespace(physical_line)
|
||||||
|
if ret is not None:
|
||||||
|
yield ret
|
||||||
|
|
@ -104,7 +104,7 @@ def test_local_plugin_can_add_option(local_config):
|
||||||
|
|
||||||
args = aggregator.aggregate_options(option_manager, cfg, cfg_dir, argv)
|
args = aggregator.aggregate_options(option_manager, cfg, cfg_dir, argv)
|
||||||
|
|
||||||
assert args.extended_default_select == {"XE", "F", "E", "C90"}
|
assert args.extended_default_select == {"XE", "F", "E", "W", "C90"}
|
||||||
assert args.anopt == "foo"
|
assert args.anopt == "foo"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
33
tests/unit/plugins/pycodestyle_test.py
Normal file
33
tests/unit/plugins/pycodestyle_test.py
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import importlib.machinery
|
||||||
|
import importlib.util
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
import flake8.plugins.pycodestyle
|
||||||
|
|
||||||
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def test_up_to_date():
|
||||||
|
"""Validate that the generated pycodestyle plugin is up to date.
|
||||||
|
|
||||||
|
We generate two "meta" plugins for pycodestyle to avoid calling overhead.
|
||||||
|
|
||||||
|
To regenerate run:
|
||||||
|
|
||||||
|
./bin/gen-pycodestyle-plugin > src/flake8/plugins/pycodestyle.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
path = os.path.join(HERE, "../../../bin/gen-pycodestyle-plugin")
|
||||||
|
name = os.path.basename(path)
|
||||||
|
loader = importlib.machinery.SourceFileLoader(name, path)
|
||||||
|
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||||
|
assert spec is not None
|
||||||
|
mod = importlib.util.module_from_spec(spec)
|
||||||
|
loader.exec_module(mod)
|
||||||
|
|
||||||
|
expected = "".join(f"{line}\n" for line in mod.lines())
|
||||||
|
|
||||||
|
with open(flake8.plugins.pycodestyle.__file__) as f:
|
||||||
|
contents = f.read()
|
||||||
|
|
||||||
|
assert contents == expected
|
||||||
Loading…
Add table
Add a link
Reference in a new issue