| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- """Module containing shims around Flake8 2.x behaviour.
- Previously, users would import :func:`get_style_guide` from ``flake8.engine``.
- In 3.0 we no longer have an "engine" module but we maintain the API from it.
- """
- import argparse
- import logging
- import os.path
- from typing import Any
- from typing import List
- from typing import Optional
- from typing import Type
- import flake8
- from flake8.discover_files import expand_paths
- from flake8.formatting import base as formatter
- from flake8.main import application as app
- from flake8.options import config
- LOG = logging.getLogger(__name__)
- __all__ = ("get_style_guide",)
- class Report:
- """Public facing object that mimic's Flake8 2.0's API.
- .. note::
- There are important changes in how this object behaves compared to
- the object provided in Flake8 2.x.
- .. warning::
- This should not be instantiated by users.
- .. versionchanged:: 3.0.0
- """
- def __init__(self, application: app.Application) -> None:
- """Initialize the Report for the user.
- .. warning:: This should not be instantiated by users.
- """
- assert application.guide is not None
- self._application = application
- self._style_guide = application.guide
- self._stats = self._style_guide.stats
- @property
- def total_errors(self) -> int:
- """Return the total number of errors."""
- return self._application.result_count
- def get_statistics(self, violation: str) -> List[str]:
- """Get the list of occurrences of a violation.
- :returns:
- List of occurrences of a violation formatted as:
- {Count} {Error Code} {Message}, e.g.,
- ``8 E531 Some error message about the error``
- """
- return [
- f"{s.count} {s.error_code} {s.message}"
- 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 paths:
- List of filenames (or paths) to check.
- :returns:
- Object that mimic's Flake8 2.0's Reporter class.
- """
- 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 filename:
- Path to the file to check if it is excluded.
- :param parent:
- Name of the parent directory containing the file.
- :returns:
- True if the filename is excluded, False otherwise.
- """
- 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 = reporter(self.options)
- 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 filename:
- The path to the file to check.
- :param lines:
- Ignored since Flake8 3.0.
- :param expected:
- Ignored since Flake8 3.0.
- :param line_offset:
- Ignored since Flake8 3.0.
- :returns:
- Object that mimic's Flake8 2.0's Reporter class.
- """
- 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
- """
- 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,
- enable_extensions=prelim_opts.enable_extensions,
- require_plugins=prelim_opts.require_plugins,
- )
- 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)
|