diff options
-rw-r--r-- | .travis.yml | 18 | ||||
-rw-r--r-- | CHANGES.txt | 91 | ||||
-rw-r--r-- | CONTRIBUTING.rst | 4 | ||||
-rw-r--r-- | LICENSE | 1 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | README.rst | 41 | ||||
-rw-r--r-- | docs/Makefile | 8 | ||||
-rw-r--r-- | docs/advanced.rst | 55 | ||||
-rw-r--r-- | docs/api.rst | 10 | ||||
-rw-r--r-- | docs/conf.py | 30 | ||||
-rw-r--r-- | docs/developer.rst | 44 | ||||
-rw-r--r-- | docs/index.rst | 16 | ||||
-rw-r--r-- | docs/intro.rst | 471 | ||||
-rw-r--r-- | docs/make.bat | 4 | ||||
-rwxr-xr-x | pycodestyle.py (renamed from pep8.py) | 289 | ||||
-rw-r--r-- | setup.py | 14 | ||||
-rw-r--r-- | testsuite/E12.py | 6 | ||||
-rw-r--r-- | testsuite/E25.py | 9 | ||||
-rw-r--r-- | testsuite/E27.py | 14 | ||||
-rw-r--r-- | testsuite/E40.py | 25 | ||||
-rw-r--r-- | testsuite/E50.py | 14 | ||||
-rw-r--r-- | testsuite/E71.py | 18 | ||||
-rw-r--r-- | testsuite/W19.py | 2 | ||||
-rw-r--r-- | testsuite/support.py | 7 | ||||
-rw-r--r-- | testsuite/test_all.py | 19 | ||||
-rw-r--r-- | testsuite/test_api.py | 151 | ||||
-rw-r--r-- | testsuite/test_parser.py | 61 | ||||
-rw-r--r-- | testsuite/test_shell.py | 26 | ||||
-rw-r--r-- | testsuite/test_util.py | 20 | ||||
-rw-r--r-- | tox.ini | 10 |
30 files changed, 968 insertions, 516 deletions
diff --git a/.travis.yml b/.travis.yml index b188325..ee069e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,29 @@ language: python +sudo: false python: - 2.6 - 2.7 - 3.2 - 3.3 - 3.4 + - 3.5 + - nightly - pypy - pypy3 install: - pip install -e . - pip list script: - - python pep8.py --testsuite testsuite - - python pep8.py --statistics pep8.py - - python pep8.py --doctest + - python pycodestyle.py --testsuite testsuite + - python pycodestyle.py --statistics pycodestyle.py + - python pycodestyle.py --doctest - python setup.py test -matrix: - allow_failures: - - python: pypy - - python: pypy3 notifications: email: - IanLee1521@gmail.com + irc: + channels: + - "irc.freenode.org##python-code-quality" + use_notice: true + skip_join: true diff --git a/CHANGES.txt b/CHANGES.txt index d53fb70..e129dc8 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,8 +2,73 @@ Changelog ========= -1.x (unreleased) ----------------- +2.0.0 (2016-05-31) +------------------ + +Announcements: + +* Repository renamed to `pycodestyle`; Issue #466 / #481. +* Added joint Code of Conduct as member of PyCQA; #483 + +Changes: + +* Added tox test support for Python 3.5 and pypy3 +* Added check E275 for whitespace on `from ... import ...` lines; #489 / #491 +* Added W503 to the list of codes ignored by default ignore list; #498 +* Removed use of project level `.pep8` configuration file; #364 + +Bugs: + +* Fixed bug with treating `~` operator as binary; #383 / #384 +* Identify binary operators as unary; #484 / #485 + +1.7.0 (2016-01-12) +------------------ + +Announcements: + +* Repository moved to PyCQA Organization on GitHub: + https://github.com/pycqa/pep8 + +Changes: + +* Reverted the fix in #368, "options passed on command line are only ones + accepted" feature. This has many unintended consequences in pep8 and flake8 + and needs to be reworked when I have more time. +* Added support for Python 3.5. (Issue #420 & #459) +* Added support for multi-line config_file option parsing. (Issue #429) +* Improved parameter parsing. (Issues #420 & #456) + +Bugs: + +* Fixed BytesWarning on Python 3. (Issue #459) + +1.6.2 (2015-02-15) +------------------ + +Changes: + +* Added check for breaking around a binary operator. (Issue #197, Pull #305) + +Bugs: + +* Restored config_file parameter in process_options(). (Issue #380) + + +1.6.1 (2015-02-08) +------------------ + +Changes: + +* Assign variables before referenced. (Issue #287) + +Bugs: + +* Exception thrown due to unassigned ``local_dir`` variable. (Issue #377) + + +1.6.0 (2015-02-06) +------------------ News: @@ -32,6 +97,15 @@ Changes: * Add ``.tox/`` to default excludes. (Issue #335) +* Do not report E121 or E126 in the default configuration. (Issues #256 / #316) + +* Allow spaces around the equals sign in an annotated function. (Issue #357) + +* Allow trailing backslash if in an inline comment. (Issue #374) + +* If ``--config`` is used, only that configuration is processed. Otherwise, + merge the user and local configurations are merged. (Issue #368 / #369) + Bug fixes: * Don't crash if Checker.build_tokens_line() returns None. (Issue #306) @@ -43,6 +117,11 @@ Bug fixes: * Fix false positive E711/E712/E713. (Issues #330 and #336) +* Do not skip physical checks if the newline is escaped. (Issue #319) + +* Flush sys.stdout to avoid race conditions with printing. See flake8 bug: + https://gitlab.com/pycqa/flake8/issues/17 for more details. (Issue #363) + 1.5.7 (2014-05-29) ------------------ @@ -274,7 +353,7 @@ Bug fixes: * Initiate a graceful shutdown on ``Control+C``. -* Allow to change the ``checker_class`` for the ``StyleGuide``. +* Allow changing the ``checker_class`` for the ``StyleGuide``. 1.4.2 (2013-02-10) @@ -284,7 +363,7 @@ Bug fixes: * Register new checkers with ``register_check(func_or_cls, codes)``. -* Allow to construct a ``StyleGuide`` with a custom parser. +* Allow constructing a ``StyleGuide`` with a custom parser. * Accept visual indentation without parenthesis after the ``if`` statement. (Issue #151) @@ -330,7 +409,7 @@ Bug fixes: (Issue #93 and #141) * Add the Sphinx-based documentation, and publish it - on http://pep8.readthedocs.org/. (Issue #105) + on https://pycodestyle.readthedocs.io/. (Issue #105) 1.3.4 (2012-12-18) @@ -493,7 +572,7 @@ Bug fixes: The ``--repeat`` flag becomes obsolete because it is the default behaviour. (Issue #6) -* Allow to specify ``--max-line-length``. (Issue #36) +* Allow specifying ``--max-line-length``. (Issue #36) * Make the shebang more flexible. (Issue #26) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..9771176 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,4 @@ +Contributing to ``pycodestyle`` +=============================== + +Please see the `developer notes <https://pycodestyle.readthedocs.io/en/latest/developer.html>`_ @@ -1,5 +1,6 @@ Copyright © 2006-2009 Johann C. Rocholl <johann@rocholl.net> Copyright © 2009-2014 Florent Xicluna <florent.xicluna@gmail.com> +Copyright © 2014-2016 Ian Lee <IanLee1521@gmail.com> Licensed under the terms of the Expat License @@ -1,11 +1,11 @@ test : - python pep8.py --testsuite testsuite + python pycodestyle.py --testsuite testsuite selftest : - python pep8.py --statistics pep8.py + python pycodestyle.py --statistics pycodestyle.py doctest : - python pep8.py --doctest + python pycodestyle.py --doctest unittest : python -m testsuite.test_all @@ -1,11 +1,16 @@ -pep8 - Python style guide checker -================================= +pycodestyle (formerly called pep8) - Python style guide checker +=============================================================== -pep8 is a tool to check your Python code against some of the style +pycodestyle is a tool to check your Python code against some of the style conventions in `PEP 8`_. .. _PEP 8: http://www.python.org/dev/peps/pep-0008/ +.. note:: + + This package used to be called ``pep8`` but was renamed to ``pycodestyle`` + to reduce confusion. Further discussion `here + <https://github.com/PyCQA/pycodestyle/issues/466>`_. Features -------- @@ -15,18 +20,18 @@ Features * Parseable output: Jump to error location in your editor. * Small: Just one Python file, requires only stdlib. You can use just - the pep8.py file for this purpose. + the ``pycodestyle.py`` file for this purpose. * Comes with a comprehensive test suite. Installation ------------ -You can install, upgrade, uninstall pep8.py with these commands:: +You can install, upgrade, uninstall ``pycodestyle.py`` with these commands:: - $ pip install pep8 - $ pip install --upgrade pep8 - $ pip uninstall pep8 + $ pip install pycodestyle + $ pip install --upgrade pycodestyle + $ pip uninstall pycodestyle There's also a package for Debian/Ubuntu, but it's not always the latest version. @@ -36,7 +41,7 @@ Example usage and output :: - $ pep8 --first optparse.py + $ pycodestyle --first optparse.py optparse.py:69:11: E401 multiple imports on one line optparse.py:77:1: E302 expected 2 blank lines, found 1 optparse.py:88:5: E301 expected 1 blank line, found 0 @@ -46,10 +51,10 @@ Example usage and output optparse.py:472:29: E221 multiple spaces before operator optparse.py:544:21: W601 .has_key() is deprecated, use 'in' -You can also make pep8.py show the source code for each error, and +You can also make ``pycodestyle.py`` show the source code for each error, and even the relevant text from PEP 8:: - $ pep8 --show-source --show-pep8 testsuite/E40.py + $ pycodestyle --show-source --show-pep8 testsuite/E40.py testsuite/E40.py:2:10: E401 multiple imports on one line import os, sys ^ @@ -61,7 +66,7 @@ even the relevant text from PEP 8:: Or you can display how often each error was found:: - $ pep8 --statistics -qq Python-2.5/Lib + $ pycodestyle --statistics -qq Python-2.5/Lib 232 E201 whitespace after '[' 599 E202 whitespace before ')' 631 E203 whitespace before ',' @@ -78,14 +83,14 @@ Or you can display how often each error was found:: Links ----- -.. image:: https://api.travis-ci.org/jcrocholl/pep8.png?branch=master - :target: https://travis-ci.org/jcrocholl/pep8 +.. image:: https://api.travis-ci.org/PyCQA/pycodestyle.png?branch=master + :target: https://travis-ci.org/PyCQA/pycodestyle :alt: Build status -.. image:: https://pypip.in/wheel/pep8/badge.png?branch=master - :target: https://pypi.python.org/pypi/pep8 +.. image:: https://pypip.in/wheel/pycodestyle/badge.png?branch=master + :target: https://pypi.python.org/pypi/pycodestyle :alt: Wheel Status -* `Read the documentation <http://pep8.readthedocs.org/>`_ +* `Read the documentation <https://pycodestyle.readthedocs.io/>`_ -* `Fork me on GitHub <http://github.com/jcrocholl/pep8>`_ +* `Fork me on GitHub <http://github.com/PyCQA/pycodestyle>`_ diff --git a/docs/Makefile b/docs/Makefile index 1952db4..96c920f 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -77,17 +77,17 @@ qthelp: @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pep8.qhcp" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pycodestyle.qhcp" @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pep8.qhc" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pycodestyle.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/pep8" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pep8" + @echo "# mkdir -p $$HOME/.local/share/devhelp/pycodestyle" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pycodestyle" @echo "# devhelp" epub: diff --git a/docs/advanced.rst b/docs/advanced.rst index 2bce2e0..fd3cf3e 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -1,4 +1,4 @@ -.. currentmodule:: pep8 +.. currentmodule:: pycodestyle ============== Advanced usage @@ -8,64 +8,81 @@ Advanced usage Automated tests --------------- -You can also execute `pep8` tests from Python code. For example, this +You can also execute ``pycodestyle`` tests from Python code. For example, this can be highly useful for automated testing of coding style conformance in your project:: import unittest - import pep8 + import pycodestyle class TestCodeFormat(unittest.TestCase): - def test_pep8_conformance(self): - """Test that we conform to PEP8.""" - pep8style = pep8.StyleGuide(quiet=True) - result = pep8style.check_files(['file1.py', 'file2.py']) + def test_conformance(self): + """Test that we conform to PEP-8.""" + style = pycodestyle.StyleGuide(quiet=True) + result = style.check_files(['file1.py', 'file2.py']) self.assertEqual(result.total_errors, 0, "Found code style errors (and warnings).") -If you are using `nosetests` for running tests, remove `quiet=True` +If you are using ``nosetests`` for running tests, remove ``quiet=True`` since Nose suppresses stdout. There's also a shortcut for checking a single file:: - import pep8 + import pycodestyle - fchecker = pep8.Checker('testsuite/E27.py', show_source=True) + fchecker = pycodestyle.Checker('testsuite/E27.py', show_source=True) file_errors = fchecker.check_all() print("Found %s errors (and warnings)" % file_errors) +Configuring tests +----------------- + +You can configure automated ``pycodestyle`` tests in a variety of ways. + +For example, you can pass in a path to a configuration file that ``pycodestyle`` +should use:: + + import pycodestyle + + style = pycodestyle.StyleGuide(config_file='/path/to/tox.ini') + +You can also set specific options explicitly:: + + style = pycodestyle.StyleGuide(ignore=['E501']) + + Skip file header ---------------- Another example is related to the `feature request #143 -<https://github.com/jcrocholl/pep8/issues/143>`_: skip a number of lines +<https://github.com/pycqa/pycodestyle/issues/143>`_: skip a number of lines at the beginning and the end of a file. This use case is easy to implement through a custom wrapper for the PEP 8 library:: #!python - import pep8 + import pycodestyle LINES_SLICE = slice(14, -20) - class PEP8(pep8.StyleGuide): - """This subclass of pep8.StyleGuide will skip the first and last lines + class StyleGuide(pycodestyle.StyleGuide): + """This subclass of pycodestyle.StyleGuide will skip the first and last lines of each file.""" def input_file(self, filename, lines=None, expected=None, line_offset=0): if lines is None: assert line_offset == 0 line_offset = LINES_SLICE.start or 0 - lines = pep8.readlines(filename)[LINES_SLICE] - return super(PEP8, self).input_file( + lines = pycodestyle.readlines(filename)[LINES_SLICE] + return super(StyleGuide, self).input_file( filename, lines=lines, expected=expected, line_offset=line_offset) if __name__ == '__main__': - pep8style = PEP8(parse_argv=True, config_file=True) - report = pep8style.check_files() + style = StyleGuide(parse_argv=True, config_file=True) + report = style.check_files() if report.total_errors: raise SystemExit(1) @@ -74,4 +91,4 @@ and 20 lines at the end. If there's no line to skip at the end, it could be changed with ``LINES_SLICE = slice(14, None)`` for example. You can save it in a file and use it with the same options as the -original ``pep8``. +original ``pycodestyle``. diff --git a/docs/api.rst b/docs/api.rst index b346aba..f9c7066 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,8 +1,8 @@ -======== -pep8 API -======== +=============== +pycodestyle API +=============== -.. module:: pep8 +.. module:: pycodestyle The library provides classes which are usable by third party tools. @@ -84,5 +84,5 @@ Utilities .. autofunction:: stdin_get_value() .. autofunction:: parse_udiff(diff, patterns=None, parent='.') .. autofunction:: filename_match(filename, patterns, default=True) - .. autofunction:: get_parser(prog='pep8', version=pep8.__version__) + .. autofunction:: get_parser(prog='pycodestyle', version=pycodestyle.__version__) .. autofunction:: init_checks_registry() diff --git a/docs/conf.py b/docs/conf.py index d1dca3c..7935b0b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# pep8 documentation build configuration file, created by +# pycodestyle documentation build configuration file, created by # sphinx-quickstart on Tue Aug 21 09:47:49 2012. # # This file is execfile()d with the current directory set to its @@ -44,20 +44,20 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'pep8' +project = u'pycodestyle' authors = u'Johann C. Rocholl, Florent Xicluna, Ian Lee' -copyright = u'2006-2014, %s' % (authors) +copyright = u'2006-2016, %s' % (authors) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # -pep8_version = __import__('pep8').__version__.split('.') +pkg_version = __import__('pycodestyle').__version__.split('.') # The short X.Y version. -version = '.'.join(pep8_version[:2]) +version = '.'.join(pkg_version[:2]) # The full version, including alpha/beta/rc tags. -release = '.'.join(pep8_version) +release = '.'.join(pkg_version) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -99,7 +99,11 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -128,7 +132,7 @@ html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +# html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -172,7 +176,7 @@ html_static_path = ['_static'] #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'pep8doc' +htmlhelp_basename = 'pycodestyledoc' # -- Options for LaTeX output ------------------------------------------------- @@ -192,7 +196,7 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto/manual]). latex_documents = [ - ('index', 'pep8.tex', u'pep8 documentation', + ('index', 'pycodestyle.tex', u'pycodestyle documentation', authors, 'manual'), ] @@ -222,7 +226,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pep8', u'pep8 documentation', + ('index', 'pycodestyle', u'pycodestyle documentation', [authors], 1) ] @@ -236,8 +240,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'pep8', u'pep8 documentation', authors, - 'pep8', 'One line description of project.', + ('index', 'pycodestyle', u'pycodestyle documentation', authors, + 'pycodestyle', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/developer.rst b/docs/developer.rst index 4725acd..3acf2a6 100644 --- a/docs/developer.rst +++ b/docs/developer.rst @@ -1,4 +1,4 @@ -.. currentmodule:: pep8 +.. currentmodule:: pycodestyle ================= Developer's notes @@ -11,13 +11,28 @@ Source code The source code is currently `available on GitHub`_ under the terms and conditions of the :ref:`Expat license <license>`. Fork away! -* `Source code <https://github.com/jcrocholl/pep8>`_ and - `issue tracker <https://github.com/jcrocholl/pep8/issues>`_ on GitHub. -* `Continuous tests <http://travis-ci.org/jcrocholl/pep8>`_ against Python +* `Source code <https://github.com/pycqa/pycodestyle>`_ and + `issue tracker <https://github.com/pycqa/pycodestyle/issues>`_ on GitHub. +* `Continuous tests <http://travis-ci.org/pycqa/pycodestyle>`_ against Python 2.6 through 3.4 and PyPy, on `Travis-CI platform <http://about.travis-ci.org/>`_. -.. _available on GitHub: https://github.com/jcrocholl/pep8 +.. _available on GitHub: https://github.com/pycqa/pycodestyle + + +Direction +~~~~~~~~~ + +Some high-level aims and directions to bear in mind for contributions: + +* ``pycodestyle`` is intended to be as fast as possible. + Using the ``ast`` module defeats that purpose. + The `pep8-naming <https://github.com/flintwork/pep8-naming>`_ plugin exists for this sort of functionality. +* If you want to provide extensibility / plugins, + please see `flake8 <https://gitlab.com/pycqa/flake8>`_ - + ``pycodestyle`` doesn't want or need a plugin architecture. +* Python 2.6 support is still deemed important. +* ``pycodestyle`` aims to have no external dependencies. Contribute @@ -74,19 +89,22 @@ Several docstrings contain examples directly from the `PEP 8`_ document. Okay: spam(ham[1], {eggs: 2}) E201: spam( ham[1], {eggs: 2}) -These examples are verified automatically when pep8.py is run with the -``--doctest`` option. You can add examples for your own check functions. -The format is simple: ``"Okay"`` or error/warning code followed by colon -and space, the rest of the line is example source code. If you put ``'r'`` -before the docstring, you can use ``\n`` for newline and ``\t`` for tab. +These examples are verified automatically when ``pycodestyle.py`` is run with +the ``--doctest`` option. You can add examples for your own check functions. +The format is simple: ``"Okay"`` or error/warning code followed by colon and +space, the rest of the line is example source code. If you put ``'r'`` before +the docstring, you can use ``\n`` for newline and ``\t`` for tab. Then be sure to pass the tests:: - $ python pep8.py --testsuite testsuite - $ python pep8.py --doctest - $ python pep8.py --verbose pep8.py + $ python pycodestyle.py --testsuite testsuite + $ python pycodestyle.py --doctest + $ python pycodestyle.py --verbose pycodestyle.py + +When contributing to pycodestyle, please observe our `Code of Conduct`_. .. _PEP 8: http://www.python.org/dev/peps/pep-0008/ +.. _Code of Conduct: http://meta.pycqa.org/en/latest/code-of-conduct.html Changes diff --git a/docs/index.rst b/docs/index.rst index 5500e0d..0764e9f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,12 +1,12 @@ -.. pep8 documentation master file +.. pycodestyle documentation master file -pep8's documentation -==================== +pycodestyle's documentation +=========================== *Python style guide checker* -pep8 is a tool to check your Python code against some of the style -conventions in `PEP 8`_. +pycodestyle (formerly pep8) is a tool to check your Python code against some of +the style conventions in `PEP 8`_. .. _PEP 8: http://www.python.org/dev/peps/pep-0008/ @@ -21,8 +21,8 @@ Contents: API <api> developer -* Online documentation: http://pep8.readthedocs.org/ -* Source code and issue tracker: https://github.com/jcrocholl/pep8 +* Online documentation: https://pycodestyle.readthedocs.io/ +* Source code and issue tracker: https://github.com/pycqa/pycodestyle Indices and tables @@ -45,7 +45,7 @@ Maintained by Florent Xicluna and Ian Lee. License ======= -The ``pep8`` library is provided under the terms and conditions of the +The ``pycodestyle`` library is provided under the terms and conditions of the Expat license:: # Permission is hereby granted, free of charge, to any person diff --git a/docs/intro.rst b/docs/intro.rst index 1bcafe8..12f67d7 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -1,9 +1,9 @@ -.. currentmodule:: pep8 +.. currentmodule:: pycodestyle Introduction ============ -pep8 is a tool to check your Python code against some of the style +pycodestyle is a tool to check your Python code against some of the style conventions in `PEP 8`_. .. contents:: @@ -18,7 +18,7 @@ Features * Parseable output: Jump to error location in your editor. * Small: Just one Python file, requires only stdlib. You can use just - the pep8.py file for this purpose. + the ``pycodestyle.py`` file for this purpose. * Comes with a comprehensive test suite. @@ -40,14 +40,14 @@ Always remember this statement from `PEP 8`_: Among other things, these features are currently not in the scope of -the ``pep8`` library: +the ``pycodestyle`` library: * **naming conventions**: this kind of feature is supported through plugins. Install `flake8 <https://pypi.python.org/pypi/flake8>`_ and the `pep8-naming extension <https://pypi.python.org/pypi/pep8-naming>`_ to use this feature. * **docstring conventions**: they are not in the scope of this library; - see the `pep257 project <https://github.com/GreenSteam/pep257>`_. + see the `pydocstyle project <https://github.com/PyCQA/pydocstyle>`_. * **automatic fixing**: see the section *PEP8 Fixers* in the :ref:`related tools <related-tools>` page. @@ -55,16 +55,11 @@ the ``pep8`` library: Installation ------------ -You can install, upgrade, uninstall pep8.py with these commands:: +You can install, upgrade, uninstall ``pycodestyle.py`` with these commands:: - $ pip install pep8 - $ pip install --upgrade pep8 - $ pip uninstall pep8 - -There's also a package for Debian/Ubuntu, but it's not always the -latest version:: - - $ sudo apt-get install pep8 + $ pip install pycodestyle + $ pip install --upgrade pycodestyle + $ pip uninstall pycodestyle Example usage and output @@ -72,7 +67,7 @@ Example usage and output :: - $ pep8 --first optparse.py + $ pycodestyle --first optparse.py optparse.py:69:11: E401 multiple imports on one line optparse.py:77:1: E302 expected 2 blank lines, found 1 optparse.py:88:5: E301 expected 1 blank line, found 0 @@ -82,10 +77,10 @@ Example usage and output optparse.py:472:29: E221 multiple spaces before operator optparse.py:544:21: W601 .has_key() is deprecated, use 'in' -You can also make pep8.py show the source code for each error, and +You can also make ``pycodestyle.py`` show the source code for each error, and even the relevant text from PEP 8:: - $ pep8 --show-source --show-pep8 testsuite/E40.py + $ pycodestyle --show-source --show-pep8 testsuite/E40.py testsuite/E40.py:2:10: E401 multiple imports on one line import os, sys ^ @@ -97,7 +92,7 @@ even the relevant text from PEP 8:: Or you can display how often each error was found:: - $ pep8 --statistics -qq Python-2.5/Lib + $ pycodestyle --statistics -qq Python-2.5/Lib 232 E201 whitespace after '[' 599 E202 whitespace before ')' 631 E203 whitespace before ',' @@ -111,15 +106,16 @@ Or you can display how often each error was found:: 612 W601 .has_key() is deprecated, use 'in' 1188 W602 deprecated form of raising exception -You can also make pep8.py show the error text in different formats by using --format having options default/pylint/custom:: +You can also make ``pycodestyle.py`` show the error text in different formats by +using ``--format`` having options default/pylint/custom:: - $ pep8 testsuite/E40.py --format=default + $ pycodestyle testsuite/E40.py --format=default testsuite/E40.py:2:10: E401 multiple imports on one line - $ pep8 testsuite/E40.py --format=pylint + $ pycodestyle testsuite/E40.py --format=pylint testsuite/E40.py:2: [E401] multiple imports on one line - $ pep8 testsuite/E40.py --format='%(path)s|%(row)d|%(col)d| %(code)s %(text)s' + $ pycodestyle testsuite/E40.py --format='%(path)s|%(row)d|%(col)d| %(code)s %(text)s' testsuite/E40.py|2|10| E401 multiple imports on one line Variables in the ``custom`` format option @@ -140,8 +136,8 @@ Variables in the ``custom`` format option Quick help is available on the command line:: - $ pep8 -h - Usage: pep8 [options] input ... + $ pycodestyle -h + Usage: pycodestyle [options] input ... Options: --version show program's version number and exit @@ -183,24 +179,28 @@ Quick help is available on the command line:: Configuration ------------- -The behaviour may be configured at two levels. +The behaviour may be configured at two levels, the user and project levels. + +At the user level, settings are read from the following locations: + +If on Windows: + ``~\.pep8`` + +Otherwise, if the :envvar:`XDG_CONFIG_HOME` environment variable is defined: + ``XDG_CONFIG_HOME/pep8`` + +Else if :envvar:`XDG_CONFIG_HOME` is not defined: + ``~/.config/pep8`` -The user settings are read from the ``~/.config/pep8`` file and -for Windows from the ``~\.pep8`` file. Example:: [pep8] ignore = E226,E302,E41 max-line-length = 160 -At the project level, a ``tox.ini`` file or a ``setup.cfg`` file is read if -present (``.pep8`` file is also supported, but it is deprecated). If none of -these files have a ``[pep8]`` section, no project specific configuration is -loaded. - -If the ``ignore`` option is not in the configuration and not in the arguments, -only the error codes ``E123/E133``, ``E226`` and ``E241/E242`` are ignored -(see below). +At the project level, a ``setup.cfg`` file or a ``tox.ini`` file is read if +present. If none of these files have a ``[pep8]`` section, no project specific +configuration is loaded. Error codes @@ -208,198 +208,205 @@ Error codes This is the current list of error and warning codes: -+----------+----------------------------------------------------------------------+ -| code | sample message | -+==========+======================================================================+ -| **E1** | *Indentation* | -+----------+----------------------------------------------------------------------+ -| E101 | indentation contains mixed spaces and tabs | -+----------+----------------------------------------------------------------------+ -| E111 | indentation is not a multiple of four | -+----------+----------------------------------------------------------------------+ -| E112 | expected an indented block | -+----------+----------------------------------------------------------------------+ -| E113 | unexpected indentation | -+----------+----------------------------------------------------------------------+ -| E114 | indentation is not a multiple of four (comment) | -+----------+----------------------------------------------------------------------+ -| E115 | expected an indented block (comment) | -+----------+----------------------------------------------------------------------+ -| E116 | unexpected indentation (comment) | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E121 (^) | continuation line under-indented for hanging indent | -+----------+----------------------------------------------------------------------+ -| E122 (^) | continuation line missing indentation or outdented | -+----------+----------------------------------------------------------------------+ -| E123 (*) | closing bracket does not match indentation of opening bracket's line | -+----------+----------------------------------------------------------------------+ -| E124 (^) | closing bracket does not match visual indentation | -+----------+----------------------------------------------------------------------+ -| E125 (^) | continuation line with same indent as next logical line | -+----------+----------------------------------------------------------------------+ -| E126 (^) | continuation line over-indented for hanging indent | -+----------+----------------------------------------------------------------------+ -| E127 (^) | continuation line over-indented for visual indent | -+----------+----------------------------------------------------------------------+ -| E128 (^) | continuation line under-indented for visual indent | -+----------+----------------------------------------------------------------------+ -| E129 (^) | visually indented line with same indent as next logical line | -+----------+----------------------------------------------------------------------+ -| E131 (^) | continuation line unaligned for hanging indent | -+----------+----------------------------------------------------------------------+ -| E133 (*) | closing bracket is missing indentation | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **E2** | *Whitespace* | -+----------+----------------------------------------------------------------------+ -| E201 | whitespace after '(' | -+----------+----------------------------------------------------------------------+ -| E202 | whitespace before ')' | -+----------+----------------------------------------------------------------------+ -| E203 | whitespace before ':' | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E211 | whitespace before '(' | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E221 | multiple spaces before operator | -+----------+----------------------------------------------------------------------+ -| E222 | multiple spaces after operator | -+----------+----------------------------------------------------------------------+ -| E223 | tab before operator | -+----------+----------------------------------------------------------------------+ -| E224 | tab after operator | -+----------+----------------------------------------------------------------------+ -| E225 | missing whitespace around operator | -+----------+----------------------------------------------------------------------+ -| E226 (*) | missing whitespace around arithmetic operator | -+----------+----------------------------------------------------------------------+ -| E227 | missing whitespace around bitwise or shift operator | -+----------+----------------------------------------------------------------------+ -| E228 | missing whitespace around modulo operator | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E231 | missing whitespace after ',' | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E241 (*) | multiple spaces after ',' | -+----------+----------------------------------------------------------------------+ -| E242 (*) | tab after ',' | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E251 | unexpected spaces around keyword / parameter equals | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E261 | at least two spaces before inline comment | -+----------+----------------------------------------------------------------------+ -| E262 | inline comment should start with '# ' | -+----------+----------------------------------------------------------------------+ -| E265 | block comment should start with '# ' | -+----------+----------------------------------------------------------------------+ -| E266 | too many leading '#' for block comment | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| E271 | multiple spaces after keyword | -+----------+----------------------------------------------------------------------+ -| E272 | multiple spaces before keyword | -+----------+----------------------------------------------------------------------+ -| E273 | tab after keyword | -+----------+----------------------------------------------------------------------+ -| E274 | tab before keyword | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **E3** | *Blank line* | -+----------+----------------------------------------------------------------------+ -| E301 | expected 1 blank line, found 0 | -+----------+----------------------------------------------------------------------+ -| E302 | expected 2 blank lines, found 0 | -+----------+----------------------------------------------------------------------+ -| E303 | too many blank lines (3) | -+----------+----------------------------------------------------------------------+ -| E304 | blank lines found after function decorator | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **E4** | *Import* | -+----------+----------------------------------------------------------------------+ -| E401 | multiple imports on one line | -+----------+----------------------------------------------------------------------+ -| E402 | module level import not at top of file | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **E5** | *Line length* | -+----------+----------------------------------------------------------------------+ -| E501 (^) | line too long (82 > 79 characters) | -+----------+----------------------------------------------------------------------+ -| E502 | the backslash is redundant between brackets | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **E7** | *Statement* | -+----------+----------------------------------------------------------------------+ -| E701 | multiple statements on one line (colon) | -+----------+----------------------------------------------------------------------+ -| E702 | multiple statements on one line (semicolon) | -+----------+----------------------------------------------------------------------+ -| E703 | statement ends with a semicolon | -+----------+----------------------------------------------------------------------+ -| E704 (*) | multiple statements on one line (def) | -+----------+----------------------------------------------------------------------+ -| E711 (^) | comparison to None should be 'if cond is None:' | -+----------+----------------------------------------------------------------------+ -| E712 (^) | comparison to True should be 'if cond is True:' or 'if cond:' | -+----------+----------------------------------------------------------------------+ -| E713 | test for membership should be 'not in' | -+----------+----------------------------------------------------------------------+ -| E714 | test for object identity should be 'is not' | -+----------+----------------------------------------------------------------------+ -| E721 | do not compare types, use 'isinstance()' | -+----------+----------------------------------------------------------------------+ -| E731 | do not assign a lambda expression, use a def | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **E9** | *Runtime* | -+----------+----------------------------------------------------------------------+ -| E901 | SyntaxError or IndentationError | -+----------+----------------------------------------------------------------------+ -| E902 | IOError | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **W1** | *Indentation warning* | -+----------+----------------------------------------------------------------------+ -| W191 | indentation contains tabs | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **W2** | *Whitespace warning* | -+----------+----------------------------------------------------------------------+ -| W291 | trailing whitespace | -+----------+----------------------------------------------------------------------+ -| W292 | no newline at end of file | -+----------+----------------------------------------------------------------------+ -| W293 | blank line contains whitespace | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **W3** | *Blank line warning* | -+----------+----------------------------------------------------------------------+ -| W391 | blank line at end of file | -+----------+----------------------------------------------------------------------+ -+----------+----------------------------------------------------------------------+ -| **W6** | *Deprecation warning* | -+----------+----------------------------------------------------------------------+ -| W601 | .has_key() is deprecated, use 'in' | -+----------+----------------------------------------------------------------------+ -| W602 | deprecated form of raising exception | -+----------+----------------------------------------------------------------------+ -| W603 | '<>' is deprecated, use '!=' | -+----------+----------------------------------------------------------------------+ -| W604 | backticks are deprecated, use 'repr()' | -+----------+----------------------------------------------------------------------+ - - -**(*)** In the default configuration, the checks **E123**, **E133**, **E226**, -**E241**, **E242** and **E704** are ignored because they are not rules unanimously -accepted, and `PEP 8`_ does not enforce them. The check **E133** is mutually -exclusive with check **E123**. Use switch ``--hang-closing`` to report **E133** -instead of **E123**. ++------------+----------------------------------------------------------------------+ +| code | sample message | ++============+======================================================================+ +| **E1** | *Indentation* | ++------------+----------------------------------------------------------------------+ +| E101 | indentation contains mixed spaces and tabs | ++------------+----------------------------------------------------------------------+ +| E111 | indentation is not a multiple of four | ++------------+----------------------------------------------------------------------+ +| E112 | expected an indented block | ++------------+----------------------------------------------------------------------+ +| E113 | unexpected indentation | ++------------+----------------------------------------------------------------------+ +| E114 | indentation is not a multiple of four (comment) | ++------------+----------------------------------------------------------------------+ +| E115 | expected an indented block (comment) | ++------------+----------------------------------------------------------------------+ +| E116 | unexpected indentation (comment) | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E121 (\*^) | continuation line under-indented for hanging indent | ++------------+----------------------------------------------------------------------+ +| E122 (^) | continuation line missing indentation or outdented | ++------------+----------------------------------------------------------------------+ +| E123 (*) | closing bracket does not match indentation of opening bracket's line | ++------------+----------------------------------------------------------------------+ +| E124 (^) | closing bracket does not match visual indentation | ++------------+----------------------------------------------------------------------+ +| E125 (^) | continuation line with same indent as next logical line | ++------------+----------------------------------------------------------------------+ +| E126 (\*^) | continuation line over-indented for hanging indent | ++------------+----------------------------------------------------------------------+ +| E127 (^) | continuation line over-indented for visual indent | ++------------+----------------------------------------------------------------------+ +| E128 (^) | continuation line under-indented for visual indent | ++------------+----------------------------------------------------------------------+ +| E129 (^) | visually indented line with same indent as next logical line | ++------------+----------------------------------------------------------------------+ +| E131 (^) | continuation line unaligned for hanging indent | ++------------+----------------------------------------------------------------------+ +| E133 (*) | closing bracket is missing indentation | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **E2** | *Whitespace* | ++------------+----------------------------------------------------------------------+ +| E201 | whitespace after '(' | ++------------+----------------------------------------------------------------------+ +| E202 | whitespace before ')' | ++------------+----------------------------------------------------------------------+ +| E203 | whitespace before ':' | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E211 | whitespace before '(' | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E221 | multiple spaces before operator | ++------------+----------------------------------------------------------------------+ +| E222 | multiple spaces after operator | ++------------+----------------------------------------------------------------------+ +| E223 | tab before operator | ++------------+----------------------------------------------------------------------+ +| E224 | tab after operator | ++------------+----------------------------------------------------------------------+ +| E225 | missing whitespace around operator | ++------------+----------------------------------------------------------------------+ +| E226 (*) | missing whitespace around arithmetic operator | ++------------+----------------------------------------------------------------------+ +| E227 | missing whitespace around bitwise or shift operator | ++------------+----------------------------------------------------------------------+ +| E228 | missing whitespace around modulo operator | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E231 | missing whitespace after ',', ';', or ':' | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E241 (*) | multiple spaces after ',' | ++------------+----------------------------------------------------------------------+ +| E242 (*) | tab after ',' | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E251 | unexpected spaces around keyword / parameter equals | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E261 | at least two spaces before inline comment | ++------------+----------------------------------------------------------------------+ +| E262 | inline comment should start with '# ' | ++------------+----------------------------------------------------------------------+ +| E265 | block comment should start with '# ' | ++------------+----------------------------------------------------------------------+ +| E266 | too many leading '#' for block comment | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| E271 | multiple spaces after keyword | ++------------+----------------------------------------------------------------------+ +| E272 | multiple spaces before keyword | ++------------+----------------------------------------------------------------------+ +| E273 | tab after keyword | ++------------+----------------------------------------------------------------------+ +| E274 | tab before keyword | ++------------+----------------------------------------------------------------------+ +| E275 | missing whitespace after keyword | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **E3** | *Blank line* | ++------------+----------------------------------------------------------------------+ +| E301 | expected 1 blank line, found 0 | ++------------+----------------------------------------------------------------------+ +| E302 | expected 2 blank lines, found 0 | ++------------+----------------------------------------------------------------------+ +| E303 | too many blank lines (3) | ++------------+----------------------------------------------------------------------+ +| E304 | blank lines found after function decorator | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **E4** | *Import* | ++------------+----------------------------------------------------------------------+ +| E401 | multiple imports on one line | ++------------+----------------------------------------------------------------------+ +| E402 | module level import not at top of file | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **E5** | *Line length* | ++------------+----------------------------------------------------------------------+ +| E501 (^) | line too long (82 > 79 characters) | ++------------+----------------------------------------------------------------------+ +| E502 | the backslash is redundant between brackets | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **E7** | *Statement* | ++------------+----------------------------------------------------------------------+ +| E701 | multiple statements on one line (colon) | ++------------+----------------------------------------------------------------------+ +| E702 | multiple statements on one line (semicolon) | ++------------+----------------------------------------------------------------------+ +| E703 | statement ends with a semicolon | ++------------+----------------------------------------------------------------------+ +| E704 (*) | multiple statements on one line (def) | ++------------+----------------------------------------------------------------------+ +| E711 (^) | comparison to None should be 'if cond is None:' | ++------------+----------------------------------------------------------------------+ +| E712 (^) | comparison to True should be 'if cond is True:' or 'if cond:' | ++------------+----------------------------------------------------------------------+ +| E713 | test for membership should be 'not in' | ++------------+----------------------------------------------------------------------+ +| E714 | test for object identity should be 'is not' | ++------------+----------------------------------------------------------------------+ +| E721 (^) | do not compare types, use 'isinstance()' | ++------------+----------------------------------------------------------------------+ +| E731 | do not assign a lambda expression, use a def | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **E9** | *Runtime* | ++------------+----------------------------------------------------------------------+ +| E901 | SyntaxError or IndentationError | ++------------+----------------------------------------------------------------------+ +| E902 | IOError | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **W1** | *Indentation warning* | ++------------+----------------------------------------------------------------------+ +| W191 | indentation contains tabs | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **W2** | *Whitespace warning* | ++------------+----------------------------------------------------------------------+ +| W291 | trailing whitespace | ++------------+----------------------------------------------------------------------+ +| W292 | no newline at end of file | ++------------+----------------------------------------------------------------------+ +| W293 | blank line contains whitespace | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **W3** | *Blank line warning* | ++------------+----------------------------------------------------------------------+ +| W391 | blank line at end of file | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **W5** | *Line break warning* | ++------------+----------------------------------------------------------------------+ +| W503 (*) | line break occurred before a binary operator | ++------------+----------------------------------------------------------------------+ ++------------+----------------------------------------------------------------------+ +| **W6** | *Deprecation warning* | ++------------+----------------------------------------------------------------------+ +| W601 | .has_key() is deprecated, use 'in' | ++------------+----------------------------------------------------------------------+ +| W602 | deprecated form of raising exception | ++------------+----------------------------------------------------------------------+ +| W603 | '<>' is deprecated, use '!=' | ++------------+----------------------------------------------------------------------+ +| W604 | backticks are deprecated, use 'repr()' | ++------------+----------------------------------------------------------------------+ + + +**(*)** In the default configuration, the checks **E121**, **E123**, **E126**, +**E133**, **E226**, **E241**, **E242**, **E704** and **W503** are ignored because +they are not rules unanimously accepted, and `PEP 8`_ does not enforce them. The +check **E133** is mutually exclusive with check **E123**. Use switch ``--hang- +closing`` to report **E133** instead of **E123**. **(^)** These checks can be disabled at the line level using the ``# noqa`` special comment. This possibility should be reserved for special cases. @@ -409,7 +416,7 @@ special comment. This possibility should be reserved for special cases. Note: most errors can be listed with such one-liner:: - $ python pep8.py --first --select E,W testsuite/ --format '%(code)s: %(text)s' + $ python pycodestyle.py --first --select E,W testsuite/ --format '%(code)s: %(text)s' .. _related-tools: @@ -417,10 +424,10 @@ Note: most errors can be listed with such one-liner:: Related tools ------------- -The `flake8 checker <https://flake8.readthedocs.org>`_ is a wrapper around -``pep8`` and similar tools. It supports plugins. +The `flake8 checker <https://flake8.readthedocs.io>`_ is a wrapper around +``pycodestyle`` and similar tools. It supports plugins. -Other tools which use ``pep8`` are referenced in the Wiki: `list of related tools -<https://github.com/jcrocholl/pep8/wiki/RelatedTools>`_. +Other tools which use ``pycodestyle`` are referenced in the Wiki: `list of related +tools <https://github.com/pycqa/pycodestyle/wiki/RelatedTools>`_. .. _PEP 8: http://www.python.org/dev/peps/pep-0008/ diff --git a/docs/make.bat b/docs/make.bat index efa0e94..1ecae62 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -99,9 +99,9 @@ if "%1" == "qthelp" ( echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pep8.qhcp + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pycodestyle.qhcp echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pep8.ghc + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pycodestyle.ghc goto end ) @@ -1,8 +1,9 @@ #!/usr/bin/env python -# pep8.py - Check Python source code formatting, according to PEP 8 +# pycodestyle.py - Check Python source code formatting, according to PEP 8 +# # Copyright (C) 2006-2009 Johann C. Rocholl <johann@rocholl.net> # Copyright (C) 2009-2014 Florent Xicluna <florent.xicluna@gmail.com> -# Copyright (C) 2014 Ian Lee <ianlee1521@gmail.com> +# Copyright (C) 2014-2016 Ian Lee <ianlee1521@gmail.com> # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files @@ -28,10 +29,10 @@ r""" Check Python source code formatting, according to PEP 8. For usage and a list of options, try this: -$ python pep8.py -h +$ python pycodestyle.py -h This program and its regression test suite live here: -http://github.com/jcrocholl/pep8 +https://github.com/pycqa/pycodestyle Groups of errors and warnings: E errors @@ -47,8 +48,6 @@ W warnings """ from __future__ import with_statement -__version__ = '1.6.0a0' - import os import sys import re @@ -56,6 +55,7 @@ import time import inspect import keyword import tokenize +import warnings from optparse import OptionParser from fnmatch import fnmatch try: @@ -64,18 +64,22 @@ try: except ImportError: from ConfigParser import RawConfigParser +__version__ = '2.0.0' + DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' -DEFAULT_IGNORE = 'E123,E226,E24,E704' +DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503' try: if sys.platform == 'win32': - DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8') + USER_CONFIG = os.path.expanduser(r'~\.pep8') else: - DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or - os.path.expanduser('~/.config'), 'pep8') + USER_CONFIG = os.path.join( + os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'), + 'pep8' + ) except ImportError: - DEFAULT_CONFIG = None + USER_CONFIG = None -PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8') +PROJECT_CONFIG = ('setup.cfg', 'tox.ini') TESTSUITE_PATH = os.path.join(os.path.dirname(__file__), 'testsuite') MAX_LINE_LENGTH = 79 REPORT_FORMAT = { @@ -106,7 +110,7 @@ ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b') DOCSTRING_REGEX = re.compile(r'u?r?["\']') EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]') WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)') -COMPARE_SINGLETON_REGEX = re.compile(r'\b(None|False|True)?\s*([=!]=)' +COMPARE_SINGLETON_REGEX = re.compile(r'(\bNone|\bFalse|\bTrue)?\s*([=!]=)' r'\s*(?(1)|(None|False|True))\b') COMPARE_NEGATIVE_REGEX = re.compile(r'\b(not)\s+[^][)(}{ ]+\s+(in|is)\s') COMPARE_TYPE_REGEX = re.compile(r'(?:[=!]=|is(?:\s+not)?)\s*type(?:s.\w+Type' @@ -323,6 +327,23 @@ def whitespace_around_keywords(logical_line): yield match.start(2), "E271 multiple spaces after keyword" +def missing_whitespace_after_import_keyword(logical_line): + r"""Multiple imports in form from x import (a, b, c) should have space + between import statement and parenthesised name list. + + Okay: from foo import (bar, baz) + E275: from foo import(bar, baz) + E275: from importable.module import(bar, baz) + """ + line = logical_line + indicator = ' import(' + if line.startswith('from '): + found = line.find(indicator) + if -1 < found: + pos = found + len(indicator) - 1 + yield pos, "E275 missing whitespace after keyword" + + def missing_whitespace(logical_line): r"""Each comma, semicolon or colon should be followed by whitespace. @@ -433,6 +454,7 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing, indent_chances = {} last_indent = tokens[0][2] visual_indent = None + last_token_multiline = False # for each depth, memorize the visual indent column indent = [last_indent[1]] if verbose >= 3: @@ -512,8 +534,9 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing, yield start, "%s continuation line %s" % error # look for visual indenting - if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT) - and not indent[depth]): + if (parens[row] and + token_type not in (tokenize.NL, tokenize.COMMENT) and + not indent[depth]): indent[depth] = start[1] indent_chances[start[1]] = True if verbose >= 4: @@ -561,7 +584,7 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing, break assert len(indent) == depth + 1 if start[1] not in indent_chances: - # allow to line up tokens + # allow lining up tokens indent_chances[start[1]] = text last_token_multiline = (start[0] != end[0]) @@ -754,6 +777,8 @@ def whitespace_around_named_parameter_equals(logical_line, tokens): Okay: boolean(a != b) Okay: boolean(a <= b) Okay: boolean(a >= b) + Okay: def foo(arg: int = 42): + Okay: async def foo(arg: int = 42): E251: def complex(real, imag = 0.0): E251: return magic(r = real, i = imag) @@ -761,6 +786,8 @@ def whitespace_around_named_parameter_equals(logical_line, tokens): parens = 0 no_space = False prev_end = None + annotated_func_arg = False + in_def = logical_line.startswith(('def', 'async def')) message = "E251 unexpected spaces around keyword / parameter equals" for token_type, text, start, end, line in tokens: if token_type == tokenize.NL: @@ -770,14 +797,21 @@ def whitespace_around_named_parameter_equals(logical_line, tokens): if start != prev_end: yield (prev_end, message) if token_type == tokenize.OP: - if text == '(': + if text in '([': parens += 1 - elif text == ')': + elif text in ')]': parens -= 1 - elif parens and text == '=': + elif in_def and text == ':' and parens == 1: + annotated_func_arg = True + elif parens and text == ',' and parens == 1: + annotated_func_arg = False + elif parens and text == '=' and not annotated_func_arg: no_space = True if start != prev_end: yield (prev_end, message) + if not parens: + annotated_func_arg = False + prev_end = end @@ -823,7 +857,7 @@ def whitespace_before_comment(logical_line, tokens): def imports_on_separate_lines(logical_line): - r"""Imports should usually be on separate lines. + r"""Place imports on separate lines. Okay: import os\nimport sys E401: import sys, os @@ -843,14 +877,17 @@ def imports_on_separate_lines(logical_line): def module_imports_on_top_of_file( logical_line, indent_level, checker_state, noqa): - r"""Imports are always put at the top of the file, just after any module - comments and docstrings, and before module globals and constants. + r"""Place imports at the top of the file. + + Always put imports at the top of the file, just after any module comments + and docstrings, and before module globals and constants. Okay: import os Okay: # this is a comment\nimport os Okay: '''this is a module docstring'''\nimport os Okay: r'''this is a module docstring'''\nimport os - Okay: __version__ = "123"\nimport os + Okay: try:\n import x\nexcept:\n pass\nelse:\n pass\nimport y + Okay: try:\n import x\nexcept:\n pass\nfinally:\n pass\nimport y E402: a=1\nimport os E402: 'One string'\n"Two string"\nimport os E402: a=1\nfrom sys import x @@ -864,6 +901,8 @@ def module_imports_on_top_of_file( line = line[1:] return line and (line[0] == '"' or line[0] == "'") + allowed_try_keywords = ('try', 'except', 'else', 'finally') + if indent_level: # Allow imports in conditional statements or functions return if not logical_line: # Allow empty lines or comments @@ -873,10 +912,10 @@ def module_imports_on_top_of_file( line = logical_line if line.startswith('import ') or line.startswith('from '): if checker_state.get('seen_non_imports', False): - yield 0, "E402 import not at top of file" - elif line.startswith('__version__ '): - # These lines should be included after the module's docstring, before - # any other code, separated by a blank line above and below. + yield 0, "E402 module level import not at top of file" + elif any(line.startswith(kw) for kw in allowed_try_keywords): + # Allow try, except, else, finally keywords intermixed with imports in + # order to support conditional importing return elif is_string_literal(line): # The first literal is a docstring, allow it. Otherwise, report error. @@ -958,10 +997,15 @@ def explicit_line_join(logical_line, tokens): Okay: aaa = [123,\n 123] Okay: aaa = ("bbb "\n "ccc") Okay: aaa = "bbb " \\n "ccc" + Okay: aaa = 123 # \\ """ prev_start = prev_end = parens = 0 + comment = False + backslash = None for token_type, text, start, end, line in tokens: - if start[0] != prev_start and parens and backslash: + if token_type == tokenize.COMMENT: + comment = True + if start[0] != prev_start and parens and backslash and not comment: yield backslash, "E502 the backslash is redundant between brackets" if end[0] != prev_end: if line.rstrip('\r\n').endswith('\\'): @@ -978,6 +1022,55 @@ def explicit_line_join(logical_line, tokens): parens -= 1 +def break_around_binary_operator(logical_line, tokens): + r""" + Avoid breaks before binary operators. + + The preferred place to break around a binary operator is after the + operator, not before it. + + W503: (width == 0\n + height == 0) + W503: (width == 0\n and height == 0) + + Okay: (width == 0 +\n height == 0) + Okay: foo(\n -x) + Okay: foo(x\n []) + Okay: x = '''\n''' + '' + Okay: foo(x,\n -y) + Okay: foo(x, # comment\n -y) + Okay: var = (1 &\n ~2) + Okay: var = (1 /\n -2) + Okay: var = (1 +\n -1 +\n -2) + """ + def is_binary_operator(token_type, text): + # The % character is strictly speaking a binary operator, but the + # common usage seems to be to put it next to the format parameters, + # after a line break. + return ((token_type == tokenize.OP or text in ['and', 'or']) and + text not in "()[]{},:.;@=%~") + + line_break = False + unary_context = True + # Previous non-newline token types and text + previous_token_type = None + previous_text = None + for token_type, text, start, end, line in tokens: + if token_type == tokenize.COMMENT: + continue + if ('\n' in text or '\r' in text) and token_type != tokenize.STRING: + line_break = True + else: + if (is_binary_operator(token_type, text) and line_break and + not unary_context and + not is_binary_operator(previous_token_type, + previous_text)): + yield start, "W503 line break before binary operator" + unary_context = text in '([{,;' + line_break = False + previous_token_type = token_type + previous_text = text + + def comparison_to_singleton(logical_line, noqa): r"""Comparison to singletons should use "is" or "is not". @@ -1033,7 +1126,7 @@ def comparison_negative(logical_line): yield pos, "E714 test for object identity should be 'is not'" -def comparison_type(logical_line): +def comparison_type(logical_line, noqa): r"""Object type comparisons should always use isinstance(). Do not compare types directly. @@ -1049,7 +1142,7 @@ def comparison_type(logical_line): Okay: if type(a1) is type(b1): """ match = COMPARE_TYPE_REGEX.search(logical_line) - if match: + if match and not noqa: inst = match.group(1) if inst and isidentifier(inst) and inst not in SINGLETONS: return # Allow comparison for types which are not obvious @@ -1094,7 +1187,7 @@ def python_3000_not_equal(logical_line): def python_3000_backticks(logical_line): - r"""Backticks are removed in Python 3: use repr() instead. + r"""Use repr() instead of backticks in Python 3. Okay: val = repr(1 + 2) W604: val = `1 + 2` @@ -1109,7 +1202,7 @@ def python_3000_backticks(logical_line): ############################################################################## -if '' == ''.encode(): +if sys.version_info < (3,): # Python 2: implicit encoding. def readlines(filename): """Read the source code.""" @@ -1133,7 +1226,9 @@ else: isidentifier = str.isidentifier def stdin_get_value(): + """Read the value from stdin.""" return TextIOWrapper(sys.stdin.buffer, errors='ignore').read() + noqa = re.compile(r'# no(?:qa|pep8)\b', re.I).search @@ -1245,15 +1340,15 @@ def update_counts(s, counts): counts[char] += 1 -if COMMENT_WITH_NL: - def _is_eol_token(token): - return (token[0] in NEWLINE or - (token[0] == tokenize.COMMENT and token[1] == token[4])) -else: - def _is_eol_token(token): - return token[0] in NEWLINE +def _is_eol_token(token): + return token[0] in NEWLINE or token[4][token[3][1]:].lstrip() == '\\\n' +if COMMENT_WITH_NL: + def _is_eol_token(token, _eol_token=_is_eol_token): + return _eol_token(token) or (token[0] == tokenize.COMMENT and + token[1] == token[4]) + ############################################################################## # Framework to run all checks ############################################################################## @@ -1262,6 +1357,16 @@ else: _checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}} +def _get_parameters(function): + if sys.version_info >= (3, 3): + return [parameter.name + for parameter + in inspect.signature(function).parameters.values() + if parameter.kind == parameter.POSITIONAL_OR_KEYWORD] + else: + return inspect.getargspec(function)[0] + + def register_check(check, codes=None): """Register a new check object.""" def _add_check(check, kind, codes, args): @@ -1270,13 +1375,13 @@ def register_check(check, codes=None): else: _checks[kind][check] = (codes or [''], args) if inspect.isfunction(check): - args = inspect.getargspec(check)[0] + args = _get_parameters(check) if args and args[0] in ('physical_line', 'logical_line'): if codes is None: codes = ERRORCODE_REGEX.findall(check.__doc__ or '') _add_check(check, args[0], codes, args) elif inspect.isclass(check): - if inspect.getargspec(check.__init__)[0][:2] == ['self', 'tree']: + if _get_parameters(check.__init__)[:2] == ['self', 'tree']: _add_check(check, 'tree', codes, None) @@ -1367,7 +1472,7 @@ class Checker(object): return check(*arguments) def init_checker_state(self, name, argument_names): - """ Prepares a custom state for the specific checker plugin.""" + """Prepare custom state for the specific checker plugin.""" if 'checker_state' in argument_names: self.checker_state = self._checker_states.setdefault(name, {}) @@ -1403,8 +1508,8 @@ class Checker(object): (start_row, start_col) = start if prev_row != start_row: # different row prev_text = self.lines[prev_row - 1][prev_col - 1] - if prev_text == ',' or (prev_text not in '{[(' - and text not in '}])'): + if prev_text == ',' or (prev_text not in '{[(' and + text not in '}])'): text = ' ' + text elif prev_col != start_col: # different column text = line[prev_col:start_col] + text @@ -1452,7 +1557,7 @@ class Checker(object): """Build the file's AST and run all AST checks.""" try: tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST) - except (SyntaxError, TypeError): + except (ValueError, SyntaxError, TypeError): return self.report_invalid_syntax() for name, cls, __ in self._ast_checks: checker = cls(tree, self.filename) @@ -1649,6 +1754,7 @@ class BaseReport(object): class FileReport(BaseReport): """Collect the results of the checks and print only the filenames.""" + print_filename = True @@ -1696,6 +1802,14 @@ class StandardReport(BaseReport): print(re.sub(r'\S', ' ', line[:offset]) + '^') if self._show_pep8 and doc: print(' ' + doc.strip()) + + # 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() return self.file_errors @@ -1719,7 +1833,7 @@ class StyleGuide(object): # build options from the command line self.checker_class = kwargs.pop('checker_class', Checker) parse_argv = kwargs.pop('parse_argv', False) - config_file = kwargs.pop('config_file', None) + config_file = kwargs.pop('config_file', False) parser = kwargs.pop('parser', None) # build options from dict options_dict = dict(*args, **kwargs) @@ -1848,6 +1962,7 @@ class StyleGuide(object): def get_parser(prog='pep8', version=__version__): + """Create the parser for the program.""" parser = OptionParser(prog=prog, version=version, usage="%prog [options] input ...") parser.config_options = [ @@ -1872,7 +1987,8 @@ def get_parser(prog='pep8', version=__version__): parser.add_option('--select', metavar='errors', default='', help="select errors and warnings (e.g. E,W6)") parser.add_option('--ignore', metavar='errors', default='', - help="skip errors and warnings (e.g. E4,W)") + help="skip errors and warnings (e.g. E4,W) " + "(default: %s)" % DEFAULT_IGNORE) parser.add_option('--show-source', action='store_true', help="show source code for each error") parser.add_option('--show-pep8', action='store_true', @@ -1894,8 +2010,8 @@ def get_parser(prog='pep8', version=__version__): parser.add_option('--format', metavar='format', default='default', help="set the error format [default|pylint|<custom>]") parser.add_option('--diff', action='store_true', - help="report only lines changed according to the " - "unified diff received on STDIN") + help="report changes only within line number ranges in " + "the unified diff received on STDIN") group = parser.add_option_group("Testing Options") if os.path.exists(TESTSUITE_PATH): group.add_option('--testsuite', metavar='dir', @@ -1908,25 +2024,40 @@ def get_parser(prog='pep8', version=__version__): def read_config(options, args, arglist, parser): - """Read both user configuration and local configuration.""" + """Read and parse configurations. + + If a config file is specified on the command line with the "--config" + option, then only it is used for configuration. + + Otherwise, the user configuration (~/.config/pep8) and any local + configurations in the current directory or above will be merged together + (in that order) using the read method of ConfigParser. + """ config = RawConfigParser() - user_conf = options.config - if user_conf and os.path.isfile(user_conf): - if options.verbose: - print('user configuration: %s' % user_conf) - config.read(user_conf) + cli_conf = options.config local_dir = os.curdir + + if USER_CONFIG and os.path.isfile(USER_CONFIG): + if options.verbose: + print('user configuration: %s' % USER_CONFIG) + config.read(USER_CONFIG) + parent = tail = args and os.path.abspath(os.path.commonprefix(args)) while tail: - if config.read([os.path.join(parent, fn) for fn in PROJECT_CONFIG]): + if config.read(os.path.join(parent, fn) for fn in PROJECT_CONFIG): local_dir = parent if options.verbose: print('local configuration: in %s' % parent) break (parent, tail) = os.path.split(parent) + if cli_conf and os.path.isfile(cli_conf): + if options.verbose: + print('cli configuration: %s' % cli_conf) + config.read(cli_conf) + pep8_section = parser.prog if config.has_section(pep8_section): option_list = dict([(o.dest, o.type or o.action) @@ -1963,19 +2094,21 @@ def read_config(options, args, arglist, parser): def process_options(arglist=None, parse_argv=False, config_file=None, parser=None): - """Process options passed either via arglist or via command line args.""" + """Process options passed either via arglist or via command line args. + + Passing in the ``config_file`` parameter allows other tools, such as flake8 + to specify their own options to be processed in pep8. + """ if not parser: parser = get_parser() if not parser.has_option('--config'): - if config_file is True: - config_file = DEFAULT_CONFIG group = parser.add_option_group("Configuration", description=( "The project options are read from the [%s] section of the " "tox.ini file or the setup.cfg file located in any parent folder " "of the path(s) being processed. Allowed options are: %s." % (parser.prog, ', '.join(parser.config_options)))) group.add_option('--config', metavar='path', default=config_file, - help="user config file location (default: %default)") + help="user config file location") # Don't read the command line if the module is used as a library. if not arglist and not parse_argv: arglist = [] @@ -1996,10 +2129,10 @@ def process_options(arglist=None, parse_argv=False, config_file=None, options = read_config(options, args, arglist, parser) options.reporter = parse_argv and options.quiet == 1 and FileReport - options.filename = options.filename and options.filename.split(',') + options.filename = _parse_multi_options(options.filename) options.exclude = normalize_paths(options.exclude) - options.select = options.select and options.select.split(',') - options.ignore = options.ignore and options.ignore.split(',') + options.select = _parse_multi_options(options.select) + options.ignore = _parse_multi_options(options.ignore) if options.diff: options.reporter = DiffReport @@ -2010,6 +2143,22 @@ def process_options(arglist=None, parse_argv=False, config_file=None, return options, args +def _parse_multi_options(options, split_token=','): + r"""Split and strip and discard empties. + + Turns the following: + + A, + B, + + into ["A", "B"] + """ + if options: + return [o.strip() for o in options.split(split_token) if o.strip()] + else: + return options + + def _main(): """Parse options and run checks on Python source.""" import signal @@ -2020,23 +2169,29 @@ def _main(): except AttributeError: pass # not supported on Windows - pep8style = StyleGuide(parse_argv=True, config_file=True) - options = pep8style.options + style_guide = StyleGuide(parse_argv=True) + options = style_guide.options + if options.doctest or options.testsuite: from testsuite.support import run_tests - report = run_tests(pep8style) + report = run_tests(style_guide) else: - report = pep8style.check_files() + report = style_guide.check_files() + if options.statistics: report.print_statistics() + if options.benchmark: report.print_benchmark() + if options.testsuite and not options.quiet: report.print_results() + if report.total_errors: if options.count: sys.stderr.write(str(report.total_errors) + '\n') sys.exit(1) + if __name__ == '__main__': _main() @@ -4,7 +4,7 @@ from setuptools import setup def get_version(): - with open('pep8.py') as f: + with open('pycodestyle.py') as f: for line in f: if line.startswith('__version__'): return eval(line.split('=')[-1]) @@ -19,16 +19,18 @@ def get_long_description(): setup( - name='pep8', + name='pycodestyle', version=get_version(), description="Python style guide checker", long_description=get_long_description(), - keywords='pep8', + keywords='pycodestyle, pep8, PEP 8, PEP-8, PEP8', author='Johann C. Rocholl', author_email='johann@rocholl.net', - url='http://pep8.readthedocs.org/', + maintainer='Ian Lee', + maintainer_email='IanLee1521@gmail.com', + url='https://pycodestyle.readthedocs.io/', license='Expat license', - py_modules=['pep8'], + py_modules=['pycodestyle'], namespace_packages=[], include_package_data=True, zip_safe=False, @@ -38,7 +40,7 @@ setup( ], entry_points={ 'console_scripts': [ - 'pep8 = pep8:_main', + 'pycodestyle = pycodestyle:_main', ], }, classifiers=[ diff --git a/testsuite/E12.py b/testsuite/E12.py index 6ebd44e..a995c95 100644 --- a/testsuite/E12.py +++ b/testsuite/E12.py @@ -323,14 +323,14 @@ if line_removed: rv.update(d=('a', 'b', 'c'), e=42) # -#: E127 +#: E127 W503 rv.update(d=('a' + 'b', 'c'), e=42, f=42 + 42) -#: E127 +#: E127 W503 input1 = {'a': {'calc': 1 + 2}, 'b': 1 + 42} -#: E128 +#: E128 W503 rv.update(d=('a' + 'b', 'c'), e=42, f=(42 + 42)) diff --git a/testsuite/E25.py b/testsuite/E25.py index 9b7ff69..7a536b5 100644 --- a/testsuite/E25.py +++ b/testsuite/E25.py @@ -29,3 +29,12 @@ foo(bar=(1 >= 1)) foo(bar=(1 <= 1)) (options, args) = parser.parse_args() d[type(None)] = _deepcopy_atomic + +# Annotated Function Definitions +#: Okay +def munge(input: AnyStr, sep: AnyStr = None, limit=1000, + extra: Union[str, dict] = None) -> AnyStr: + pass +#: Okay +async def add(a: int = 0, b: int = 0) -> int: + return a + b diff --git a/testsuite/E27.py b/testsuite/E27.py index f9d3e8e..888b3a8 100644 --- a/testsuite/E27.py +++ b/testsuite/E27.py @@ -28,3 +28,17 @@ a and b a and b #: E273 E274 this and False +#: Okay +from u import (a, b) +from v import c, d +#: E271 +from w import (e, f) +#: E275 +from w import(e, f) +#: E275 +from importable.module import(e, f) +#: E275 +try: + from importable.module import(e, f) +except ImportError: + pass diff --git a/testsuite/E40.py b/testsuite/E40.py index d921c25..1051e32 100644 --- a/testsuite/E40.py +++ b/testsuite/E40.py @@ -11,3 +11,28 @@ from foo.bar.yourclass import YourClass import myclass import foo.bar.yourclass +#: E402 +__all__ = ['abc'] + +import foo +#: Okay +try: + import foo +except: + pass +else: + print('imported foo') +finally: + print('made attempt to import foo') + +import bar +#: E402 +VERSION = '1.2.3' + +import foo +#: E402 +import foo + +a = 1 + +import bar diff --git a/testsuite/E50.py b/testsuite/E50.py index 31ad6b9..f60f389 100644 --- a/testsuite/E50.py +++ b/testsuite/E50.py @@ -1,5 +1,19 @@ #: E501 a = '12345678901234567890123456789012345678901234567890123456789012345678901234567890' +#: E501 +a = '1234567890123456789012345678901234567890123456789012345678901234567890' or \ + 6 +#: E501 +a = 7 or \ + '1234567890123456789012345678901234567890123456789012345678901234567890' or \ + 6 +#: E501 E501 +a = 7 or \ + '1234567890123456789012345678901234567890123456789012345678901234567890' or \ + '1234567890123456789012345678901234567890123456789012345678901234567890' or \ + 6 +#: E501 +a = '1234567890123456789012345678901234567890123456789012345678901234567890' # \ #: E502 a = ('123456789012345678901234567890123456789012345678901234567890123456789' \ '01234567890') diff --git a/testsuite/E71.py b/testsuite/E71.py index ea870e5..7464da9 100644 --- a/testsuite/E71.py +++ b/testsuite/E71.py @@ -10,6 +10,18 @@ if None == res: #: E711 if None != res: pass +#: E711 +if res[1] == None: + pass +#: E711 +if res[1] != None: + pass +#: E711 +if None != res[1]: + pass +#: E711 +if None == res[1]: + pass # #: E712 @@ -24,6 +36,12 @@ if True != res: #: E712 if False == res: pass +#: E712 +if res[1] == True: + pass +#: E712 +if res[1] != False: + pass # #: E713 diff --git a/testsuite/W19.py b/testsuite/W19.py index edbb1f0..afdfb76 100644 --- a/testsuite/W19.py +++ b/testsuite/W19.py @@ -86,7 +86,7 @@ if (a == 2 or b == """abc def ghi jkl mno"""): return True -#: E101 W191 +#: W191:2:1 W191:3:1 E101:3:2 if length > options.max_line_length: return options.max_line_length, \ "E501 line too long (%d characters)" % length diff --git a/testsuite/support.py b/testsuite/support.py index 5185005..003f181 100644 --- a/testsuite/support.py +++ b/testsuite/support.py @@ -3,7 +3,7 @@ import os.path import re import sys -from pep8 import Checker, BaseReport, StandardReport, readlines +from pycodestyle import Checker, BaseReport, StandardReport, readlines SELFTEST_REGEX = re.compile(r'\b(Okay|[EW]\d{3}):\s(.*)') ROOT_DIR = os.path.dirname(os.path.dirname(__file__)) @@ -16,6 +16,9 @@ class PseudoFile(list): def getvalue(self): return ''.join(self) + def flush(self): + pass + class TestReport(StandardReport): """Collect the results for the tests.""" @@ -116,7 +119,7 @@ def selftest(options): print("%s: %s" % (code, source)) else: count_failed += 1 - print("pep8.py: %s:" % error) + print("pycodestyle.py: %s:" % error) for line in checker.lines: print(line.rstrip()) return count_failed, count_all diff --git a/testsuite/test_all.py b/testsuite/test_all.py index 50e2cb9..bd18943 100644 --- a/testsuite/test_all.py +++ b/testsuite/test_all.py @@ -4,24 +4,26 @@ import os.path import sys import unittest -import pep8 +import pycodestyle from testsuite.support import init_tests, selftest, ROOT_DIR # Note: please only use a subset of unittest methods which were present # in Python 2.5: assert(True|False|Equal|NotEqual|Raises) -class Pep8TestCase(unittest.TestCase): +class PycodestyleTestCase(unittest.TestCase): """Test the standard errors and warnings (E and W).""" def setUp(self): - self._style = pep8.StyleGuide( + self._style = pycodestyle.StyleGuide( paths=[os.path.join(ROOT_DIR, 'testsuite')], select='E,W', quiet=True) def test_doctest(self): import doctest - fail_d, done_d = doctest.testmod(pep8, verbose=False, report=False) + fail_d, done_d = doctest.testmod( + pycodestyle, verbose=False, report=False + ) self.assertTrue(done_d, msg='tests not found') self.assertFalse(fail_d, msg='%s failure(s)' % fail_d) @@ -37,20 +39,21 @@ class Pep8TestCase(unittest.TestCase): msg='%s failure(s)' % report.total_errors) def test_own_dog_food(self): - files = [pep8.__file__.rstrip('oc'), __file__.rstrip('oc'), + files = [pycodestyle.__file__.rstrip('oc'), __file__.rstrip('oc'), os.path.join(ROOT_DIR, 'setup.py')] - report = self._style.init_report(pep8.StandardReport) + report = self._style.init_report(pycodestyle.StandardReport) report = self._style.check_files(files) self.assertFalse(report.total_errors, msg='Failures: %s' % report.messages) def suite(): - from testsuite import test_api, test_shell, test_util + from testsuite import test_api, test_parser, test_shell, test_util suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(Pep8TestCase)) + suite.addTest(unittest.makeSuite(PycodestyleTestCase)) suite.addTest(unittest.makeSuite(test_api.APITestCase)) + suite.addTest(unittest.makeSuite(test_parser.ParserTestCase)) suite.addTest(unittest.makeSuite(test_shell.ShellTestCase)) suite.addTest(unittest.makeSuite(test_util.UtilTestCase)) return suite diff --git a/testsuite/test_api.py b/testsuite/test_api.py index de7bc7b..6549a46 100644 --- a/testsuite/test_api.py +++ b/testsuite/test_api.py @@ -4,7 +4,7 @@ import shlex import sys import unittest -import pep8 +import pycodestyle from testsuite.support import ROOT_DIR, PseudoFile E11 = os.path.join(ROOT_DIR, 'testsuite', 'E11.py') @@ -25,17 +25,18 @@ class APITestCase(unittest.TestCase): def setUp(self): self._saved_stdout = sys.stdout self._saved_stderr = sys.stderr - self._saved_checks = pep8._checks + self._saved_checks = pycodestyle._checks sys.stdout = PseudoFile() sys.stderr = PseudoFile() - pep8._checks = dict((k, dict((f, (vals[0][:], vals[1])) - for (f, vals) in v.items())) - for (k, v) in self._saved_checks.items()) + pycodestyle._checks = dict( + (k, dict((f, (vals[0][:], vals[1])) for (f, vals) in v.items())) + for (k, v) in self._saved_checks.items() + ) def tearDown(self): sys.stdout = self._saved_stdout sys.stderr = self._saved_stderr - pep8._checks = self._saved_checks + pycodestyle._checks = self._saved_checks def reset(self): del sys.stdout[:], sys.stderr[:] @@ -44,14 +45,14 @@ class APITestCase(unittest.TestCase): def check_dummy(physical_line, line_number): if False: yield - pep8.register_check(check_dummy, ['Z001']) + pycodestyle.register_check(check_dummy, ['Z001']) - self.assertTrue(check_dummy in pep8._checks['physical_line']) - codes, args = pep8._checks['physical_line'][check_dummy] + self.assertTrue(check_dummy in pycodestyle._checks['physical_line']) + codes, args = pycodestyle._checks['physical_line'][check_dummy] self.assertTrue('Z001' in codes) self.assertEqual(args, ['physical_line', 'line_number']) - options = pep8.StyleGuide().options + options = pycodestyle.StyleGuide().options self.assertTrue(any(func == check_dummy for name, func, args in options.physical_checks)) @@ -59,32 +60,32 @@ class APITestCase(unittest.TestCase): def check_dummy(logical_line, tokens): if False: yield - pep8.register_check(check_dummy, ['Z401']) + pycodestyle.register_check(check_dummy, ['Z401']) - self.assertTrue(check_dummy in pep8._checks['logical_line']) - codes, args = pep8._checks['logical_line'][check_dummy] + self.assertTrue(check_dummy in pycodestyle._checks['logical_line']) + codes, args = pycodestyle._checks['logical_line'][check_dummy] self.assertTrue('Z401' in codes) self.assertEqual(args, ['logical_line', 'tokens']) - pep8.register_check(check_dummy, []) - pep8.register_check(check_dummy, ['Z402', 'Z403']) - codes, args = pep8._checks['logical_line'][check_dummy] + pycodestyle.register_check(check_dummy, []) + pycodestyle.register_check(check_dummy, ['Z402', 'Z403']) + codes, args = pycodestyle._checks['logical_line'][check_dummy] self.assertEqual(codes, ['Z401', 'Z402', 'Z403']) self.assertEqual(args, ['logical_line', 'tokens']) - options = pep8.StyleGuide().options + options = pycodestyle.StyleGuide().options self.assertTrue(any(func == check_dummy for name, func, args in options.logical_checks)) def test_register_ast_check(self): - pep8.register_check(DummyChecker, ['Z701']) + pycodestyle.register_check(DummyChecker, ['Z701']) - self.assertTrue(DummyChecker in pep8._checks['tree']) - codes, args = pep8._checks['tree'][DummyChecker] + self.assertTrue(DummyChecker in pycodestyle._checks['tree']) + codes, args = pycodestyle._checks['tree'][DummyChecker] self.assertTrue('Z701' in codes) self.assertTrue(args is None) - options = pep8.StyleGuide().options + options = pycodestyle.StyleGuide().options self.assertTrue(any(cls == DummyChecker for name, cls, args in options.ast_checks)) @@ -96,23 +97,23 @@ class APITestCase(unittest.TestCase): def check_dummy(logical, tokens): if False: yield - pep8.register_check(InvalidChecker, ['Z741']) - pep8.register_check(check_dummy, ['Z441']) + pycodestyle.register_check(InvalidChecker, ['Z741']) + pycodestyle.register_check(check_dummy, ['Z441']) - for checkers in pep8._checks.values(): + for checkers in pycodestyle._checks.values(): self.assertTrue(DummyChecker not in checkers) self.assertTrue(check_dummy not in checkers) - self.assertRaises(TypeError, pep8.register_check) + self.assertRaises(TypeError, pycodestyle.register_check) def test_styleguide(self): - report = pep8.StyleGuide().check_files() + report = pycodestyle.StyleGuide().check_files() self.assertEqual(report.total_errors, 0) self.assertFalse(sys.stdout) self.assertFalse(sys.stderr) self.reset() - report = pep8.StyleGuide().check_files(['missing-file']) + report = pycodestyle.StyleGuide().check_files(['missing-file']) stdout = sys.stdout.getvalue().splitlines() self.assertEqual(len(stdout), report.total_errors) self.assertEqual(report.total_errors, 1) @@ -121,7 +122,7 @@ class APITestCase(unittest.TestCase): self.assertFalse(sys.stderr) self.reset() - report = pep8.StyleGuide().check_files([E11]) + report = pycodestyle.StyleGuide().check_files([E11]) stdout = sys.stdout.getvalue().splitlines() self.assertEqual(len(stdout), report.total_errors) self.assertEqual(report.total_errors, 17) @@ -129,7 +130,7 @@ class APITestCase(unittest.TestCase): self.reset() # Passing the paths in the constructor gives same result - report = pep8.StyleGuide(paths=[E11]).check_files() + report = pycodestyle.StyleGuide(paths=[E11]).check_files() stdout = sys.stdout.getvalue().splitlines() self.assertEqual(len(stdout), report.total_errors) self.assertEqual(report.total_errors, 17) @@ -138,10 +139,10 @@ class APITestCase(unittest.TestCase): def test_styleguide_options(self): # Instanciate a simple checker - pep8style = pep8.StyleGuide(paths=[E11]) + pep8style = pycodestyle.StyleGuide(paths=[E11]) # Check style's attributes - self.assertEqual(pep8style.checker_class, pep8.Checker) + self.assertEqual(pep8style.checker_class, pycodestyle.Checker) self.assertEqual(pep8style.paths, [E11]) self.assertEqual(pep8style.runner, pep8style.input_file) self.assertEqual(pep8style.options.ignore_code, pep8style.ignore_code) @@ -173,13 +174,16 @@ class APITestCase(unittest.TestCase): _saved_argv = sys.argv sys.argv = shlex.split('pep8 %s /dev/null' % argstring) try: - return pep8.StyleGuide(parse_argv=True) + return pycodestyle.StyleGuide(parse_argv=True) finally: sys.argv = _saved_argv options = parse_argv('').options self.assertEqual(options.select, ()) - self.assertEqual(options.ignore, ('E123', 'E226', 'E24', 'E704')) + self.assertEqual( + options.ignore, + ('E121', 'E123', 'E126', 'E226', 'E24', 'E704', 'W503') + ) options = parse_argv('--doctest').options self.assertEqual(options.select, ()) @@ -205,22 +209,22 @@ class APITestCase(unittest.TestCase): self.assertEqual(options.select, ('E24',)) self.assertEqual(options.ignore, ('',)) - pep8style = pep8.StyleGuide(paths=[E11]) + pep8style = pycodestyle.StyleGuide(paths=[E11]) self.assertFalse(pep8style.ignore_code('E112')) self.assertFalse(pep8style.ignore_code('W191')) self.assertTrue(pep8style.ignore_code('E241')) - pep8style = pep8.StyleGuide(select='E', paths=[E11]) + pep8style = pycodestyle.StyleGuide(select='E', paths=[E11]) self.assertFalse(pep8style.ignore_code('E112')) self.assertTrue(pep8style.ignore_code('W191')) self.assertFalse(pep8style.ignore_code('E241')) - pep8style = pep8.StyleGuide(select='W', paths=[E11]) + pep8style = pycodestyle.StyleGuide(select='W', paths=[E11]) self.assertTrue(pep8style.ignore_code('E112')) self.assertFalse(pep8style.ignore_code('W191')) self.assertTrue(pep8style.ignore_code('E241')) - pep8style = pep8.StyleGuide(select=('F401',), paths=[E11]) + pep8style = pycodestyle.StyleGuide(select=('F401',), paths=[E11]) self.assertEqual(pep8style.options.select, ('F401',)) self.assertEqual(pep8style.options.ignore, ('',)) self.assertFalse(pep8style.ignore_code('F')) @@ -228,7 +232,7 @@ class APITestCase(unittest.TestCase): self.assertTrue(pep8style.ignore_code('F402')) def test_styleguide_excluded(self): - pep8style = pep8.StyleGuide(paths=[E11]) + pep8style = pycodestyle.StyleGuide(paths=[E11]) self.assertFalse(pep8style.excluded('./foo/bar')) self.assertFalse(pep8style.excluded('./foo/bar/main.py')) @@ -245,7 +249,7 @@ class APITestCase(unittest.TestCase): self.assertFalse(pep8style.excluded('./CVS/subdir')) def test_styleguide_checks(self): - pep8style = pep8.StyleGuide(paths=[E11]) + pep8style = pycodestyle.StyleGuide(paths=[E11]) # Default lists of checkers self.assertTrue(len(pep8style.options.physical_checks) > 4) @@ -261,49 +265,51 @@ class APITestCase(unittest.TestCase): self.assertEqual(args[0], 'logical_line') # Do run E11 checks - options = pep8.StyleGuide().options - self.assertTrue(any(func == pep8.indentation + options = pycodestyle.StyleGuide().options + self.assertTrue(any(func == pycodestyle.indentation for name, func, args in options.logical_checks)) - options = pep8.StyleGuide(select=['E']).options - self.assertTrue(any(func == pep8.indentation + options = pycodestyle.StyleGuide(select=['E']).options + self.assertTrue(any(func == pycodestyle.indentation for name, func, args in options.logical_checks)) - options = pep8.StyleGuide(ignore=['W']).options - self.assertTrue(any(func == pep8.indentation + options = pycodestyle.StyleGuide(ignore=['W']).options + self.assertTrue(any(func == pycodestyle.indentation for name, func, args in options.logical_checks)) - options = pep8.StyleGuide(ignore=['E12']).options - self.assertTrue(any(func == pep8.indentation + options = pycodestyle.StyleGuide(ignore=['E12']).options + self.assertTrue(any(func == pycodestyle.indentation for name, func, args in options.logical_checks)) # Do not run E11 checks - options = pep8.StyleGuide(select=['W']).options - self.assertFalse(any(func == pep8.indentation + options = pycodestyle.StyleGuide(select=['W']).options + self.assertFalse(any(func == pycodestyle.indentation for name, func, args in options.logical_checks)) - options = pep8.StyleGuide(ignore=['E']).options - self.assertFalse(any(func == pep8.indentation + options = pycodestyle.StyleGuide(ignore=['E']).options + self.assertFalse(any(func == pycodestyle.indentation for name, func, args in options.logical_checks)) - options = pep8.StyleGuide(ignore=['E11']).options - self.assertFalse(any(func == pep8.indentation + options = pycodestyle.StyleGuide(ignore=['E11']).options + self.assertFalse(any(func == pycodestyle.indentation for name, func, args in options.logical_checks)) def test_styleguide_init_report(self): - pep8style = pep8.StyleGuide(paths=[E11]) + style = pycodestyle.StyleGuide(paths=[E11]) + + standard_report = pycodestyle.StandardReport - self.assertEqual(pep8style.options.reporter, pep8.StandardReport) - self.assertEqual(type(pep8style.options.report), pep8.StandardReport) + self.assertEqual(style.options.reporter, standard_report) + self.assertEqual(type(style.options.report), standard_report) - class MinorityReport(pep8.BaseReport): + class MinorityReport(pycodestyle.BaseReport): pass - report = pep8style.init_report(MinorityReport) - self.assertEqual(pep8style.options.report, report) + report = style.init_report(MinorityReport) + self.assertEqual(style.options.report, report) self.assertEqual(type(report), MinorityReport) - pep8style = pep8.StyleGuide(paths=[E11], reporter=MinorityReport) - self.assertEqual(type(pep8style.options.report), MinorityReport) - self.assertEqual(pep8style.options.reporter, MinorityReport) + style = pycodestyle.StyleGuide(paths=[E11], reporter=MinorityReport) + self.assertEqual(type(style.options.report), MinorityReport) + self.assertEqual(style.options.reporter, MinorityReport) def test_styleguide_check_files(self): - pep8style = pep8.StyleGuide(paths=[E11]) + pep8style = pycodestyle.StyleGuide(paths=[E11]) report = pep8style.check_files() self.assertTrue(report.total_errors) @@ -314,12 +320,12 @@ class APITestCase(unittest.TestCase): def test_check_unicode(self): # Do not crash if lines are Unicode (Python 2.x) - pep8.register_check(DummyChecker, ['Z701']) + pycodestyle.register_check(DummyChecker, ['Z701']) source = '#\n' if hasattr(source, 'decode'): source = source.decode('ascii') - pep8style = pep8.StyleGuide() + pep8style = pycodestyle.StyleGuide() count_errors = pep8style.input_file('stdin', lines=[source]) self.assertFalse(sys.stdout) @@ -327,15 +333,18 @@ class APITestCase(unittest.TestCase): self.assertEqual(count_errors, 0) def test_check_nullbytes(self): - pep8.register_check(DummyChecker, ['Z701']) + pycodestyle.register_check(DummyChecker, ['Z701']) - pep8style = pep8.StyleGuide() + pep8style = pycodestyle.StyleGuide() count_errors = pep8style.input_file('stdin', lines=['\x00\n']) stdout = sys.stdout.getvalue() if 'SyntaxError' in stdout: # PyPy 2.2 returns a SyntaxError expected = "stdin:1:2: E901 SyntaxError" + elif 'ValueError' in stdout: + # Python 3.5. + expected = "stdin:1:1: E901 ValueError" else: expected = "stdin:1:1: E901 TypeError" self.assertTrue(stdout.startswith(expected), @@ -345,13 +354,13 @@ class APITestCase(unittest.TestCase): self.assertEqual(count_errors, 1) def test_styleguide_unmatched_triple_quotes(self): - pep8.register_check(DummyChecker, ['Z701']) + pycodestyle.register_check(DummyChecker, ['Z701']) lines = [ 'def foo():\n', ' """test docstring""\'\n', ] - pep8style = pep8.StyleGuide() + pep8style = pycodestyle.StyleGuide() pep8style.input_file('stdin', lines=lines) stdout = sys.stdout.getvalue() @@ -359,7 +368,7 @@ class APITestCase(unittest.TestCase): self.assertTrue(expected in stdout) def test_styleguide_continuation_line_outdented(self): - pep8.register_check(DummyChecker, ['Z701']) + pycodestyle.register_check(DummyChecker, ['Z701']) lines = [ 'def foo():\n', ' pass\n', @@ -370,7 +379,7 @@ class APITestCase(unittest.TestCase): ' pass\n', ] - pep8style = pep8.StyleGuide() + pep8style = pycodestyle.StyleGuide() count_errors = pep8style.input_file('stdin', lines=lines) self.assertEqual(count_errors, 2) stdout = sys.stdout.getvalue() diff --git a/testsuite/test_parser.py b/testsuite/test_parser.py new file mode 100644 index 0000000..26a45fc --- /dev/null +++ b/testsuite/test_parser.py @@ -0,0 +1,61 @@ +import os +import tempfile +import unittest + +import pycodestyle + + +def _process_file(contents): + with tempfile.NamedTemporaryFile(delete=False) as f: + f.write(contents) + + options, args = pycodestyle.process_options(config_file=f.name) + os.remove(f.name) + + return options, args + + +class ParserTestCase(unittest.TestCase): + + def test_vanilla_ignore_parsing(self): + contents = b""" +[pep8] +ignore = E226,E24 + """ + options, args = _process_file(contents) + + self.assertEqual(options.ignore, ["E226", "E24"]) + + def test_multiline_ignore_parsing(self): + contents = b""" +[pep8] +ignore = + E226, + E24 + """ + + options, args = _process_file(contents) + + self.assertEqual(options.ignore, ["E226", "E24"]) + + def test_trailing_comma_ignore_parsing(self): + contents = b""" +[pep8] +ignore = E226, + """ + + options, args = _process_file(contents) + + self.assertEqual(options.ignore, ["E226"]) + + def test_multiline_trailing_comma_ignore_parsing(self): + contents = b""" +[pep8] +ignore = + E226, + E24, + """ + + options, args = _process_file(contents) + + self.assertEqual(options.ignore, ["E226", "E24"]) diff --git a/testsuite/test_shell.py b/testsuite/test_shell.py index e536852..760c228 100644 --- a/testsuite/test_shell.py +++ b/testsuite/test_shell.py @@ -3,7 +3,7 @@ import os.path import sys import unittest -import pep8 +import pycodestyle from testsuite.support import ROOT_DIR, PseudoFile @@ -14,9 +14,9 @@ class ShellTestCase(unittest.TestCase): self._saved_argv = sys.argv self._saved_stdout = sys.stdout self._saved_stderr = sys.stderr - self._saved_pconfig = pep8.PROJECT_CONFIG - self._saved_cpread = pep8.RawConfigParser._read - self._saved_stdin_get_value = pep8.stdin_get_value + self._saved_pconfig = pycodestyle.PROJECT_CONFIG + self._saved_cpread = pycodestyle.RawConfigParser._read + self._saved_stdin_get_value = pycodestyle.stdin_get_value self._config_filenames = [] self.stdin = '' sys.argv = ['pep8'] @@ -25,16 +25,16 @@ class ShellTestCase(unittest.TestCase): def fake_config_parser_read(cp, fp, filename): self._config_filenames.append(filename) - pep8.RawConfigParser._read = fake_config_parser_read - pep8.stdin_get_value = self.stdin_get_value + pycodestyle.RawConfigParser._read = fake_config_parser_read + pycodestyle.stdin_get_value = self.stdin_get_value def tearDown(self): sys.argv = self._saved_argv sys.stdout = self._saved_stdout sys.stderr = self._saved_stderr - pep8.PROJECT_CONFIG = self._saved_pconfig - pep8.RawConfigParser._read = self._saved_cpread - pep8.stdin_get_value = self._saved_stdin_get_value + pycodestyle.PROJECT_CONFIG = self._saved_pconfig + pycodestyle.RawConfigParser._read = self._saved_cpread + pycodestyle.stdin_get_value = self._saved_stdin_get_value def stdin_get_value(self): return self.stdin @@ -43,7 +43,7 @@ class ShellTestCase(unittest.TestCase): del sys.stdout[:], sys.stderr[:] sys.argv[1:] = args try: - pep8._main() + pycodestyle._main() errorcode = None except SystemExit: errorcode = sys.exc_info()[1].code @@ -88,7 +88,7 @@ class ShellTestCase(unittest.TestCase): self.assertTrue('setup.cfg' in config_filenames) def test_check_stdin(self): - pep8.PROJECT_CONFIG = () + pycodestyle.PROJECT_CONFIG = () stdout, stderr, errcode = self.pep8('-') self.assertFalse(errcode) self.assertFalse(stderr) @@ -111,7 +111,7 @@ class ShellTestCase(unittest.TestCase): def test_check_noarg(self): # issue #170: do not read stdin by default - pep8.PROJECT_CONFIG = () + pycodestyle.PROJECT_CONFIG = () stdout, stderr, errcode = self.pep8() self.assertEqual(errcode, 2) self.assertEqual(stderr.splitlines(), @@ -120,7 +120,7 @@ class ShellTestCase(unittest.TestCase): self.assertFalse(self._config_filenames) def test_check_diff(self): - pep8.PROJECT_CONFIG = () + pycodestyle.PROJECT_CONFIG = () diff_lines = [ "--- testsuite/E11.py 2006-06-01 08:49:50 +0500", "+++ testsuite/E11.py 2008-04-06 17:36:29 +0500", diff --git a/testsuite/test_util.py b/testsuite/test_util.py index 11395cc..8eaba7e 100644 --- a/testsuite/test_util.py +++ b/testsuite/test_util.py @@ -3,21 +3,21 @@ import os import unittest -import pep8 +from pycodestyle import normalize_paths class UtilTestCase(unittest.TestCase): def test_normalize_paths(self): cwd = os.getcwd() - self.assertEqual(pep8.normalize_paths(''), []) - self.assertEqual(pep8.normalize_paths([]), []) - self.assertEqual(pep8.normalize_paths(None), []) - self.assertEqual(pep8.normalize_paths(['foo']), ['foo']) - self.assertEqual(pep8.normalize_paths('foo'), ['foo']) - self.assertEqual(pep8.normalize_paths('foo,bar'), ['foo', 'bar']) - self.assertEqual(pep8.normalize_paths('foo, bar '), ['foo', 'bar']) - self.assertEqual(pep8.normalize_paths('/foo/bar,baz/../bat'), + self.assertEqual(normalize_paths(''), []) + self.assertEqual(normalize_paths([]), []) + self.assertEqual(normalize_paths(None), []) + self.assertEqual(normalize_paths(['foo']), ['foo']) + self.assertEqual(normalize_paths('foo'), ['foo']) + self.assertEqual(normalize_paths('foo,bar'), ['foo', 'bar']) + self.assertEqual(normalize_paths('foo, bar '), ['foo', 'bar']) + self.assertEqual(normalize_paths('/foo/bar,baz/../bat'), ['/foo/bar', cwd + '/bat']) - self.assertEqual(pep8.normalize_paths(".pyc,\n build/*"), + self.assertEqual(normalize_paths(".pyc,\n build/*"), ['.pyc', cwd + '/build/*']) @@ -1,15 +1,15 @@ -# Tox (http://codespeak.net/~hpk/tox/) is a tool for running tests +# Tox (https://testrun.org/tox/latest/) is a tool for running tests # in multiple virtualenvs. This configuration file will run the # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy, jython +envlist = py26, py27, py32, py33, py34, py35, pypy, pypy3, jython [testenv] commands = {envpython} setup.py install - {envpython} pep8.py --testsuite testsuite - {envpython} pep8.py --statistics pep8.py - {envpython} pep8.py --doctest + {envpython} pycodestyle.py --testsuite testsuite + {envpython} pycodestyle.py --statistics pycodestyle.py + {envpython} pycodestyle.py --doctest {envpython} -m testsuite.test_all |