summaryrefslogtreecommitdiff
path: root/old
diff options
context:
space:
mode:
authorIan Cordasco <graffatcolmingov@gmail.com>2016-03-15 15:58:24 -0500
committerIan Cordasco <graffatcolmingov@gmail.com>2016-03-15 15:58:24 -0500
commit784a70dd0ed74bef5ca2dac636705dea82687a47 (patch)
tree4a861f60f8f196cd28b56a63ed34fdb7ba6adc3a /old
parent62a7cca512463ad661d9ba4c129651ee55352d60 (diff)
downloadflake8-784a70dd0ed74bef5ca2dac636705dea82687a47.tar.gz
Move flake8 2 out of the way
Diffstat (limited to 'old')
-rw-r--r--old/flake8/__init__.py1
-rw-r--r--old/flake8/__main__.py4
-rw-r--r--old/flake8/_pyflakes.py120
-rw-r--r--old/flake8/callbacks.py27
-rw-r--r--old/flake8/compat.py12
-rw-r--r--old/flake8/engine.py316
-rw-r--r--old/flake8/hooks.py297
-rw-r--r--old/flake8/main.py142
-rw-r--r--old/flake8/reporter.py152
-rw-r--r--old/flake8/run.py11
-rw-r--r--old/flake8/tests/__init__.py1
-rw-r--r--old/flake8/tests/_test_warnings.py309
-rw-r--r--old/flake8/tests/test_engine.py236
-rw-r--r--old/flake8/tests/test_hooks.py59
-rw-r--r--old/flake8/tests/test_integration.py79
-rw-r--r--old/flake8/tests/test_main.py18
-rw-r--r--old/flake8/tests/test_pyflakes.py73
-rw-r--r--old/flake8/tests/test_reporter.py36
-rw-r--r--old/flake8/tests/test_util.py120
-rw-r--r--old/flake8/util.py77
-rw-r--r--old/setup.py75
-rw-r--r--old/tox.ini40
22 files changed, 2205 insertions, 0 deletions
diff --git a/old/flake8/__init__.py b/old/flake8/__init__.py
new file mode 100644
index 0000000..36dc058
--- /dev/null
+++ b/old/flake8/__init__.py
@@ -0,0 +1 @@
+__version__ = '2.5.4'
diff --git a/old/flake8/__main__.py b/old/flake8/__main__.py
new file mode 100644
index 0000000..aaa497b
--- /dev/null
+++ b/old/flake8/__main__.py
@@ -0,0 +1,4 @@
+from flake8.main import main
+
+# python -m flake8 (with Python >= 2.7)
+main()
diff --git a/old/flake8/_pyflakes.py b/old/flake8/_pyflakes.py
new file mode 100644
index 0000000..976b2ab
--- /dev/null
+++ b/old/flake8/_pyflakes.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+try:
+ # The 'demandimport' breaks pyflakes and flake8._pyflakes
+ from mercurial import demandimport
+except ImportError:
+ pass
+else:
+ demandimport.disable()
+import os
+
+import pep8
+import pyflakes
+import pyflakes.checker
+
+
+def patch_pyflakes():
+ """Add error codes to Pyflakes messages."""
+ codes = dict([line.split()[::-1] for line in (
+ 'F401 UnusedImport',
+ 'F402 ImportShadowedByLoopVar',
+ 'F403 ImportStarUsed',
+ 'F404 LateFutureImport',
+ 'F810 Redefined', # XXX Obsolete?
+ 'F811 RedefinedWhileUnused',
+ 'F812 RedefinedInListComp',
+ 'F821 UndefinedName',
+ 'F822 UndefinedExport',
+ 'F823 UndefinedLocal',
+ 'F831 DuplicateArgument',
+ 'F841 UnusedVariable',
+ )])
+
+ for name, obj in vars(pyflakes.messages).items():
+ if name[0].isupper() and obj.message:
+ obj.flake8_msg = '%s %s' % (codes.get(name, 'F999'), obj.message)
+patch_pyflakes()
+
+
+class FlakesChecker(pyflakes.checker.Checker):
+ """Subclass the Pyflakes checker to conform with the flake8 API."""
+ name = 'pyflakes'
+ version = pyflakes.__version__
+
+ def __init__(self, tree, filename):
+ filename = pep8.normalize_paths(filename)[0]
+ withDoctest = self.withDoctest
+ included_by = [include for include in self.include_in_doctest
+ if include != '' and filename.startswith(include)]
+ if included_by:
+ withDoctest = True
+
+ for exclude in self.exclude_from_doctest:
+ if exclude != '' and filename.startswith(exclude):
+ withDoctest = False
+ overlaped_by = [include for include in included_by
+ if include.startswith(exclude)]
+
+ if overlaped_by:
+ withDoctest = True
+
+ super(FlakesChecker, self).__init__(tree, filename,
+ withDoctest=withDoctest)
+
+ @classmethod
+ def add_options(cls, parser):
+ parser.add_option('--builtins',
+ help="define more built-ins, comma separated")
+ parser.add_option('--doctests', default=False, action='store_true',
+ help="check syntax of the doctests")
+ parser.add_option('--include-in-doctest', default='',
+ dest='include_in_doctest',
+ help='Run doctests only on these files',
+ type='string')
+ parser.add_option('--exclude-from-doctest', default='',
+ dest='exclude_from_doctest',
+ help='Skip these files when running doctests',
+ type='string')
+ parser.config_options.extend(['builtins', 'doctests',
+ 'include-in-doctest',
+ 'exclude-from-doctest'])
+
+ @classmethod
+ def parse_options(cls, options):
+ if options.builtins:
+ cls.builtIns = cls.builtIns.union(options.builtins.split(','))
+ cls.withDoctest = options.doctests
+
+ included_files = []
+ for included_file in options.include_in_doctest.split(','):
+ if included_file == '':
+ continue
+ if not included_file.startswith((os.sep, './', '~/')):
+ included_files.append('./' + included_file)
+ else:
+ included_files.append(included_file)
+ cls.include_in_doctest = pep8.normalize_paths(','.join(included_files))
+
+ excluded_files = []
+ for excluded_file in options.exclude_from_doctest.split(','):
+ if excluded_file == '':
+ continue
+ if not excluded_file.startswith((os.sep, './', '~/')):
+ excluded_files.append('./' + excluded_file)
+ else:
+ excluded_files.append(excluded_file)
+ cls.exclude_from_doctest = pep8.normalize_paths(
+ ','.join(excluded_files))
+
+ inc_exc = set(cls.include_in_doctest).intersection(
+ set(cls.exclude_from_doctest))
+ if inc_exc:
+ raise ValueError('"%s" was specified in both the '
+ 'include-in-doctest and exclude-from-doctest '
+ 'options. You are not allowed to specify it in '
+ 'both for doctesting.' % inc_exc)
+
+ def run(self):
+ for m in self.messages:
+ col = getattr(m, 'col', 0)
+ yield m.lineno, col, (m.flake8_msg % m.message_args), m.__class__
diff --git a/old/flake8/callbacks.py b/old/flake8/callbacks.py
new file mode 100644
index 0000000..3767f30
--- /dev/null
+++ b/old/flake8/callbacks.py
@@ -0,0 +1,27 @@
+import atexit
+import sys
+
+
+def install_vcs_hook(option, option_str, value, parser):
+ # For now, there's no way to affect a change in how pep8 processes
+ # options. If no args are provided and there's no config file present,
+ # it will error out because no input was provided. To get around this,
+ # when we're using --install-hook, we'll say that there were arguments so
+ # we can actually attempt to install the hook.
+ # See: https://gitlab.com/pycqa/flake8/issues/2 and
+ # https://github.com/jcrocholl/pep8/blob/4c5bf00cb613be617c7f48d3b2b82a1c7b895ac1/pep8.py#L1912
+ # for more context.
+ parser.values.install_hook = True
+ parser.rargs.append('.')
+
+
+def restore_stdout(old_stdout):
+ sys.stdout.close()
+ sys.stdout = old_stdout
+
+
+def redirect_stdout(option, option_str, value, parser):
+ fd = open(value, 'w')
+ old_stdout, sys.stdout = sys.stdout, fd
+
+ atexit.register(restore_stdout, old_stdout)
diff --git a/old/flake8/compat.py b/old/flake8/compat.py
new file mode 100644
index 0000000..9bd00a7
--- /dev/null
+++ b/old/flake8/compat.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+"""Compatibility shims for Flake8."""
+import os.path
+import sys
+
+
+def relpath(path, start='.'):
+ """Wallpaper over the differences between 2.6 and newer versions."""
+ if sys.version_info < (2, 7) and path.startswith(start):
+ return path[len(start):]
+ else:
+ return os.path.relpath(path, start=start)
diff --git a/old/flake8/engine.py b/old/flake8/engine.py
new file mode 100644
index 0000000..816f1ee
--- /dev/null
+++ b/old/flake8/engine.py
@@ -0,0 +1,316 @@
+# -*- coding: utf-8 -*-
+import errno
+import io
+import platform
+import re
+import sys
+import warnings
+
+import pep8
+
+from flake8 import __version__
+from flake8 import callbacks
+from flake8.reporter import (multiprocessing, BaseQReport, FileQReport,
+ QueueReport)
+from flake8 import util
+
+_flake8_noqa = re.compile(r'\s*# flake8[:=]\s*noqa', re.I).search
+
+EXTRA_EXCLUDE = ['.tox', '.eggs', '*.egg']
+
+pep8.PROJECT_CONFIG += ('.flake8',)
+
+
+def _load_entry_point(entry_point, verify_requirements):
+ """Based on the version of setuptools load an entry-point correctly.
+
+ setuptools 11.3 deprecated `require=False` in the call to EntryPoint.load.
+ To load entry points correctly after that without requiring all
+ dependencies be present, the proper way is to call EntryPoint.resolve.
+
+ This function will provide backwards compatibility for older versions of
+ setuptools while also ensuring we do the right thing for the future.
+ """
+ if hasattr(entry_point, 'resolve') and hasattr(entry_point, 'require'):
+ if verify_requirements:
+ entry_point.require()
+ plugin = entry_point.resolve()
+ else:
+ plugin = entry_point.load(require=verify_requirements)
+
+ return plugin
+
+
+def _register_extensions():
+ """Register all the extensions."""
+ extensions = util.OrderedSet()
+ extensions.add(('pep8', pep8.__version__))
+ parser_hooks = []
+ options_hooks = []
+ ignored_hooks = []
+ try:
+ from pkg_resources import iter_entry_points
+ except ImportError:
+ pass
+ else:
+ for entry in iter_entry_points('flake8.extension'):
+ # Do not verify that the requirements versions are valid
+ checker = _load_entry_point(entry, verify_requirements=False)
+ pep8.register_check(checker, codes=[entry.name])
+ extensions.add((checker.name, checker.version))
+ if hasattr(checker, 'add_options'):
+ parser_hooks.append(checker.add_options)
+ if hasattr(checker, 'parse_options'):
+ options_hooks.append(checker.parse_options)
+ if getattr(checker, 'off_by_default', False) is True:
+ ignored_hooks.append(entry.name)
+ return extensions, parser_hooks, options_hooks, ignored_hooks
+
+
+def get_parser():
+ """This returns an instance of optparse.OptionParser with all the
+ extensions registered and options set. This wraps ``pep8.get_parser``.
+ """
+ (extensions, parser_hooks, options_hooks, ignored) = _register_extensions()
+ details = ', '.join('%s: %s' % ext for ext in extensions)
+ python_version = get_python_version()
+ parser = pep8.get_parser('flake8', '%s (%s) %s' % (
+ __version__, details, python_version
+ ))
+ for opt in ('--repeat', '--testsuite', '--doctest'):
+ try:
+ parser.remove_option(opt)
+ except ValueError:
+ pass
+
+ if multiprocessing:
+ parser.config_options.append('jobs')
+ parser.add_option('-j', '--jobs', type='string', default='auto',
+ help="number of jobs to run simultaneously, "
+ "or 'auto'. This is ignored on Windows.")
+
+ parser.add_option('--exit-zero', action='store_true',
+ help="exit with code 0 even if there are errors")
+ for parser_hook in parser_hooks:
+ parser_hook(parser)
+ # See comment above regarding why this has to be a callback.
+ parser.add_option('--install-hook', default=False, dest='install_hook',
+ help='Install the appropriate hook for this '
+ 'repository.', action='callback',
+ callback=callbacks.install_vcs_hook)
+ parser.add_option('--output-file', default=None,
+ help='Redirect report to a file.',
+ type='string', nargs=1, action='callback',
+ callback=callbacks.redirect_stdout)
+ parser.add_option('--enable-extensions', default='',
+ dest='enable_extensions',
+ help='Enable plugins and extensions that are disabled '
+ 'by default',
+ type='string')
+ parser.config_options.extend(['output-file', 'enable-extensions'])
+ parser.ignored_extensions = ignored
+ return parser, options_hooks
+
+
+class NoQAStyleGuide(pep8.StyleGuide):
+
+ def input_file(self, filename, lines=None, expected=None, line_offset=0):
+ """Run all checks on a Python source file."""
+ if self.options.verbose:
+ print('checking %s' % filename)
+ fchecker = self.checker_class(
+ filename, lines=lines, options=self.options)
+ # Any "flake8: noqa" comments to ignore the entire file?
+ if any(_flake8_noqa(line) for line in fchecker.lines):
+ return 0
+ return fchecker.check_all(expected=expected, line_offset=line_offset)
+
+
+class StyleGuide(object):
+ """A wrapper StyleGuide object for Flake8 usage.
+
+ This allows for OSErrors to be caught in the styleguide and special logic
+ to be used to handle those errors.
+ """
+
+ # Reasoning for error numbers is in-line below
+ serial_retry_errors = set([
+ # ENOSPC: Added by sigmavirus24
+ # > On some operating systems (OSX), multiprocessing may cause an
+ # > ENOSPC error while trying to trying to create a Semaphore.
+ # > In those cases, we should replace the customized Queue Report
+ # > class with pep8's StandardReport class to ensure users don't run
+ # > into this problem.
+ # > (See also: https://gitlab.com/pycqa/flake8/issues/74)
+ errno.ENOSPC,
+ # NOTE(sigmavirus24): When adding to this list, include the reasoning
+ # on the lines before the error code and always append your error
+ # code. Further, please always add a trailing `,` to reduce the visual
+ # noise in diffs.
+ ])
+
+ def __init__(self, **kwargs):
+ # This allows us to inject a mocked StyleGuide in the tests.
+ self._styleguide = kwargs.pop('styleguide', NoQAStyleGuide(**kwargs))
+
+ @property
+ def options(self):
+ return self._styleguide.options
+
+ @property
+ def paths(self):
+ return self._styleguide.paths
+
+ def _retry_serial(self, func, *args, **kwargs):
+ """This will retry the passed function in serial if necessary.
+
+ In the event that we encounter an OSError with an errno in
+ :attr:`serial_retry_errors`, this function will retry this function
+ using pep8's default Report class which operates in serial.
+ """
+ try:
+ return func(*args, **kwargs)
+ except OSError as oserr:
+ if oserr.errno in self.serial_retry_errors:
+ self.init_report(pep8.StandardReport)
+ else:
+ raise
+ return func(*args, **kwargs)
+
+ def check_files(self, paths=None):
+ return self._retry_serial(self._styleguide.check_files, paths=paths)
+
+ def excluded(self, filename, parent=None):
+ return self._styleguide.excluded(filename, parent=parent)
+
+ def init_report(self, reporter=None):
+ return self._styleguide.init_report(reporter)
+
+ def input_file(self, filename, lines=None, expected=None, line_offset=0):
+ return self._retry_serial(
+ self._styleguide.input_file,
+ filename=filename,
+ lines=lines,
+ expected=expected,
+ line_offset=line_offset,
+ )
+
+
+def _parse_multi_options(options, split_token=','):
+ r"""Split and strip and discard empties.
+
+ Turns the following:
+
+ A,
+ B,
+
+ into ["A", "B"].
+
+ Credit: Kristian Glass as contributed to pep8
+ """
+ if options:
+ return [o.strip() for o in options.split(split_token) if o.strip()]
+ else:
+ return options
+
+
+def _disable_extensions(parser, options):
+ ignored_extensions = set(getattr(parser, 'ignored_extensions', []))
+ enabled = set(_parse_multi_options(options.enable_extensions))
+
+ # Remove any of the selected extensions from the extensions ignored by
+ # default.
+ ignored_extensions -= enabled
+
+ # Whatever is left afterwards should be unioned with options.ignore and
+ # options.ignore should be updated with that.
+ options.ignore = tuple(ignored_extensions.union(options.ignore))
+
+
+def get_style_guide(**kwargs):
+ """Parse the options and configure the checker. This returns a sub-class
+ of ``pep8.StyleGuide``."""
+ kwargs['parser'], options_hooks = get_parser()
+ styleguide = StyleGuide(**kwargs)
+ options = styleguide.options
+ _disable_extensions(kwargs['parser'], options)
+
+ if options.exclude and not isinstance(options.exclude, list):
+ options.exclude = pep8.normalize_paths(options.exclude)
+ elif not options.exclude:
+ options.exclude = []
+
+ # Add patterns in EXTRA_EXCLUDE to the list of excluded patterns
+ options.exclude.extend(pep8.normalize_paths(EXTRA_EXCLUDE))
+
+ for options_hook in options_hooks:
+ options_hook(options)
+
+ if util.warn_when_using_jobs(options):
+ if not multiprocessing:
+ warnings.warn("The multiprocessing module is not available. "
+ "Ignoring --jobs arguments.")
+ if util.is_windows():
+ warnings.warn("The --jobs option is not available on Windows. "
+ "Ignoring --jobs arguments.")
+ if util.is_using_stdin(styleguide.paths):
+ warnings.warn("The --jobs option is not compatible with supplying "
+ "input using - . Ignoring --jobs arguments.")
+ if options.diff:
+ warnings.warn("The --diff option was specified with --jobs but "
+ "they are not compatible. Ignoring --jobs arguments."
+ )
+
+ if options.diff:
+ options.jobs = None
+
+ force_disable_jobs = util.force_disable_jobs(styleguide)
+
+ if multiprocessing and options.jobs and not force_disable_jobs:
+ if options.jobs.isdigit():
+ n_jobs = int(options.jobs)
+ else:
+ try:
+ n_jobs = multiprocessing.cpu_count()
+ except NotImplementedError:
+ n_jobs = 1
+ if n_jobs > 1:
+ options.jobs = n_jobs
+ reporter = QueueReport
+ if options.quiet:
+ reporter = BaseQReport
+ if options.quiet == 1:
+ reporter = FileQReport
+ report = styleguide.init_report(reporter)
+ report.input_file = styleguide.input_file
+ styleguide.runner = report.task_queue.put
+
+ return styleguide
+
+
+def get_python_version():
+ # The implementation isn't all that important.
+ try:
+ impl = platform.python_implementation() + " "
+ except AttributeError: # Python 2.5
+ impl = ''
+ return '%s%s on %s' % (impl, platform.python_version(), platform.system())
+
+
+def make_stdin_get_value(original):
+ def stdin_get_value():
+ if not hasattr(stdin_get_value, 'cached_stdin'):
+ value = original()
+ if sys.version_info < (3, 0):
+ stdin = io.BytesIO(value)
+ else:
+ stdin = io.StringIO(value)
+ stdin_get_value.cached_stdin = stdin
+ else:
+ stdin = stdin_get_value.cached_stdin
+ return stdin.getvalue()
+
+ return stdin_get_value
+
+
+pep8.stdin_get_value = make_stdin_get_value(pep8.stdin_get_value)
diff --git a/old/flake8/hooks.py b/old/flake8/hooks.py
new file mode 100644
index 0000000..14f844e
--- /dev/null
+++ b/old/flake8/hooks.py
@@ -0,0 +1,297 @@
+# -*- coding: utf-8 -*-
+from __future__ import with_statement
+import os
+import pep8
+import sys
+import stat
+from subprocess import Popen, PIPE
+import shutil
+import tempfile
+try:
+ from configparser import ConfigParser
+except ImportError: # Python 2
+ from ConfigParser import ConfigParser
+
+from flake8 import compat
+from flake8.engine import get_parser, get_style_guide
+from flake8.main import DEFAULT_CONFIG
+
+
+def git_hook(complexity=-1, strict=False, ignore=None, lazy=False):
+ """This is the function used by the git hook.
+
+ :param int complexity: (optional), any value > 0 enables complexity
+ checking with mccabe
+ :param bool strict: (optional), if True, this returns the total number of
+ errors which will cause the hook to fail
+ :param str ignore: (optional), a comma-separated list of errors and
+ warnings to ignore
+ :param bool lazy: (optional), allows for the instances where you don't add
+ the files to the index before running a commit, e.g., git commit -a
+ :returns: total number of errors if strict is True, otherwise 0
+ """
+ gitcmd = "git diff-index --cached --name-only --diff-filter=ACMRTUXB HEAD"
+ if lazy:
+ # Catch all files, including those not added to the index
+ gitcmd = gitcmd.replace('--cached ', '')
+
+ if hasattr(ignore, 'split'):
+ ignore = ignore.split(',')
+
+ # Returns the exit code, list of files modified, list of error messages
+ _, files_modified, _ = run(gitcmd)
+
+ # We only want to pass ignore and max_complexity if they differ from the
+ # defaults so that we don't override a local configuration file
+ options = {}
+ if ignore:
+ options['ignore'] = ignore
+ if complexity > -1:
+ options['max_complexity'] = complexity
+
+ tmpdir = tempfile.mkdtemp()
+
+ flake8_style = get_style_guide(config_file=DEFAULT_CONFIG, paths=['.'],
+ **options)
+ filepatterns = flake8_style.options.filename
+
+ # Copy staged versions to temporary directory
+ files_to_check = []
+ try:
+ for file_ in files_modified:
+ # get the staged version of the file
+ gitcmd_getstaged = "git show :%s" % file_
+ _, out, _ = run(gitcmd_getstaged, raw_output=True, decode=False)
+ # write the staged version to temp dir with its full path to
+ # avoid overwriting files with the same name
+ dirname, filename = os.path.split(os.path.abspath(file_))
+ prefix = os.path.commonprefix([dirname, tmpdir])
+ dirname = compat.relpath(dirname, start=prefix)
+ dirname = os.path.join(tmpdir, dirname)
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+
+ # check_files() only does this check if passed a dir; so we do it
+ if ((pep8.filename_match(file_, filepatterns) and
+ not flake8_style.excluded(file_))):
+
+ filename = os.path.join(dirname, filename)
+ files_to_check.append(filename)
+ # write staged version of file to temporary directory
+ with open(filename, "wb") as fh:
+ fh.write(out)
+
+ # Run the checks
+ report = flake8_style.check_files(files_to_check)
+ # remove temporary directory
+ finally:
+ shutil.rmtree(tmpdir, ignore_errors=True)
+
+ if strict:
+ return report.total_errors
+
+ return 0
+
+
+def hg_hook(ui, repo, **kwargs):
+ """This is the function executed directly by Mercurial as part of the
+ hook. This is never called directly by the user, so the parameters are
+ undocumented. If you would like to learn more about them, please feel free
+ to read the official Mercurial documentation.
+ """
+ complexity = ui.config('flake8', 'complexity', default=-1)
+ strict = ui.configbool('flake8', 'strict', default=True)
+ ignore = ui.config('flake8', 'ignore', default=None)
+ config = ui.config('flake8', 'config', default=DEFAULT_CONFIG)
+
+ paths = _get_files(repo, **kwargs)
+
+ # We only want to pass ignore and max_complexity if they differ from the
+ # defaults so that we don't override a local configuration file
+ options = {}
+ if ignore:
+ options['ignore'] = ignore
+ if complexity > -1:
+ options['max_complexity'] = complexity
+
+ flake8_style = get_style_guide(config_file=config, paths=['.'],
+ **options)
+ report = flake8_style.check_files(paths)
+
+ if strict:
+ return report.total_errors
+
+ return 0
+
+
+def run(command, raw_output=False, decode=True):
+ p = Popen(command.split(), stdout=PIPE, stderr=PIPE)
+ (stdout, stderr) = p.communicate()
+ # On python 3, subprocess.Popen returns bytes objects which expect
+ # endswith to be given a bytes object or a tuple of bytes but not native
+ # string objects. This is simply less mysterious than using b'.py' in the
+ # endswith method. That should work but might still fail horribly.
+ if decode:
+ if hasattr(stdout, 'decode'):
+ stdout = stdout.decode('utf-8')
+ if hasattr(stderr, 'decode'):
+ stderr = stderr.decode('utf-8')
+ if not raw_output:
+ stdout = [line.strip() for line in stdout.splitlines()]
+ stderr = [line.strip() for line in stderr.splitlines()]
+ return (p.returncode, stdout, stderr)
+
+
+def _get_files(repo, **kwargs):
+ seen = set()
+ for rev in range(repo[kwargs['node']], len(repo)):
+ for file_ in repo[rev].files():
+ file_ = os.path.join(repo.root, file_)
+ if file_ in seen or not os.path.exists(file_):
+ continue
+ seen.add(file_)
+ if file_.endswith('.py'):
+ yield file_
+
+
+def find_vcs():
+ try:
+ _, git_dir, _ = run('git rev-parse --git-dir')
+ except OSError:
+ pass
+ else:
+ if git_dir and os.path.isdir(git_dir[0]):
+ if not os.path.isdir(os.path.join(git_dir[0], 'hooks')):
+ os.mkdir(os.path.join(git_dir[0], 'hooks'))
+ return os.path.join(git_dir[0], 'hooks', 'pre-commit')
+ try:
+ _, hg_dir, _ = run('hg root')
+ except OSError:
+ pass
+ else:
+ if hg_dir and os.path.isdir(hg_dir[0]):
+ return os.path.join(hg_dir[0], '.hg', 'hgrc')
+ return ''
+
+
+def get_git_config(option, opt_type='', convert_type=True):
+ # type can be --bool, --int or an empty string
+ _, git_cfg_value, _ = run('git config --get %s %s' % (opt_type, option),
+ raw_output=True)
+ git_cfg_value = git_cfg_value.strip()
+ if not convert_type:
+ return git_cfg_value
+ if opt_type == '--bool':
+ git_cfg_value = git_cfg_value.lower() == 'true'
+ elif git_cfg_value and opt_type == '--int':
+ git_cfg_value = int(git_cfg_value)
+ return git_cfg_value
+
+
+_params = {
+ 'FLAKE8_COMPLEXITY': '--int',
+ 'FLAKE8_STRICT': '--bool',
+ 'FLAKE8_IGNORE': '',
+ 'FLAKE8_LAZY': '--bool',
+}
+
+
+def get_git_param(option, default=''):
+ global _params
+ opt_type = _params[option]
+ param_value = get_git_config(option.lower().replace('_', '.'),
+ opt_type=opt_type, convert_type=False)
+ if param_value == '':
+ param_value = os.environ.get(option, default)
+ if opt_type == '--bool' and not isinstance(param_value, bool):
+ param_value = param_value.lower() == 'true'
+ elif param_value and opt_type == '--int':
+ param_value = int(param_value)
+ return param_value
+
+
+git_hook_file = """#!/usr/bin/env python
+import sys
+from flake8.hooks import git_hook, get_git_param
+
+# `get_git_param` will retrieve configuration from your local git config and
+# then fall back to using the environment variables that the hook has always
+# supported.
+# For example, to set the complexity, you'll need to do:
+# git config flake8.complexity 10
+COMPLEXITY = get_git_param('FLAKE8_COMPLEXITY', 10)
+STRICT = get_git_param('FLAKE8_STRICT', False)
+IGNORE = get_git_param('FLAKE8_IGNORE', None)
+LAZY = get_git_param('FLAKE8_LAZY', False)
+
+if __name__ == '__main__':
+ sys.exit(git_hook(
+ complexity=COMPLEXITY,
+ strict=STRICT,
+ ignore=IGNORE,
+ lazy=LAZY,
+ ))
+"""
+
+
+def _install_hg_hook(path):
+ getenv = os.environ.get
+ if not os.path.isfile(path):
+ # Make the file so we can avoid IOError's
+ open(path, 'w').close()
+
+ c = ConfigParser()
+ c.readfp(open(path, 'r'))
+ if not c.has_section('hooks'):
+ c.add_section('hooks')
+
+ if not c.has_option('hooks', 'commit'):
+ c.set('hooks', 'commit', 'python:flake8.hooks.hg_hook')
+
+ if not c.has_option('hooks', 'qrefresh'):
+ c.set('hooks', 'qrefresh', 'python:flake8.hooks.hg_hook')
+
+ if not c.has_section('flake8'):
+ c.add_section('flake8')
+
+ if not c.has_option('flake8', 'complexity'):
+ c.set('flake8', 'complexity', str(getenv('FLAKE8_COMPLEXITY', 10)))
+
+ if not c.has_option('flake8', 'strict'):
+ c.set('flake8', 'strict', getenv('FLAKE8_STRICT', False))
+
+ if not c.has_option('flake8', 'ignore'):
+ c.set('flake8', 'ignore', getenv('FLAKE8_IGNORE', ''))
+
+ if not c.has_option('flake8', 'lazy'):
+ c.set('flake8', 'lazy', getenv('FLAKE8_LAZY', False))
+
+ with open(path, 'w') as fd:
+ c.write(fd)
+
+
+def install_hook():
+ vcs = find_vcs()
+
+ if not vcs:
+ p = get_parser()[0]
+ sys.stderr.write('Error: could not find either a git or mercurial '
+ 'directory. Please re-run this in a proper '
+ 'repository.\n')
+ p.print_help()
+ sys.exit(1)
+
+ status = 0
+ if 'git' in vcs:
+ if os.path.exists(vcs):
+ sys.exit('Error: hook already exists (%s)' % vcs)
+ with open(vcs, 'w') as fd:
+ fd.write(git_hook_file)
+ # rwxr--r--
+ os.chmod(vcs, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
+ elif 'hg' in vcs:
+ _install_hg_hook(vcs)
+ else:
+ status = 1
+
+ sys.exit(status)
diff --git a/old/flake8/main.py b/old/flake8/main.py
new file mode 100644
index 0000000..570b318
--- /dev/null
+++ b/old/flake8/main.py
@@ -0,0 +1,142 @@
+# -*- coding: utf-8 -*-
+import os
+import re
+import sys
+
+import setuptools
+
+from flake8.engine import get_parser, get_style_guide
+from flake8.util import option_normalizer
+
+if sys.platform.startswith('win'):
+ DEFAULT_CONFIG = os.path.expanduser(r'~\.flake8')
+else:
+ DEFAULT_CONFIG = os.path.join(
+ os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'),
+ 'flake8'
+ )
+
+EXTRA_IGNORE = []
+
+
+def main():
+ """Parse options and run checks on Python source."""
+ # Prepare
+ flake8_style = get_style_guide(parse_argv=True, config_file=DEFAULT_CONFIG)
+ options = flake8_style.options
+
+ if options.install_hook:
+ from flake8.hooks import install_hook
+ install_hook()
+
+ # Run the checkers
+ report = flake8_style.check_files()
+
+ exit_code = print_report(report, flake8_style)
+ if exit_code > 0:
+ raise SystemExit(exit_code > 0)
+
+
+def print_report(report, flake8_style):
+ # Print the final report
+ options = flake8_style.options
+ if options.statistics:
+ report.print_statistics()
+ if options.benchmark:
+ report.print_benchmark()
+ if report.total_errors:
+ if options.count:
+ sys.stderr.write(str(report.total_errors) + '\n')
+ if not options.exit_zero:
+ return 1
+ return 0
+
+
+def check_file(path, ignore=(), complexity=-1):
+ """Checks a file using pep8 and pyflakes by default and mccabe
+ optionally.
+
+ :param str path: path to the file to be checked
+ :param tuple ignore: (optional), error and warning codes to be ignored
+ :param int complexity: (optional), enables the mccabe check for values > 0
+ """
+ ignore = set(ignore).union(EXTRA_IGNORE)
+ flake8_style = get_style_guide(
+ config_file=DEFAULT_CONFIG, ignore=ignore, max_complexity=complexity)
+ return flake8_style.input_file(path)
+
+
+def check_code(code, ignore=(), complexity=-1):
+ """Checks code using pep8 and pyflakes by default and mccabe optionally.
+
+ :param str code: code to be checked
+ :param tuple ignore: (optional), error and warning codes to be ignored
+ :param int complexity: (optional), enables the mccabe check for values > 0
+ """
+ ignore = set(ignore).union(EXTRA_IGNORE)
+ flake8_style = get_style_guide(
+ config_file=DEFAULT_CONFIG, ignore=ignore, max_complexity=complexity)
+ return flake8_style.input_file(None, lines=code.splitlines(True))
+
+
+class Flake8Command(setuptools.Command):
+ """The :class:`Flake8Command` class is used by setuptools to perform
+ checks on registered modules.
+ """
+
+ description = "Run flake8 on modules registered in setuptools"
+ user_options = []
+
+ def initialize_options(self):
+ self.option_to_cmds = {}
+ parser = get_parser()[0]
+ for opt in parser.option_list:
+ cmd_name = opt._long_opts[0][2:]
+ option_name = cmd_name.replace('-', '_')
+ self.option_to_cmds[option_name] = opt
+ setattr(self, option_name, None)
+
+ def finalize_options(self):
+ self.options_dict = {}
+ for (option_name, opt) in self.option_to_cmds.items():
+ if option_name in ['help', 'verbose']:
+ continue
+ value = getattr(self, option_name)
+ if value is None:
+ continue
+ value = option_normalizer(value, opt, option_name)
+ # Check if there's any values that need to be fixed.
+ if option_name == "include" and isinstance(value, str):
+ value = re.findall('[^,;\s]+', value)
+
+ self.options_dict[option_name] = value
+
+ def distribution_files(self):
+ if self.distribution.packages:
+ package_dirs = self.distribution.package_dir or {}
+ for package in self.distribution.packages:
+ pkg_dir = package
+ if package in package_dirs:
+ pkg_dir = package_dirs[package]
+ elif '' in package_dirs:
+ pkg_dir = package_dirs[''] + os.path.sep + pkg_dir
+ yield pkg_dir.replace('.', os.path.sep)
+
+ if self.distribution.py_modules:
+ for filename in self.distribution.py_modules:
+ yield "%s.py" % filename
+ # Don't miss the setup.py file itself
+ yield "setup.py"
+
+ def run(self):
+ # Prepare
+ paths = list(self.distribution_files())
+ flake8_style = get_style_guide(config_file=DEFAULT_CONFIG,
+ paths=paths,
+ **self.options_dict)
+
+ # Run the checkers
+ report = flake8_style.check_files()
+ exit_code = print_report(report, flake8_style)
+ if exit_code > 0:
+ raise SystemExit(exit_code > 0)
diff --git a/old/flake8/reporter.py b/old/flake8/reporter.py
new file mode 100644
index 0000000..1df3d9e
--- /dev/null
+++ b/old/flake8/reporter.py
@@ -0,0 +1,152 @@
+# -*- coding: utf-8 -*-
+# Adapted from a contribution of Johan Dahlin
+
+import collections
+import errno
+import re
+import sys
+try:
+ import multiprocessing
+except ImportError: # Python 2.5
+ multiprocessing = None
+
+import pep8
+
+__all__ = ['multiprocessing', 'BaseQReport', 'QueueReport']
+
+
+class BaseQReport(pep8.BaseReport):
+ """Base Queue Report."""
+ _loaded = False # Windows support
+
+ # Reasoning for ignored error numbers is in-line below
+ ignored_errors = set([
+ # EPIPE: Added by sigmavirus24
+ # > If output during processing is piped to something that may close
+ # > its own stdin before we've finished printing results, we need to
+ # > catch a Broken pipe error and continue on.
+ # > (See also: https://gitlab.com/pycqa/flake8/issues/69)
+ errno.EPIPE,
+ # NOTE(sigmavirus24): When adding to this list, include the reasoning
+ # on the lines before the error code and always append your error
+ # code. Further, please always add a trailing `,` to reduce the visual
+ # noise in diffs.
+ ])
+
+ def __init__(self, options):
+ assert options.jobs > 0
+ super(BaseQReport, self).__init__(options)
+ self.counters = collections.defaultdict(int)
+ self.n_jobs = options.jobs
+
+ # init queues
+ self.task_queue = multiprocessing.Queue()
+ self.result_queue = multiprocessing.Queue()
+ if sys.platform == 'win32':
+ # Work around http://bugs.python.org/issue10845
+ sys.modules['__main__'].__file__ = __file__
+
+ def _cleanup_queue(self, queue):
+ while not queue.empty():
+ queue.get_nowait()
+
+ def _put_done(self):
+ # collect queues
+ for i in range(self.n_jobs):
+ self.task_queue.put('DONE')
+ self.update_state(self.result_queue.get())
+
+ def _process_main(self):
+ if not self._loaded:
+ # Windows needs to parse again the configuration
+ from flake8.main import get_style_guide, DEFAULT_CONFIG
+ get_style_guide(parse_argv=True, config_file=DEFAULT_CONFIG)
+ for filename in iter(self.task_queue.get, 'DONE'):
+ self.input_file(filename)
+
+ def start(self):
+ super(BaseQReport, self).start()
+ self.__class__._loaded = True
+ # spawn processes
+ for i in range(self.n_jobs):
+ p = multiprocessing.Process(target=self.process_main)
+ p.daemon = True
+ p.start()
+
+ def stop(self):
+ try:
+ self._put_done()
+ except KeyboardInterrupt:
+ pass
+ finally:
+ # cleanup queues to unlock threads
+ self._cleanup_queue(self.result_queue)
+ self._cleanup_queue(self.task_queue)
+ super(BaseQReport, self).stop()
+
+ def process_main(self):
+ try:
+ self._process_main()
+ except KeyboardInterrupt:
+ pass
+ except IOError as ioerr:
+ # If we happen across an IOError that we aren't certain can/should
+ # be ignored, we should re-raise the exception.
+ if ioerr.errno not in self.ignored_errors:
+ raise
+ finally:
+ # ensure all output is flushed before main process continues
+ sys.stdout.flush()
+ sys.stderr.flush()
+ self.result_queue.put(self.get_state())
+
+ def get_state(self):
+ return {'total_errors': self.total_errors,
+ 'counters': self.counters,
+ 'messages': self.messages}
+
+ def update_state(self, state):
+ self.total_errors += state['total_errors']
+ for key, value in state['counters'].items():
+ self.counters[key] += value
+ self.messages.update(state['messages'])
+
+
+class FileQReport(BaseQReport):
+ """File Queue Report."""
+ print_filename = True
+
+
+class QueueReport(pep8.StandardReport, BaseQReport):
+ """Standard Queue Report."""
+
+ def get_file_results(self):
+ """Print the result and return the overall count for this file."""
+ self._deferred_print.sort()
+
+ for line_number, offset, code, text, doc in self._deferred_print:
+ print(self._fmt % {
+ 'path': self.filename,
+ 'row': self.line_offset + line_number, 'col': offset + 1,
+ 'code': code, 'text': text,
+ })
+ # stdout is block buffered when not stdout.isatty().
+ # line can be broken where buffer boundary since other processes
+ # write to same file.
+ # flush() after print() to avoid buffer boundary.
+ # Typical buffer size is 8192. line written safely when
+ # len(line) < 8192.
+ sys.stdout.flush()
+ if self._show_source:
+ if line_number > len(self.lines):
+ line = ''
+ else:
+ line = self.lines[line_number - 1]
+ print(line.rstrip())
+ sys.stdout.flush()
+ print(re.sub(r'\S', ' ', line[:offset]) + '^')
+ sys.stdout.flush()
+ if self._show_pep8 and doc:
+ print(' ' + doc.strip())
+ sys.stdout.flush()
+ return self.file_errors
diff --git a/old/flake8/run.py b/old/flake8/run.py
new file mode 100644
index 0000000..aca929e
--- /dev/null
+++ b/old/flake8/run.py
@@ -0,0 +1,11 @@
+
+"""
+Implementation of the command-line I{flake8} tool.
+"""
+from flake8.hooks import git_hook, hg_hook # noqa
+from flake8.main import check_code, check_file, Flake8Command # noqa
+from flake8.main import main
+
+
+if __name__ == '__main__':
+ main()
diff --git a/old/flake8/tests/__init__.py b/old/flake8/tests/__init__.py
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/old/flake8/tests/__init__.py
@@ -0,0 +1 @@
+#
diff --git a/old/flake8/tests/_test_warnings.py b/old/flake8/tests/_test_warnings.py
new file mode 100644
index 0000000..004a597
--- /dev/null
+++ b/old/flake8/tests/_test_warnings.py
@@ -0,0 +1,309 @@
+"""
+ _test_warnings.py
+
+ Tests for the warnings that are emitted by flake8.
+
+ This module is named _test_warnings instead of test_warnings so that a
+ normal nosetests run does not collect it. The tests in this module pass
+ when they are run alone, but they fail when they are run along with other
+ tests (nosetests --with-isolation doesn't help).
+
+ In tox.ini, these tests are run separately.
+
+"""
+
+from __future__ import with_statement
+
+import os
+import warnings
+import unittest
+try:
+ from unittest import mock
+except ImportError:
+ import mock # < PY33
+
+from flake8 import engine
+from flake8.util import is_windows
+
+# The Problem
+# ------------
+#
+# Some of the tests in this module pass when this module is run on its own, but
+# they fail when this module is run as part of the whole test suite. These are
+# the problematic tests:
+#
+# test_jobs_verbose
+# test_stdin_jobs_warning
+#
+# On some platforms, the warnings.capture_warnings function doesn't work
+# properly when run with the other flake8 tests. It drops some warnings, even
+# though the warnings filter is set to 'always'. However, when run separately,
+# these tests pass.
+#
+# This problem only occurs on Windows, with Python 3.3 and older. Maybe it's
+# related to PEP 446 - Inheritable file descriptors?
+#
+#
+#
+#
+# Things that didn't work
+# ------------
+#
+# Nose --attr
+# I tried using the nosetests --attr feature to run the tests separately. I
+# put the following in setup.cfg
+#
+# [nosetests]
+# atttr=!run_alone
+#
+# Then I added a tox section thst did this
+#
+# nosetests --attr=run_alone
+#
+# However, the command line --attr would not override the config file --attr,
+# so the special tox section wound up runing all the tests, and failing.
+#
+#
+#
+# Nose --with-isolation
+# The nosetests --with-isolation flag did not help.
+#
+#
+#
+# unittest.skipIf
+# I tried decorating the problematic tests with the unittest.skipIf
+# decorator.
+#
+# @unittest.skipIf(is_windows() and sys.version_info < (3, 4),
+# "Fails on Windows with Python < 3.4 when run with other"
+# " tests.")
+#
+# The idea is, skip the tests in the main test run, on affected platforms.
+# Then, only on those platforms, come back in later and run the tests
+# separately.
+#
+# I added a new stanza to tox.ini, to run the tests separately on the
+# affected platforms.
+#
+# nosetests --no-skip
+#
+# I ran in to a bug in the nosetests skip plugin. It would report the test as
+# having been run, but it would not actually run the test. So, when run with
+# --no-skip, the following test would be reported as having run and passed!
+#
+# @unittest.skip("This passes o_o")
+# def test_should_fail(self):
+# assert 0
+#
+# This bug has been reported here:
+# "--no-skip broken with Python 2.7"
+# https://github.com/nose-devs/nose/issues/512
+#
+#
+#
+# py.test
+#
+# I tried using py.test, and its @pytest.mark.xfail decorator. I added some
+# separate stanzas in tox, and useing the pytest --runxfail option to run the
+# tests separately. This allows us to run all the tests together, on
+# platforms that allow it. On platforms that don't allow us to run the tests
+# all together, this still runs all the tests, but in two separate steps.
+#
+# This is the same solution as the nosetests --no-skip solution I described
+# above, but --runxfail does not have the same bug as --no-skip.
+#
+# This has the advantage that all tests are discoverable by default, outside
+# of tox. However, nose does not recognize the pytest.mark.xfail decorator.
+# So, if a user runs nosetests, it still tries to run the problematic tests
+# together with the rest of the test suite, causing them to fail.
+#
+#
+#
+#
+#
+#
+# Solution
+# ------------
+# Move the problematic tests to _test_warnings.py, so nose.collector will not
+# find them. Set up a separate section in tox.ini that runs this:
+#
+# nosetests flake8.tests._test_warnings
+#
+# This allows all tests to pass on all platforms, when run through tox.
+# However, it means that, even on unaffected platforms, the problematic tests
+# are not discovered and run outside of tox (if the user just runs nosetests
+# manually, for example).
+
+
+class IntegrationTestCaseWarnings(unittest.TestCase):
+ """Integration style tests to check that warnings are issued properly for
+ different command line options."""
+
+ windows_warning_text = ("The --jobs option is not available on Windows."
+ " Ignoring --jobs arguments.")
+ stdin_warning_text = ("The --jobs option is not compatible with"
+ " supplying input using - . Ignoring --jobs"
+ " arguments.")
+
+ def this_file(self):
+ """Return the real path of this file."""
+ this_file = os.path.realpath(__file__)
+ if this_file.endswith("pyc"):
+ this_file = this_file[:-1]
+ return this_file
+
+ @staticmethod
+ def get_style_guide_with_warnings(engine, *args, **kwargs):
+ """
+ Return a style guide object (obtained by calling
+ engine.get_style_guide) and a list of the warnings that were raised in
+ the process.
+
+ Note: not threadsafe
+ """
+
+ # Note
+ # https://docs.python.org/2/library/warnings.html
+ #
+ # The catch_warnings manager works by replacing and then later
+ # restoring the module's showwarning() function and internal list of
+ # filter specifications. This means the context manager is modifying
+ # global state and therefore is not thread-safe
+
+ with warnings.catch_warnings(record=True) as collected_warnings:
+ # Cause all warnings to always be triggered.
+ warnings.simplefilter("always")
+
+ # Get the style guide
+ style_guide = engine.get_style_guide(*args, **kwargs)
+
+ # Now that the warnings have been collected, return the style guide and
+ # the warnings.
+ return (style_guide, collected_warnings)
+
+ def verify_warnings(self, collected_warnings, expected_warnings):
+ """
+ Verifies that collected_warnings is a sequence that contains user
+ warnings that match the sequence of string values passed in as
+ expected_warnings.
+ """
+ if expected_warnings is None:
+ expected_warnings = []
+
+ collected_user_warnings = [w for w in collected_warnings
+ if issubclass(w.category, UserWarning)]
+
+ self.assertEqual(len(collected_user_warnings),
+ len(expected_warnings))
+
+ collected_warnings_set = set(str(warning.message)
+ for warning
+ in collected_user_warnings)
+ expected_warnings_set = set(expected_warnings)
+ self.assertEqual(collected_warnings_set, expected_warnings_set)
+
+ def check_files_collect_warnings(self,
+ arglist=[],
+ explicit_stdin=False,
+ count=0,
+ verbose=False):
+ """Call check_files and collect any warnings that are issued."""
+ if verbose:
+ arglist.append('--verbose')
+ if explicit_stdin:
+ target_file = "-"
+ else:
+ target_file = self.this_file()
+ argv = ['flake8'] + arglist + [target_file]
+ with mock.patch("sys.argv", argv):
+ (style_guide,
+ collected_warnings,
+ ) = self.get_style_guide_with_warnings(engine,
+ parse_argv=True)
+ report = style_guide.check_files()
+ self.assertEqual(report.total_errors, count)
+ return style_guide, report, collected_warnings
+
+ def check_files_no_warnings_allowed(self,
+ arglist=[],
+ explicit_stdin=False,
+ count=0,
+ verbose=False):
+ """Call check_files, and assert that there were no warnings issued."""
+ (style_guide,
+ report,
+ collected_warnings,
+ ) = self.check_files_collect_warnings(arglist=arglist,
+ explicit_stdin=explicit_stdin,
+ count=count,
+ verbose=verbose)
+ self.verify_warnings(collected_warnings, expected_warnings=None)
+ return style_guide, report
+
+ def _job_tester(self, jobs, verbose=False):
+ # mock stdout.flush so we can count the number of jobs created
+ with mock.patch('sys.stdout.flush') as mocked:
+ (guide,
+ report,
+ collected_warnings,
+ ) = self.check_files_collect_warnings(
+ arglist=['--jobs=%s' % jobs],
+ verbose=verbose)
+
+ if is_windows():
+ # The code path where guide.options.jobs gets converted to an
+ # int is not run on windows. So, do the int conversion here.
+ self.assertEqual(int(guide.options.jobs), jobs)
+ # On windows, call count is always zero.
+ self.assertEqual(mocked.call_count, 0)
+ else:
+ self.assertEqual(guide.options.jobs, jobs)
+ self.assertEqual(mocked.call_count, jobs)
+
+ expected_warings = []
+ if verbose and is_windows():
+ expected_warings.append(self.windows_warning_text)
+ self.verify_warnings(collected_warnings, expected_warings)
+
+ def test_jobs(self, verbose=False):
+ self._job_tester(2, verbose=verbose)
+ self._job_tester(10, verbose=verbose)
+
+ def test_no_args_no_warnings(self, verbose=False):
+ self.check_files_no_warnings_allowed(verbose=verbose)
+
+ def test_stdin_jobs_warning(self, verbose=False):
+ self.count = 0
+
+ def fake_stdin():
+ self.count += 1
+ with open(self.this_file(), "r") as f:
+ return f.read()
+
+ with mock.patch("pep8.stdin_get_value", fake_stdin):
+ (style_guide,
+ report,
+ collected_warnings,
+ ) = self.check_files_collect_warnings(arglist=['--jobs=4'],
+ explicit_stdin=True,
+ verbose=verbose)
+ expected_warings = []
+ if verbose:
+ expected_warings.append(self.stdin_warning_text)
+ if is_windows():
+ expected_warings.append(self.windows_warning_text)
+ self.verify_warnings(collected_warnings, expected_warings)
+ self.assertEqual(self.count, 1)
+
+ def test_jobs_verbose(self):
+ self.test_jobs(verbose=True)
+
+ def test_no_args_no_warnings_verbose(self):
+ self.test_no_args_no_warnings(verbose=True)
+
+ def test_stdin_jobs_warning_verbose(self):
+ self.test_stdin_jobs_warning(verbose=True)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/old/flake8/tests/test_engine.py b/old/flake8/tests/test_engine.py
new file mode 100644
index 0000000..82ba0dd
--- /dev/null
+++ b/old/flake8/tests/test_engine.py
@@ -0,0 +1,236 @@
+from __future__ import with_statement
+
+import errno
+import unittest
+try:
+ from unittest import mock
+except ImportError:
+ import mock # < PY33
+
+from flake8 import engine, util, __version__, reporter
+import pep8
+
+
+class TestEngine(unittest.TestCase):
+ def setUp(self):
+ self.patches = {}
+
+ def tearDown(self):
+ assert len(self.patches.items()) == 0
+
+ def start_patch(self, patch):
+ self.patches[patch] = mock.patch(patch)
+ return self.patches[patch].start()
+
+ def stop_patches(self):
+ patches = self.patches.copy()
+ for k, v in patches.items():
+ v.stop()
+ del(self.patches[k])
+
+ def test_get_style_guide(self):
+ with mock.patch('flake8.engine._register_extensions') as reg_ext:
+ reg_ext.return_value = ([], [], [], [])
+ g = engine.get_style_guide()
+ self.assertTrue(isinstance(g, engine.StyleGuide))
+ reg_ext.assert_called_once_with()
+
+ def test_get_style_guide_kwargs(self):
+ m = mock.Mock()
+ with mock.patch('flake8.engine.StyleGuide') as StyleGuide:
+ with mock.patch('flake8.engine.get_parser') as get_parser:
+ m.ignored_extensions = []
+ StyleGuide.return_value.options.jobs = '42'
+ StyleGuide.return_value.options.diff = False
+ get_parser.return_value = (m, [])
+ engine.get_style_guide(foo='bar')
+ get_parser.assert_called_once_with()
+ StyleGuide.assert_called_once_with(**{'parser': m, 'foo': 'bar'})
+
+ def test_register_extensions(self):
+ with mock.patch('pep8.register_check') as register_check:
+ registered_exts = engine._register_extensions()
+ self.assertTrue(isinstance(registered_exts[0], util.OrderedSet))
+ self.assertTrue(len(registered_exts[0]) > 0)
+ for i in registered_exts[1:]:
+ self.assertTrue(isinstance(i, list))
+ self.assertTrue(register_check.called)
+
+ def test_disable_extensions(self):
+ parser = mock.MagicMock()
+ options = mock.MagicMock()
+
+ parser.ignored_extensions = ['I123', 'I345', 'I678', 'I910']
+
+ options.enable_extensions = 'I345,\nI678,I910'
+ options.ignore = ('E121', 'E123')
+
+ engine._disable_extensions(parser, options)
+ self.assertEqual(set(options.ignore), set(['E121', 'E123', 'I123']))
+
+ def test_get_parser(self):
+ # setup
+ re = self.start_patch('flake8.engine._register_extensions')
+ gpv = self.start_patch('flake8.engine.get_python_version')
+ pgp = self.start_patch('pep8.get_parser')
+ m = mock.Mock()
+ re.return_value = ([('pyflakes', '0.7'), ('mccabe', '0.2')], [], [],
+ [])
+ gpv.return_value = 'Python Version'
+ pgp.return_value = m
+ # actual call we're testing
+ parser, hooks = engine.get_parser()
+ # assertions
+ self.assertTrue(re.called)
+ self.assertTrue(gpv.called)
+ pgp.assert_called_once_with(
+ 'flake8',
+ '%s (pyflakes: 0.7, mccabe: 0.2) Python Version' % __version__)
+ self.assertTrue(m.remove_option.called)
+ self.assertTrue(m.add_option.called)
+ self.assertEqual(parser, m)
+ self.assertEqual(hooks, [])
+ # clean-up
+ self.stop_patches()
+
+ def test_get_python_version(self):
+ self.assertTrue('on' in engine.get_python_version())
+ # Silly test but it will provide 100% test coverage
+ # Also we can never be sure (without reconstructing the string
+ # ourselves) what system we may be testing on.
+
+ def test_windows_disables_jobs(self):
+ with mock.patch('flake8.util.is_windows') as is_windows:
+ is_windows.return_value = True
+ guide = engine.get_style_guide()
+ assert isinstance(guide, reporter.BaseQReport) is False
+
+ def test_stdin_disables_jobs(self):
+ with mock.patch('flake8.util.is_using_stdin') as is_using_stdin:
+ is_using_stdin.return_value = True
+ guide = engine.get_style_guide()
+ assert isinstance(guide, reporter.BaseQReport) is False
+
+ def test_disables_extensions_that_are_not_selected(self):
+ with mock.patch('flake8.engine._register_extensions') as re:
+ re.return_value = ([('fake_ext', '0.1a1')], [], [], ['X'])
+ sg = engine.get_style_guide()
+ assert 'X' in sg.options.ignore
+
+ def test_enables_off_by_default_extensions(self):
+ with mock.patch('flake8.engine._register_extensions') as re:
+ re.return_value = ([('fake_ext', '0.1a1')], [], [], ['X'])
+ parser, options = engine.get_parser()
+ parser.parse_args(['--select=X'])
+ sg = engine.StyleGuide(parser=parser)
+ assert 'X' not in sg.options.ignore
+
+ def test_load_entry_point_verifies_requirements(self):
+ entry_point = mock.Mock(spec=['require', 'resolve', 'load'])
+
+ engine._load_entry_point(entry_point, verify_requirements=True)
+ entry_point.require.assert_called_once_with()
+ entry_point.resolve.assert_called_once_with()
+
+ def test_load_entry_point_does_not_verify_requirements(self):
+ entry_point = mock.Mock(spec=['require', 'resolve', 'load'])
+
+ engine._load_entry_point(entry_point, verify_requirements=False)
+ self.assertFalse(entry_point.require.called)
+ entry_point.resolve.assert_called_once_with()
+
+ def test_load_entry_point_passes_require_argument_to_load(self):
+ entry_point = mock.Mock(spec=['load'])
+
+ engine._load_entry_point(entry_point, verify_requirements=True)
+ entry_point.load.assert_called_once_with(require=True)
+ entry_point.reset_mock()
+
+ engine._load_entry_point(entry_point, verify_requirements=False)
+ entry_point.load.assert_called_once_with(require=False)
+
+
+def oserror_generator(error_number, message='Ominous OSError message'):
+ def oserror_side_effect(*args, **kwargs):
+ if hasattr(oserror_side_effect, 'used'):
+ return
+
+ oserror_side_effect.used = True
+ raise OSError(error_number, message)
+
+ return oserror_side_effect
+
+
+class TestStyleGuide(unittest.TestCase):
+ def setUp(self):
+ mocked_styleguide = mock.Mock(spec=engine.NoQAStyleGuide)
+ self.styleguide = engine.StyleGuide(styleguide=mocked_styleguide)
+ self.mocked_sg = mocked_styleguide
+
+ def test_proxies_excluded(self):
+ self.styleguide.excluded('file.py', parent='.')
+
+ self.mocked_sg.excluded.assert_called_once_with('file.py', parent='.')
+
+ def test_proxies_init_report(self):
+ reporter = object()
+ self.styleguide.init_report(reporter)
+
+ self.mocked_sg.init_report.assert_called_once_with(reporter)
+
+ def test_proxies_check_files(self):
+ self.styleguide.check_files(['foo', 'bar'])
+
+ self.mocked_sg.check_files.assert_called_once_with(
+ paths=['foo', 'bar']
+ )
+
+ def test_proxies_input_file(self):
+ self.styleguide.input_file('file.py',
+ lines=[9, 10],
+ expected='foo',
+ line_offset=20)
+
+ self.mocked_sg.input_file.assert_called_once_with(filename='file.py',
+ lines=[9, 10],
+ expected='foo',
+ line_offset=20)
+
+ def test_check_files_retries_on_specific_OSErrors(self):
+ self.mocked_sg.check_files.side_effect = oserror_generator(
+ errno.ENOSPC, 'No space left on device'
+ )
+
+ self.styleguide.check_files(['foo', 'bar'])
+
+ self.mocked_sg.init_report.assert_called_once_with(pep8.StandardReport)
+
+ def test_input_file_retries_on_specific_OSErrors(self):
+ self.mocked_sg.input_file.side_effect = oserror_generator(
+ errno.ENOSPC, 'No space left on device'
+ )
+
+ self.styleguide.input_file('file.py')
+
+ self.mocked_sg.init_report.assert_called_once_with(pep8.StandardReport)
+
+ def test_check_files_reraises_unknown_OSErrors(self):
+ self.mocked_sg.check_files.side_effect = oserror_generator(
+ errno.EADDRINUSE,
+ 'lol why are we talking about binding to sockets'
+ )
+
+ self.assertRaises(OSError, self.styleguide.check_files,
+ ['foo', 'bar'])
+
+ def test_input_file_reraises_unknown_OSErrors(self):
+ self.mocked_sg.input_file.side_effect = oserror_generator(
+ errno.EADDRINUSE,
+ 'lol why are we talking about binding to sockets'
+ )
+
+ self.assertRaises(OSError, self.styleguide.input_file,
+ ['foo', 'bar'])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/old/flake8/tests/test_hooks.py b/old/flake8/tests/test_hooks.py
new file mode 100644
index 0000000..ba46794
--- /dev/null
+++ b/old/flake8/tests/test_hooks.py
@@ -0,0 +1,59 @@
+"""Module containing the tests for flake8.hooks."""
+import os
+import unittest
+
+try:
+ from unittest import mock
+except ImportError:
+ import mock
+
+import flake8.hooks
+from flake8.util import is_windows
+
+
+def excluded(filename):
+ return filename.endswith('afile.py')
+
+
+class TestGitHook(unittest.TestCase):
+ if is_windows:
+ # On Windows, absolute paths start with a drive letter, for example C:
+ # Here we build a fake absolute path starting with the current drive
+ # letter, for example C:\fake\temp
+ current_drive, ignore_tail = os.path.splitdrive(os.getcwd())
+ fake_abs_path = os.path.join(current_drive, os.path.sep, 'fake', 'tmp')
+ else:
+ fake_abs_path = os.path.join(os.path.sep, 'fake', 'tmp')
+
+ @mock.patch('os.makedirs')
+ @mock.patch('flake8.hooks.open', create=True)
+ @mock.patch('shutil.rmtree')
+ @mock.patch('tempfile.mkdtemp', return_value=fake_abs_path)
+ @mock.patch('flake8.hooks.run',
+ return_value=(None,
+ [os.path.join('foo', 'afile.py'),
+ os.path.join('foo', 'bfile.py')],
+ None))
+ @mock.patch('flake8.hooks.get_style_guide')
+ def test_prepends_tmp_directory_to_exclude(self, get_style_guide, run,
+ *args):
+ style_guide = get_style_guide.return_value = mock.Mock()
+ style_guide.options.exclude = [os.path.join('foo', 'afile.py')]
+ style_guide.options.filename = [os.path.join('foo', '*')]
+ style_guide.excluded = excluded
+
+ flake8.hooks.git_hook()
+
+ dirname, filename = os.path.split(
+ os.path.abspath(os.path.join('foo', 'bfile.py')))
+ if is_windows:
+ # In Windows, the absolute path in dirname will start with a drive
+ # letter. Here, we discad the drive letter.
+ ignore_drive, dirname = os.path.splitdrive(dirname)
+ tmpdir = os.path.join(self.fake_abs_path, dirname[1:])
+ tmpfile = os.path.join(tmpdir, 'bfile.py')
+ style_guide.check_files.assert_called_once_with([tmpfile])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/old/flake8/tests/test_integration.py b/old/flake8/tests/test_integration.py
new file mode 100644
index 0000000..d1417c6
--- /dev/null
+++ b/old/flake8/tests/test_integration.py
@@ -0,0 +1,79 @@
+from __future__ import with_statement
+
+import os
+import unittest
+try:
+ from unittest import mock
+except ImportError:
+ import mock # < PY33
+
+from flake8 import engine
+from flake8.util import is_windows
+
+
+class IntegrationTestCase(unittest.TestCase):
+ """Integration style tests to exercise different command line options."""
+
+ def this_file(self):
+ """Return the real path of this file."""
+ this_file = os.path.realpath(__file__)
+ if this_file.endswith("pyc"):
+ this_file = this_file[:-1]
+ return this_file
+
+ def check_files(self, arglist=[], explicit_stdin=False, count=0):
+ """Call check_files."""
+ if explicit_stdin:
+ target_file = "-"
+ else:
+ target_file = self.this_file()
+ argv = ['flake8'] + arglist + [target_file]
+ with mock.patch("sys.argv", argv):
+ style_guide = engine.get_style_guide(parse_argv=True)
+ report = style_guide.check_files()
+ self.assertEqual(report.total_errors, count)
+ return style_guide, report
+
+ def test_no_args(self):
+ # assert there are no reported errors
+ self.check_files()
+
+ def _job_tester(self, jobs):
+ # mock stdout.flush so we can count the number of jobs created
+ with mock.patch('sys.stdout.flush') as mocked:
+ guide, report = self.check_files(arglist=['--jobs=%s' % jobs])
+ if is_windows():
+ # The code path where guide.options.jobs gets converted to an
+ # int is not run on windows. So, do the int conversion here.
+ self.assertEqual(int(guide.options.jobs), jobs)
+ # On windows, call count is always zero.
+ self.assertEqual(mocked.call_count, 0)
+ else:
+ self.assertEqual(guide.options.jobs, jobs)
+ self.assertEqual(mocked.call_count, jobs)
+
+ def test_jobs(self):
+ self._job_tester(2)
+ self._job_tester(10)
+
+ def test_stdin(self):
+ self.count = 0
+
+ def fake_stdin():
+ self.count += 1
+ with open(self.this_file(), "r") as f:
+ return f.read()
+
+ with mock.patch("pep8.stdin_get_value", fake_stdin):
+ guide, report = self.check_files(arglist=['--jobs=4'],
+ explicit_stdin=True)
+ self.assertEqual(self.count, 1)
+
+ def test_stdin_fail(self):
+ def fake_stdin():
+ return "notathing\n"
+ with mock.patch("pep8.stdin_get_value", fake_stdin):
+ # only assert needed is in check_files
+ guide, report = self.check_files(arglist=['--jobs=4'],
+ explicit_stdin=True,
+ count=1)
diff --git a/old/flake8/tests/test_main.py b/old/flake8/tests/test_main.py
new file mode 100644
index 0000000..af08093
--- /dev/null
+++ b/old/flake8/tests/test_main.py
@@ -0,0 +1,18 @@
+from __future__ import with_statement
+
+import unittest
+
+import setuptools
+from flake8 import main
+
+
+class TestMain(unittest.TestCase):
+ def test_issue_39_regression(self):
+ distribution = setuptools.Distribution()
+ cmd = main.Flake8Command(distribution)
+ cmd.options_dict = {}
+ cmd.run()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/old/flake8/tests/test_pyflakes.py b/old/flake8/tests/test_pyflakes.py
new file mode 100644
index 0000000..fb2f042
--- /dev/null
+++ b/old/flake8/tests/test_pyflakes.py
@@ -0,0 +1,73 @@
+from __future__ import with_statement
+
+import ast
+import unittest
+
+from collections import namedtuple
+
+from flake8._pyflakes import FlakesChecker
+
+Options = namedtuple("Options", ['builtins', 'doctests',
+ 'include_in_doctest',
+ 'exclude_from_doctest'])
+
+
+class TestFlakesChecker(unittest.TestCase):
+
+ def setUp(self):
+ self.tree = ast.parse('print("cookies")')
+
+ def test_doctest_flag_enabled(self):
+ options = Options(builtins=None, doctests=True,
+ include_in_doctest='',
+ exclude_from_doctest='')
+ FlakesChecker.parse_options(options)
+ flake_checker = FlakesChecker(self.tree, 'cookies.txt')
+ assert flake_checker.withDoctest is True
+
+ def test_doctest_flag_disabled(self):
+ options = Options(builtins=None, doctests=False,
+ include_in_doctest='',
+ exclude_from_doctest='')
+ FlakesChecker.parse_options(options)
+ flake_checker = FlakesChecker(self.tree, 'cookies.txt')
+ assert flake_checker.withDoctest is False
+
+ def test_doctest_flag_enabled_exclude_file(self):
+ options = Options(builtins=None, doctests=True,
+ include_in_doctest='',
+ exclude_from_doctest='cookies.txt,'
+ 'hungry/cookies.txt')
+ FlakesChecker.parse_options(options)
+ flake_checker = FlakesChecker(self.tree, './cookies.txt')
+ assert flake_checker.withDoctest is False
+
+ def test_doctest_flag_disabled_include_file(self):
+ options = Options(builtins=None, doctests=False,
+ include_in_doctest='./cookies.txt,cake_yuck.txt',
+ exclude_from_doctest='')
+ FlakesChecker.parse_options(options)
+ flake_checker = FlakesChecker(self.tree, './cookies.txt')
+ assert flake_checker.withDoctest is True
+
+ def test_doctest_flag_disabled_include_file_exclude_dir(self):
+ options = Options(builtins=None, doctests=False,
+ include_in_doctest='./cookies.txt',
+ exclude_from_doctest='./')
+ FlakesChecker.parse_options(options)
+ flake_checker = FlakesChecker(self.tree, './cookies.txt')
+ assert flake_checker.withDoctest is True
+
+ def test_doctest_flag_disabled_include_dir_exclude_file(self):
+ options = Options(builtins=None, doctests=False,
+ include_in_doctest='./',
+ exclude_from_doctest='./cookies.txt')
+ FlakesChecker.parse_options(options)
+ flake_checker = FlakesChecker(self.tree, './cookies.txt')
+ assert flake_checker.withDoctest is False
+
+ def test_doctest_flag_disabled_include_file_exclude_file_error(self):
+ options = Options(builtins=None, doctests=False,
+ include_in_doctest='./cookies.txt',
+ exclude_from_doctest='./cookies.txt,cake_yuck.txt')
+ self.assertRaises(ValueError, FlakesChecker.parse_options, options)
diff --git a/old/flake8/tests/test_reporter.py b/old/flake8/tests/test_reporter.py
new file mode 100644
index 0000000..f91bb52
--- /dev/null
+++ b/old/flake8/tests/test_reporter.py
@@ -0,0 +1,36 @@
+from __future__ import with_statement
+
+import errno
+import unittest
+try:
+ from unittest import mock
+except ImportError:
+ import mock # < PY33
+
+from flake8 import reporter
+
+
+def ioerror_report_factory(errno_code):
+ class IOErrorBaseQReport(reporter.BaseQReport):
+ def _process_main(self):
+ raise IOError(errno_code, 'Fake bad pipe exception')
+
+ options = mock.MagicMock()
+ options.jobs = 2
+ return IOErrorBaseQReport(options)
+
+
+class TestBaseQReport(unittest.TestCase):
+ def test_does_not_raise_a_bad_pipe_ioerror(self):
+ """Test that no EPIPE IOError exception is re-raised or leaked."""
+ report = ioerror_report_factory(errno.EPIPE)
+ try:
+ report.process_main()
+ except IOError:
+ self.fail('BaseQReport.process_main raised an IOError for EPIPE'
+ ' but it should have caught this exception.')
+
+ def test_raises_a_enoent_ioerror(self):
+ """Test that an ENOENT IOError exception is re-raised."""
+ report = ioerror_report_factory(errno.ENOENT)
+ self.assertRaises(IOError, report.process_main)
diff --git a/old/flake8/tests/test_util.py b/old/flake8/tests/test_util.py
new file mode 100644
index 0000000..bfbc660
--- /dev/null
+++ b/old/flake8/tests/test_util.py
@@ -0,0 +1,120 @@
+import optparse
+import unittest
+
+from flake8.util import option_normalizer
+
+
+class TestOptionSerializerParsesTrue(unittest.TestCase):
+
+ def setUp(self):
+ self.option = optparse.Option('--foo', action='store_true')
+ self.option_name = 'fake_option'
+
+ def test_1_is_true(self):
+ value = option_normalizer('1', self.option, self.option_name)
+ self.assertTrue(value)
+
+ def test_T_is_true(self):
+ value = option_normalizer('T', self.option, self.option_name)
+ self.assertTrue(value)
+
+ def test_TRUE_is_true(self):
+ value = option_normalizer('TRUE', self.option, self.option_name)
+ self.assertTrue(value, True)
+
+ def test_ON_is_true(self):
+ value = option_normalizer('ON', self.option, self.option_name)
+ self.assertTrue(value)
+
+ def test_t_is_true(self):
+ value = option_normalizer('t', self.option, self.option_name)
+ self.assertTrue(value)
+
+ def test_true_is_true(self):
+ value = option_normalizer('true', self.option, self.option_name)
+ self.assertTrue(value)
+
+ def test_on_is_true(self):
+ value = option_normalizer('on', self.option, self.option_name)
+ self.assertTrue(value)
+
+
+class TestOptionSerializerParsesFalse(unittest.TestCase):
+
+ def setUp(self):
+ self.option = optparse.Option('--foo', action='store_true')
+ self.option_name = 'fake_option'
+
+ def test_0_is_false(self):
+ value = option_normalizer('0', self.option, self.option_name)
+ self.assertFalse(value)
+
+ def test_F_is_false(self):
+ value = option_normalizer('F', self.option, self.option_name)
+ self.assertFalse(value)
+
+ def test_FALSE_is_false(self):
+ value = option_normalizer('FALSE', self.option, self.option_name)
+ self.assertFalse(value)
+
+ def test_OFF_is_false(self):
+ value = option_normalizer('OFF', self.option, self.option_name)
+ self.assertFalse(value)
+
+ def test_f_is_false(self):
+ value = option_normalizer('f', self.option, self.option_name)
+ self.assertFalse(value)
+
+ def test_false_is_false(self):
+ value = option_normalizer('false', self.option, self.option_name)
+ self.assertFalse(value)
+
+ def test_off_is_false(self):
+ value = option_normalizer('off', self.option, self.option_name)
+ self.assertFalse(value)
+
+
+class TestOptionSerializerParsesLists(unittest.TestCase):
+
+ def setUp(self):
+ self.option = optparse.Option('--select')
+ self.option_name = 'select'
+ self.answer = ['F401', 'F402', 'F403', 'F404']
+
+ def test_parses_simple_comma_separated_lists(self):
+ value = option_normalizer('F401,F402,F403,F404', self.option,
+ self.option_name)
+ self.assertEqual(value, self.answer)
+
+ def test_parses_less_simple_comma_separated_lists(self):
+ value = option_normalizer('F401 ,F402 ,F403 ,F404', self.option,
+ self.option_name)
+ self.assertEqual(value, self.answer)
+
+ value = option_normalizer('F401, F402, F403, F404', self.option,
+ self.option_name)
+ self.assertEqual(value, self.answer)
+
+ def test_parses_comma_separated_lists_with_newlines(self):
+ value = option_normalizer('''\
+ F401,
+ F402,
+ F403,
+ F404,
+ ''', self.option, self.option_name)
+ self.assertEqual(value, self.answer)
+
+
+class TestOptionSerializerParsesInts(unittest.TestCase):
+
+ def setUp(self):
+ self.option = optparse.Option('--max-complexity', type='int')
+ self.option_name = 'max_complexity'
+
+ def test_parses_an_int(self):
+ value = option_normalizer('2', self.option, self.option_name)
+ self.assertEqual(value, 2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/old/flake8/util.py b/old/flake8/util.py
new file mode 100644
index 0000000..4e2c0d3
--- /dev/null
+++ b/old/flake8/util.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+import os
+
+try:
+ import ast
+ iter_child_nodes = ast.iter_child_nodes
+except ImportError: # Python 2.5
+ import _ast as ast
+
+ if 'decorator_list' not in ast.ClassDef._fields:
+ # Patch the missing attribute 'decorator_list'
+ ast.ClassDef.decorator_list = ()
+ ast.FunctionDef.decorator_list = property(lambda s: s.decorators)
+
+ def iter_child_nodes(node):
+ """
+ Yield all direct child nodes of *node*, that is, all fields that
+ are nodes and all items of fields that are lists of nodes.
+ """
+ if not node._fields:
+ return
+ for name in node._fields:
+ field = getattr(node, name, None)
+ if isinstance(field, ast.AST):
+ yield field
+ elif isinstance(field, list):
+ for item in field:
+ if isinstance(item, ast.AST):
+ yield item
+
+
+class OrderedSet(list):
+ """List without duplicates."""
+ __slots__ = ()
+
+ def add(self, value):
+ if value not in self:
+ self.append(value)
+
+
+def is_windows():
+ """Determine if the system is Windows."""
+ return os.name == 'nt'
+
+
+def is_using_stdin(paths):
+ """Determine if we're running checks on stdin."""
+ return '-' in paths
+
+
+def warn_when_using_jobs(options):
+ return (options.verbose and options.jobs and options.jobs.isdigit() and
+ int(options.jobs) > 1)
+
+
+def force_disable_jobs(styleguide):
+ return is_windows() or is_using_stdin(styleguide.paths)
+
+
+INT_TYPES = ('int', 'count')
+BOOL_TYPES = ('store_true', 'store_false')
+LIST_OPTIONS = ('select', 'ignore', 'exclude', 'enable_extensions')
+
+
+def option_normalizer(value, option, option_name):
+ if option.action in BOOL_TYPES:
+ if str(value).upper() in ('1', 'T', 'TRUE', 'ON'):
+ value = True
+ if str(value).upper() in ('0', 'F', 'FALSE', 'OFF'):
+ value = False
+ elif option.type in INT_TYPES:
+ value = int(value)
+ elif option_name in LIST_OPTIONS:
+ if isinstance(value, str):
+ value = [opt.strip() for opt in value.split(',') if opt.strip()]
+
+ return value
diff --git a/old/setup.py b/old/setup.py
new file mode 100644
index 0000000..fab5e86
--- /dev/null
+++ b/old/setup.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+from __future__ import with_statement
+from setuptools import setup
+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 = ['nose']
+if mock is None:
+ tests_require += ['mock']
+
+
+def get_version(fname='flake8/__init__.py'):
+ with open(fname) as f:
+ for line in f:
+ if line.startswith('__version__'):
+ return eval(line.split('=')[-1])
+
+
+def get_long_description():
+ descr = []
+ for fname in ('README.rst', 'CHANGES.rst'):
+ with open(fname) as f:
+ descr.append(f.read())
+ return '\n\n'.join(descr)
+
+
+setup(
+ name="flake8",
+ license="MIT",
+ version=get_version(),
+ description="the modular source code checker: pep8, pyflakes and co",
+ long_description=get_long_description(),
+ author="Tarek Ziade",
+ author_email="tarek@ziade.org",
+ maintainer="Ian Cordasco",
+ maintainer_email="graffatcolmingov@gmail.com",
+ url="https://gitlab.com/pycqa/flake8",
+ packages=["flake8", "flake8.tests"],
+ install_requires=[
+ "pyflakes >= 0.8.1, < 1.1",
+ "pep8 >= 1.5.7, != 1.6.0, != 1.6.1, != 1.6.2",
+ "mccabe >= 0.2.1, < 0.5",
+ ],
+ entry_points={
+ 'distutils.commands': ['flake8 = flake8.main:Flake8Command'],
+ 'console_scripts': ['flake8 = flake8.main:main'],
+ 'flake8.extension': [
+ 'F = flake8._pyflakes:FlakesChecker',
+ ],
+ },
+ classifiers=[
+ "Environment :: Console",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: MIT License",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 3",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "Topic :: Software Development :: Quality Assurance",
+ ],
+ tests_require=tests_require,
+ test_suite='nose.collector',
+)
diff --git a/old/tox.ini b/old/tox.ini
new file mode 100644
index 0000000..14e2a44
--- /dev/null
+++ b/old/tox.ini
@@ -0,0 +1,40 @@
+[tox]
+minversion = 1.6
+envlist =
+ py26,py27,py33,py34,py27-flake8,py34-flake8
+
+[testenv]
+usedevelop = True
+deps =
+ mock
+ nose
+commands =
+ python setup.py test -q
+ python setup.py flake8
+ nosetests flake8.tests._test_warnings
+
+[testenv:py27-flake8]
+basepython = python2.7
+deps =
+ flake8
+commands = flake8 {posargs} flake8/
+
+[testenv:py34-flake8]
+basepython = python3.4
+deps =
+ flake8
+commands = flake8 {posargs} flake8/
+
+[testenv:release]
+basepython = python2.7
+deps =
+ twine >= 1.5.0
+ wheel
+commands =
+ python setup.py sdist bdist_wheel
+ twine upload --skip-existing {posargs} dist/*
+
+[flake8]
+select = E,F,W
+max_line_length = 79
+exclude = .git,.tox,dist,docs,*egg