mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-11 23:34:17 +00:00
Merge pull request #1510 from asottile/type_legacy_pt2
type the rest of the legacy api
This commit is contained in:
commit
f0fb786883
3 changed files with 183 additions and 181 deletions
|
|
@ -106,9 +106,5 @@ disallow_untyped_defs = true
|
||||||
no_implicit_optional = true
|
no_implicit_optional = true
|
||||||
warn_unused_ignores = true
|
warn_unused_ignores = true
|
||||||
|
|
||||||
# TODO: fix these
|
|
||||||
[mypy-flake8.api.legacy]
|
|
||||||
disallow_untyped_defs = false
|
|
||||||
|
|
||||||
[mypy-tests.*]
|
[mypy-tests.*]
|
||||||
disallow_untyped_defs = false
|
disallow_untyped_defs = false
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,13 @@ In 3.0 we no longer have an "engine" module but we maintain the API from it.
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
import os.path
|
||||||
|
from typing import Any
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from typing import Optional
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
import flake8
|
import flake8
|
||||||
|
from flake8.discover_files import expand_paths
|
||||||
from flake8.formatting import base as formatter
|
from flake8.formatting import base as formatter
|
||||||
from flake8.main import application as app
|
from flake8.main import application as app
|
||||||
from flake8.options import config
|
from flake8.options import config
|
||||||
|
|
@ -19,156 +23,6 @@ LOG = logging.getLogger(__name__)
|
||||||
__all__ = ("get_style_guide",)
|
__all__ = ("get_style_guide",)
|
||||||
|
|
||||||
|
|
||||||
def get_style_guide(**kwargs):
|
|
||||||
r"""Provision a StyleGuide for use.
|
|
||||||
|
|
||||||
:param \*\*kwargs:
|
|
||||||
Keyword arguments that provide some options for the StyleGuide.
|
|
||||||
:returns:
|
|
||||||
An initialized StyleGuide
|
|
||||||
:rtype:
|
|
||||||
:class:`StyleGuide`
|
|
||||||
"""
|
|
||||||
application = app.Application()
|
|
||||||
prelim_opts, remaining_args = application.parse_preliminary_options([])
|
|
||||||
flake8.configure_logging(prelim_opts.verbose, prelim_opts.output_file)
|
|
||||||
|
|
||||||
cfg, cfg_dir = config.load_config(
|
|
||||||
config=prelim_opts.config,
|
|
||||||
extra=prelim_opts.append_config,
|
|
||||||
isolated=prelim_opts.isolated,
|
|
||||||
)
|
|
||||||
|
|
||||||
application.find_plugins(cfg, cfg_dir, prelim_opts.enable_extensions)
|
|
||||||
application.register_plugin_options()
|
|
||||||
application.parse_configuration_and_cli(cfg, cfg_dir, remaining_args)
|
|
||||||
# We basically want application.initialize to be called but with these
|
|
||||||
# options set instead before we make our formatter, notifier, internal
|
|
||||||
# style guide and file checker manager.
|
|
||||||
options = application.options
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
try:
|
|
||||||
getattr(options, key)
|
|
||||||
setattr(options, key, value)
|
|
||||||
except AttributeError:
|
|
||||||
LOG.error('Could not update option "%s"', key)
|
|
||||||
application.make_formatter()
|
|
||||||
application.make_guide()
|
|
||||||
application.make_file_checker_manager()
|
|
||||||
return StyleGuide(application)
|
|
||||||
|
|
||||||
|
|
||||||
class StyleGuide:
|
|
||||||
"""Public facing object that mimic's Flake8 2.0's StyleGuide.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
There are important changes in how this object behaves compared to
|
|
||||||
the StyleGuide object provided in Flake8 2.x.
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
This object should not be instantiated directly by users.
|
|
||||||
|
|
||||||
.. versionchanged:: 3.0.0
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, application):
|
|
||||||
"""Initialize our StyleGuide."""
|
|
||||||
self._application = application
|
|
||||||
self._file_checker_manager = application.file_checker_manager
|
|
||||||
|
|
||||||
@property
|
|
||||||
def options(self) -> argparse.Namespace:
|
|
||||||
"""Return application's options.
|
|
||||||
|
|
||||||
An instance of :class:`argparse.Namespace` containing parsed options.
|
|
||||||
"""
|
|
||||||
return self._application.options
|
|
||||||
|
|
||||||
@property
|
|
||||||
def paths(self):
|
|
||||||
"""Return the extra arguments passed as paths."""
|
|
||||||
return self._application.paths
|
|
||||||
|
|
||||||
def check_files(self, paths=None):
|
|
||||||
"""Run collected checks on the files provided.
|
|
||||||
|
|
||||||
This will check the files passed in and return a :class:`Report`
|
|
||||||
instance.
|
|
||||||
|
|
||||||
:param list paths:
|
|
||||||
List of filenames (or paths) to check.
|
|
||||||
:returns:
|
|
||||||
Object that mimic's Flake8 2.0's Reporter class.
|
|
||||||
:rtype:
|
|
||||||
flake8.api.legacy.Report
|
|
||||||
"""
|
|
||||||
self._application.options.filenames = paths
|
|
||||||
self._application.run_checks()
|
|
||||||
self._application.report_errors()
|
|
||||||
return Report(self._application)
|
|
||||||
|
|
||||||
def excluded(self, filename, parent=None):
|
|
||||||
"""Determine if a file is excluded.
|
|
||||||
|
|
||||||
:param str filename:
|
|
||||||
Path to the file to check if it is excluded.
|
|
||||||
:param str parent:
|
|
||||||
Name of the parent directory containing the file.
|
|
||||||
:returns:
|
|
||||||
True if the filename is excluded, False otherwise.
|
|
||||||
:rtype:
|
|
||||||
bool
|
|
||||||
"""
|
|
||||||
return self._file_checker_manager.is_path_excluded(filename) or (
|
|
||||||
parent
|
|
||||||
and self._file_checker_manager.is_path_excluded(
|
|
||||||
os.path.join(parent, filename)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def init_report(self, reporter=None):
|
|
||||||
"""Set up a formatter for this run of Flake8."""
|
|
||||||
if reporter is None:
|
|
||||||
return
|
|
||||||
if not issubclass(reporter, formatter.BaseFormatter):
|
|
||||||
raise ValueError(
|
|
||||||
"Report should be subclass of "
|
|
||||||
"flake8.formatter.BaseFormatter."
|
|
||||||
)
|
|
||||||
self._application.formatter = None
|
|
||||||
self._application.make_formatter(reporter)
|
|
||||||
self._application.guide = None
|
|
||||||
# NOTE(sigmavirus24): This isn't the intended use of
|
|
||||||
# Application#make_guide but it works pretty well.
|
|
||||||
# Stop cringing... I know it's gross.
|
|
||||||
self._application.make_guide()
|
|
||||||
self._application.file_checker_manager = None
|
|
||||||
self._application.make_file_checker_manager()
|
|
||||||
|
|
||||||
def input_file(self, filename, lines=None, expected=None, line_offset=0):
|
|
||||||
"""Run collected checks on a single file.
|
|
||||||
|
|
||||||
This will check the file passed in and return a :class:`Report`
|
|
||||||
instance.
|
|
||||||
|
|
||||||
:param str filename:
|
|
||||||
The path to the file to check.
|
|
||||||
:param list lines:
|
|
||||||
Ignored since Flake8 3.0.
|
|
||||||
:param expected:
|
|
||||||
Ignored since Flake8 3.0.
|
|
||||||
:param int line_offset:
|
|
||||||
Ignored since Flake8 3.0.
|
|
||||||
:returns:
|
|
||||||
Object that mimic's Flake8 2.0's Reporter class.
|
|
||||||
:rtype:
|
|
||||||
flake8.api.legacy.Report
|
|
||||||
"""
|
|
||||||
return self.check_files([filename])
|
|
||||||
|
|
||||||
|
|
||||||
class Report:
|
class Report:
|
||||||
"""Public facing object that mimic's Flake8 2.0's API.
|
"""Public facing object that mimic's Flake8 2.0's API.
|
||||||
|
|
||||||
|
|
@ -213,3 +67,175 @@ class Report:
|
||||||
f"{s.count} {s.error_code} {s.message}"
|
f"{s.count} {s.error_code} {s.message}"
|
||||||
for s in self._stats.statistics_for(violation)
|
for s in self._stats.statistics_for(violation)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class StyleGuide:
|
||||||
|
"""Public facing object that mimic's Flake8 2.0's StyleGuide.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
There are important changes in how this object behaves compared to
|
||||||
|
the StyleGuide object provided in Flake8 2.x.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
This object should not be instantiated directly by users.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.0.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, application: app.Application) -> None:
|
||||||
|
"""Initialize our StyleGuide."""
|
||||||
|
self._application = application
|
||||||
|
self._file_checker_manager = application.file_checker_manager
|
||||||
|
|
||||||
|
@property
|
||||||
|
def options(self) -> argparse.Namespace:
|
||||||
|
"""Return application's options.
|
||||||
|
|
||||||
|
An instance of :class:`argparse.Namespace` containing parsed options.
|
||||||
|
"""
|
||||||
|
assert self._application.options is not None
|
||||||
|
return self._application.options
|
||||||
|
|
||||||
|
@property
|
||||||
|
def paths(self) -> List[str]:
|
||||||
|
"""Return the extra arguments passed as paths."""
|
||||||
|
assert self._application.options is not None
|
||||||
|
return self._application.options.filenames
|
||||||
|
|
||||||
|
def check_files(self, paths: Optional[List[str]] = None) -> Report:
|
||||||
|
"""Run collected checks on the files provided.
|
||||||
|
|
||||||
|
This will check the files passed in and return a :class:`Report`
|
||||||
|
instance.
|
||||||
|
|
||||||
|
:param list paths:
|
||||||
|
List of filenames (or paths) to check.
|
||||||
|
:returns:
|
||||||
|
Object that mimic's Flake8 2.0's Reporter class.
|
||||||
|
:rtype:
|
||||||
|
flake8.api.legacy.Report
|
||||||
|
"""
|
||||||
|
assert self._application.options is not None
|
||||||
|
self._application.options.filenames = paths
|
||||||
|
self._application.run_checks()
|
||||||
|
self._application.report_errors()
|
||||||
|
return Report(self._application)
|
||||||
|
|
||||||
|
def excluded(self, filename: str, parent: Optional[str] = None) -> bool:
|
||||||
|
"""Determine if a file is excluded.
|
||||||
|
|
||||||
|
:param str filename:
|
||||||
|
Path to the file to check if it is excluded.
|
||||||
|
:param str parent:
|
||||||
|
Name of the parent directory containing the file.
|
||||||
|
:returns:
|
||||||
|
True if the filename is excluded, False otherwise.
|
||||||
|
:rtype:
|
||||||
|
bool
|
||||||
|
"""
|
||||||
|
|
||||||
|
def excluded(path: str) -> bool:
|
||||||
|
paths = tuple(
|
||||||
|
expand_paths(
|
||||||
|
paths=[path],
|
||||||
|
stdin_display_name=self.options.stdin_display_name,
|
||||||
|
filename_patterns=self.options.filename,
|
||||||
|
exclude=self.options.exclude,
|
||||||
|
is_running_from_diff=self.options.diff,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return not paths
|
||||||
|
|
||||||
|
return excluded(filename) or (
|
||||||
|
parent is not None and excluded(os.path.join(parent, filename))
|
||||||
|
)
|
||||||
|
|
||||||
|
def init_report(
|
||||||
|
self,
|
||||||
|
reporter: Optional[Type[formatter.BaseFormatter]] = None,
|
||||||
|
) -> None:
|
||||||
|
"""Set up a formatter for this run of Flake8."""
|
||||||
|
if reporter is None:
|
||||||
|
return
|
||||||
|
if not issubclass(reporter, formatter.BaseFormatter):
|
||||||
|
raise ValueError(
|
||||||
|
"Report should be subclass of "
|
||||||
|
"flake8.formatter.BaseFormatter."
|
||||||
|
)
|
||||||
|
self._application.formatter = None
|
||||||
|
self._application.make_formatter(reporter)
|
||||||
|
self._application.guide = None
|
||||||
|
# NOTE(sigmavirus24): This isn't the intended use of
|
||||||
|
# Application#make_guide but it works pretty well.
|
||||||
|
# Stop cringing... I know it's gross.
|
||||||
|
self._application.make_guide()
|
||||||
|
self._application.file_checker_manager = None
|
||||||
|
self._application.make_file_checker_manager()
|
||||||
|
|
||||||
|
def input_file(
|
||||||
|
self,
|
||||||
|
filename: str,
|
||||||
|
lines: Optional[Any] = None,
|
||||||
|
expected: Optional[Any] = None,
|
||||||
|
line_offset: Optional[Any] = 0,
|
||||||
|
) -> Report:
|
||||||
|
"""Run collected checks on a single file.
|
||||||
|
|
||||||
|
This will check the file passed in and return a :class:`Report`
|
||||||
|
instance.
|
||||||
|
|
||||||
|
:param str filename:
|
||||||
|
The path to the file to check.
|
||||||
|
:param list lines:
|
||||||
|
Ignored since Flake8 3.0.
|
||||||
|
:param expected:
|
||||||
|
Ignored since Flake8 3.0.
|
||||||
|
:param int line_offset:
|
||||||
|
Ignored since Flake8 3.0.
|
||||||
|
:returns:
|
||||||
|
Object that mimic's Flake8 2.0's Reporter class.
|
||||||
|
:rtype:
|
||||||
|
flake8.api.legacy.Report
|
||||||
|
"""
|
||||||
|
return self.check_files([filename])
|
||||||
|
|
||||||
|
|
||||||
|
def get_style_guide(**kwargs: Any) -> StyleGuide:
|
||||||
|
r"""Provision a StyleGuide for use.
|
||||||
|
|
||||||
|
:param \*\*kwargs:
|
||||||
|
Keyword arguments that provide some options for the StyleGuide.
|
||||||
|
:returns:
|
||||||
|
An initialized StyleGuide
|
||||||
|
:rtype:
|
||||||
|
:class:`StyleGuide`
|
||||||
|
"""
|
||||||
|
application = app.Application()
|
||||||
|
prelim_opts, remaining_args = application.parse_preliminary_options([])
|
||||||
|
flake8.configure_logging(prelim_opts.verbose, prelim_opts.output_file)
|
||||||
|
|
||||||
|
cfg, cfg_dir = config.load_config(
|
||||||
|
config=prelim_opts.config,
|
||||||
|
extra=prelim_opts.append_config,
|
||||||
|
isolated=prelim_opts.isolated,
|
||||||
|
)
|
||||||
|
|
||||||
|
application.find_plugins(cfg, cfg_dir, prelim_opts.enable_extensions)
|
||||||
|
application.register_plugin_options()
|
||||||
|
application.parse_configuration_and_cli(cfg, cfg_dir, remaining_args)
|
||||||
|
# We basically want application.initialize to be called but with these
|
||||||
|
# options set instead before we make our formatter, notifier, internal
|
||||||
|
# style guide and file checker manager.
|
||||||
|
options = application.options
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
try:
|
||||||
|
getattr(options, key)
|
||||||
|
setattr(options, key, value)
|
||||||
|
except AttributeError:
|
||||||
|
LOG.error('Could not update option "%s"', key)
|
||||||
|
application.make_formatter()
|
||||||
|
application.make_guide()
|
||||||
|
application.make_file_checker_manager()
|
||||||
|
return StyleGuide(application)
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,9 @@ def test_styleguide_options():
|
||||||
def test_styleguide_paths():
|
def test_styleguide_paths():
|
||||||
"""Show that we proxy the StyleGuide.paths attribute."""
|
"""Show that we proxy the StyleGuide.paths attribute."""
|
||||||
app = mock.Mock()
|
app = mock.Mock()
|
||||||
app.paths = "paths"
|
app.options.filenames = ["paths"]
|
||||||
style_guide = api.StyleGuide(app)
|
style_guide = api.StyleGuide(app)
|
||||||
assert style_guide.paths == "paths"
|
assert style_guide.paths == ["paths"]
|
||||||
|
|
||||||
|
|
||||||
def test_styleguide_check_files():
|
def test_styleguide_check_files():
|
||||||
|
|
@ -78,33 +78,13 @@ def test_styleguide_check_files():
|
||||||
def test_styleguide_excluded():
|
def test_styleguide_excluded():
|
||||||
"""Verify we delegate to our file checker manager.
|
"""Verify we delegate to our file checker manager.
|
||||||
|
|
||||||
We also want to ensure that if we don't specify a parent, is_path_excluded
|
|
||||||
is called exactly once.
|
|
||||||
"""
|
|
||||||
app = mock.Mock()
|
|
||||||
file_checker_manager = app.file_checker_manager = mock.Mock()
|
|
||||||
style_guide = api.StyleGuide(app)
|
|
||||||
|
|
||||||
style_guide.excluded("file.py")
|
|
||||||
file_checker_manager.is_path_excluded.assert_called_once_with("file.py")
|
|
||||||
|
|
||||||
|
|
||||||
def test_styleguide_excluded_with_parent():
|
|
||||||
"""Verify we delegate to our file checker manager.
|
|
||||||
|
|
||||||
When we add the parent argument, we don't check that is_path_excluded was
|
When we add the parent argument, we don't check that is_path_excluded was
|
||||||
called only once.
|
called only once.
|
||||||
"""
|
"""
|
||||||
app = mock.Mock()
|
style_guide = api.get_style_guide(exclude=["file*", "*/parent/*"])
|
||||||
file_checker_manager = app.file_checker_manager = mock.Mock()
|
assert not style_guide.excluded("unrelated.py")
|
||||||
file_checker_manager.is_path_excluded.return_value = False
|
assert style_guide.excluded("file.py")
|
||||||
style_guide = api.StyleGuide(app)
|
assert style_guide.excluded("test.py", "parent")
|
||||||
|
|
||||||
style_guide.excluded("file.py", "parent")
|
|
||||||
assert file_checker_manager.is_path_excluded.call_args_list == [
|
|
||||||
mock.call("file.py"),
|
|
||||||
mock.call(os.path.join("parent", "file.py")),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def test_styleguide_init_report_does_nothing():
|
def test_styleguide_init_report_does_nothing():
|
||||||
|
|
@ -121,7 +101,7 @@ def test_styleguide_init_report_with_non_subclass():
|
||||||
app = mock.Mock()
|
app = mock.Mock()
|
||||||
style_guide = api.StyleGuide(app)
|
style_guide = api.StyleGuide(app)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
style_guide.init_report(object)
|
style_guide.init_report(object) # type: ignore
|
||||||
assert app.make_formatter.called is False
|
assert app.make_formatter.called is False
|
||||||
assert app.make_guide.called is False
|
assert app.make_guide.called is False
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue