From f963641e932daed5ca5d71efa7293a9b756b8f76 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Thu, 30 Jun 2016 06:54:10 -0500 Subject: [PATCH 1/7] Update defaults McCabe reports C90* not C* and Flake8 2 used to exclude .eggs and *.egg --- src/flake8/defaults.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flake8/defaults.py b/src/flake8/defaults.py index d9f5a0b..ede2946 100644 --- a/src/flake8/defaults.py +++ b/src/flake8/defaults.py @@ -1,8 +1,8 @@ """Constants that define defaults.""" -EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' +EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg' IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504' -SELECT = 'E,F,W,C' +SELECT = 'E,F,W,C90' MAX_LINE_LENGTH = 79 TRUTHY_VALUES = set(['true', '1', 't']) From 6a2ad045fa3aeff24fbcf11b2abf8ae27035b9f1 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Thu, 30 Jun 2016 08:27:32 -0500 Subject: [PATCH 2/7] Add the skeleton for the LegacyStyleGuide --- src/flake8/api/style_guide.py | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/flake8/api/style_guide.py diff --git a/src/flake8/api/style_guide.py b/src/flake8/api/style_guide.py new file mode 100644 index 0000000..4e8595c --- /dev/null +++ b/src/flake8/api/style_guide.py @@ -0,0 +1,47 @@ +"""Module containing shims around Flake8 2.0 behaviour.""" +import os.path + +from flake8.formatting import base as formatter + + +class LegacyStyleGuide(object): + """Public facing object that mimic's Flake8 2.0's StyleGuide.""" + + def __init__(self, application): + self._application = application + self._file_checker_manager = application.file_checker_manager + + @property + def options(self): + """The parsed options. + + An instance of :class:`optparse.Values` containing parsed options. + """ + return self._application.options + + @property + def paths(self): + """The extra arguments passed as paths.""" + return self._application.paths + + def check_files(self, paths=None): + raise NotImplementedError('This should be easy') + + def excluded(self, filename, parent=None): + 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): + if (reporter is not None and + isinstance(reporter, formatter.BaseFormatter)): + self._application.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() + + def input_file(self, filename, lines=None, expected=None, line_offset=0): + raise NotImplementedError('This should be a pain') From 4a05d02ca6dc2f7868bfe2b52b619435cea70ad4 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Thu, 30 Jun 2016 15:34:29 -0500 Subject: [PATCH 3/7] Fix up MANIFEST.in --- MANIFEST.in | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index b87aff1..96b10e7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,8 @@ include *.rst include CONTRIBUTORS.txt include LICENSE -recursive-include docs * -recursive-include tests * -recursive-include src * +global-exclude *.pyc +recursive-include docs *.rst *.py +recursive-include tests *.py *.ini *.rst *_diff +recursive-include src *.py +prune docs/build/ From cde783d135953d7d16a1373f13b066731083e477 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Thu, 30 Jun 2016 16:03:02 -0500 Subject: [PATCH 4/7] Clean up setup.py a bit --- setup.py | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/setup.py b/setup.py index 2624db4..cd002cd 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,5 @@ -"""Packaging logic for Flake8.""" # -*- coding: utf-8 -*- -from __future__ import with_statement - +"""Packaging logic for Flake8.""" import functools import io import os @@ -13,25 +11,8 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) import flake8 # noqa -try: - # Work around a traceback with Nose on Python 2.6 - # http://bugs.python.org/issue15881#msg170215 - __import__('multiprocessing') -except ImportError: - pass - -try: - # Use https://docs.python.org/3/library/unittest.mock.html - from unittest import mock -except ImportError: - # < Python 3.3 - mock = None - - -tests_require = ['pytest'] -if mock is None: - tests_require.append('mock') +tests_require = ['mock', 'pytest'] requires = [ "pyflakes >= 0.8.1, != 1.2.0, != 1.2.1, != 1.2.2, < 1.3.0", @@ -47,7 +28,7 @@ if sys.version_info < (3, 2): def get_long_description(): - """Generate a long description from the README and CHANGES files.""" + """Generate a long description from the README file.""" descr = [] for fname in ('README.rst',): with io.open(fname, encoding='utf-8') as f: @@ -130,6 +111,7 @@ setuptools.setup( }, classifiers=[ "Environment :: Console", + "Framework :: Flake8", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", From 41cd67f747bac544b023e56134a43f5ea9c0c896 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Thu, 30 Jun 2016 20:09:46 -0500 Subject: [PATCH 5/7] Simplify our test environments --- tox.ini | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tox.ini b/tox.ini index 940806b..42dac04 100644 --- a/tox.ini +++ b/tox.ini @@ -28,9 +28,7 @@ commands = # Linters [testenv:flake8] -skipsdist = true skip_install = true -use_develop = false deps = flake8 flake8-docstrings>=0.2.7 @@ -40,9 +38,7 @@ commands = [testenv:pylint] basepython = python3 -skipsdist = true skip_install = true -use_develop = false deps = pyflakes pylint @@ -51,9 +47,7 @@ commands = [testenv:doc8] basepython = python3 -skipsdist = true skip_install = true -use_develop = false deps = sphinx doc8 @@ -62,9 +56,7 @@ commands = [testenv:mypy] basepython = python3 -skipsdist = true skip_install = true -use_develop = false deps = mypy-lang commands = @@ -72,9 +64,7 @@ commands = [testenv:bandit] basepython = python3 -skipsdist = true skip_install = true -use_develop = false deps = bandit commands = @@ -82,9 +72,7 @@ commands = [testenv:linters] basepython = python3 -skipsdist = true skip_install = true -use_develop = false deps = {[testenv:flake8]deps} {[testenv:pylint]deps} @@ -108,9 +96,7 @@ commands = [testenv:serve-docs] basepython = python3 -skipsdist = true skip_install = true -use_develop = false changedir = docs/build/html deps = commands = @@ -124,10 +110,8 @@ commands = python setup.py check -r -s [testenv:release] -skipsdist = true basepython = python3 skip_install = true -use_develop = false deps = wheel setuptools From a4ce229fb6493c11fd8ed850d5c07a5964fade7d Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Thu, 7 Jul 2016 13:29:53 -0500 Subject: [PATCH 6/7] Fill in most of the legacy API This does not handle setting custom options via the parameters to get_style_guide. --- src/flake8/api/__init__.py | 5 -- src/flake8/api/legacy.py | 142 +++++++++++++++++++++++++++++++++ src/flake8/api/style_guide.py | 47 ----------- src/flake8/main/application.py | 18 +++-- 4 files changed, 153 insertions(+), 59 deletions(-) create mode 100644 src/flake8/api/legacy.py delete mode 100644 src/flake8/api/style_guide.py diff --git a/src/flake8/api/__init__.py b/src/flake8/api/__init__.py index 9f95557..c2eefbe 100644 --- a/src/flake8/api/__init__.py +++ b/src/flake8/api/__init__.py @@ -3,8 +3,3 @@ This is the only submodule in Flake8 with a guaranteed stable API. All other submodules are considered internal only and are subject to change. """ - - -def get_style_guide(**kwargs): - """Stub out the only function I'm aware of people using.""" - pass diff --git a/src/flake8/api/legacy.py b/src/flake8/api/legacy.py new file mode 100644 index 0000000..42e83c3 --- /dev/null +++ b/src/flake8/api/legacy.py @@ -0,0 +1,142 @@ +"""Module containing shims around Flake8 2.0 behaviour.""" +import os.path + +from flake8.formatting import base as formatter +from flake8.main import application as app + + +def get_style_guide(**kwargs): + """Stub out the only function I'm aware of people using.""" + application = app.Application() + application.initialize([]) + return StyleGuide(application) + + +class StyleGuide(object): + """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): + """The parsed options. + + An instance of :class:`optparse.Values` containing parsed options. + """ + return self._application.options + + @property + def paths(self): + """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.run_checks(paths) + 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 not None and + not issubclass(reporter, formatter.BaseFormatter)): + raise ValueError("Report should be subclass of " + "flake8.formatter.BaseFormatter.") + 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() + + 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(object): + """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. + + .. versionchanged:: 3.0.0 + """ + + def __init__(self, application): + """Initialize the Report for the user. + + .. warning:: This should not be instantiated by users. + """ + self._application = application + + @property + def total_errors(self): + """The total number of errors found by Flake8.""" + return self._application.result_count + + def get_statistics(self, violation): + """Get the number of occurences of a violation.""" + raise NotImplementedError('Statistics capturing needs to happen first') diff --git a/src/flake8/api/style_guide.py b/src/flake8/api/style_guide.py deleted file mode 100644 index 4e8595c..0000000 --- a/src/flake8/api/style_guide.py +++ /dev/null @@ -1,47 +0,0 @@ -"""Module containing shims around Flake8 2.0 behaviour.""" -import os.path - -from flake8.formatting import base as formatter - - -class LegacyStyleGuide(object): - """Public facing object that mimic's Flake8 2.0's StyleGuide.""" - - def __init__(self, application): - self._application = application - self._file_checker_manager = application.file_checker_manager - - @property - def options(self): - """The parsed options. - - An instance of :class:`optparse.Values` containing parsed options. - """ - return self._application.options - - @property - def paths(self): - """The extra arguments passed as paths.""" - return self._application.paths - - def check_files(self, paths=None): - raise NotImplementedError('This should be easy') - - def excluded(self, filename, parent=None): - 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): - if (reporter is not None and - isinstance(reporter, formatter.BaseFormatter)): - self._application.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() - - def input_file(self, filename, lines=None, expected=None, line_offset=0): - raise NotImplementedError('This should be a pain') diff --git a/src/flake8/main/application.py b/src/flake8/main/application.py index b1e0772..35feede 100644 --- a/src/flake8/main/application.py +++ b/src/flake8/main/application.py @@ -177,13 +177,15 @@ class Application(object): self.options, self.args) - def make_formatter(self): + def make_formatter(self, formatter_class=None): # type: () -> NoneType """Initialize a formatter based on the parsed options.""" if self.formatter is None: - self.formatter = self.formatting_plugins.get( - self.options.format, self.formatting_plugins['default'] - ).execute(self.options) + if formatter_class is None: + formatter_class = self.formatting_plugins.get( + self.options.format, self.formatting_plugins['default'] + ).execute + self.formatter = formatter_class(self.options) def make_notifier(self): # type: () -> NoneType @@ -212,15 +214,17 @@ class Application(object): checker_plugins=self.check_plugins, ) - def run_checks(self): - # type: () -> NoneType + def run_checks(self, files=None): + # type: (Union[List[str], NoneType]) -> NoneType """Run the actual checks with the FileChecker Manager. This method encapsulates the logic to make a :class:`~flake8.checker.Manger` instance run the checks it is managing. + + :param list files: + List of filenames to process """ - files = None if self.running_against_diff: files = list(sorted(self.parsed_diff.keys())) self.file_checker_manager.start(files) From 1372d0dd1c103077c53eb1977090c3065cac1992 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Thu, 7 Jul 2016 17:39:02 -0500 Subject: [PATCH 7/7] Handle kwargs passed to get_style_guide --- src/flake8/api/legacy.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/flake8/api/legacy.py b/src/flake8/api/legacy.py index 42e83c3..35c7101 100644 --- a/src/flake8/api/legacy.py +++ b/src/flake8/api/legacy.py @@ -1,14 +1,24 @@ """Module containing shims around Flake8 2.0 behaviour.""" +import logging import os.path from flake8.formatting import base as formatter from flake8.main import application as app +LOG = logging.getLogger(__name__) + def get_style_guide(**kwargs): """Stub out the only function I'm aware of people using.""" application = app.Application() application.initialize([]) + 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) return StyleGuide(application)