diff options
| author | Ian Cordasco <graffatcolmingov@gmail.com> | 2016-06-25 12:01:02 -0500 |
|---|---|---|
| committer | Ian Cordasco <graffatcolmingov@gmail.com> | 2016-06-25 12:01:02 -0500 |
| commit | cee691059f0a2805c644a1c3541f70e306225b48 (patch) | |
| tree | 63ae4c14f3968d8d88c398bb4cbb15d691618202 /docs/source | |
| parent | 93089108932a5382630243a5691d4cf796b60ec4 (diff) | |
| parent | 6eb2e3a70147baad1cc2ad3d51c269974da2320f (diff) | |
| download | flake8-cee691059f0a2805c644a1c3541f70e306225b48.tar.gz | |
Merge branch 'origin/proposed/3.0' into master3.0.0b1
Diffstat (limited to 'docs/source')
65 files changed, 3906 insertions, 0 deletions
diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..c7a0fd0 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,300 @@ +# -*- coding: utf-8 -*- +# +# flake8 documentation build configuration file, created by +# sphinx-quickstart on Tue Jan 19 07:14:10 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.3' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.viewcode', + 'sphinx-prompt', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'flake8' +copyright = u'2016, Ian Cordasco' +author = u'Ian Cordasco' + +import flake8 +# 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. +# +# The short X.Y version. +version = flake8.__version__ +# The full version, including alpha/beta/rc tags. +release = flake8.__version__ + +rst_epilog = """ +.. |Flake8| replace:: :program:`Flake8` +""" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'sphinx_rtd_theme' + +# 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 +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# 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'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'flake8doc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'flake8.tex', u'flake8 Documentation', + u'Ian Cordasco', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'flake8', u'flake8 Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Flake8', u'Flake8 Documentation', u'Tarek Ziade', + 'Flake8', 'Code checking using pycodestyle, pyflakes and mccabe', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None)} diff --git a/docs/source/faq.rst b/docs/source/faq.rst new file mode 100644 index 0000000..3f2bc04 --- /dev/null +++ b/docs/source/faq.rst @@ -0,0 +1,56 @@ +============================ + Frequently Asked Questions +============================ + +When is Flake8 released? +======================== + +|Flake8| is released *as necessary*. Sometimes there are specific goals and +drives to get to a release. Usually, we release as users report and fix +bugs. + + +How can I help Flake8 release faster? +===================================== + +Look at the next milestone. If there's work you can help us complete, that +will help us get to the next milestone. If there's a show-stopping bug that +needs to be released, let us know but please be kind. |Flake8| is developed +and released entirely on volunteer time. + + +What is the next version of Flake8? +=================================== + +In general we try to use milestones to indicate this. If the last release +on PyPI is 3.1.5 and you see a milestone for 3.2.0 in GitLab, there's a +good chance that 3.2.0 is the next release. + + +Why does Flake8 use ranges for its dependencies? +================================================ + +|Flake8| uses ranges for mccabe, pyflakes, and pycodestyle because each of +those projects tend to add *new* checks in minor releases. It has been an +implicit design goal of |Flake8|'s to make the list of error codes stable in +its own minor releases. That way if you install something from the 2.5 +series today, you will not find new checks in the same series in a month +from now when you install it again. + +|Flake8|'s dependencies tend to avoid new checks in patch versions which is +why |Flake8| expresses its dependencies roughly as:: + + pycodestyle >= 2.0.0, < 2.1.0 + pyflakes >= 0.8.0, != 1.2.0, != 1.2.1, != 1.2.2, < 1.3.0 + mccabe >= 0.5.0, < 0.6.0 + +This allows those projects to release patch versions that fix bugs and for +|Flake8| users to consume those fixes. + + +Should I file an issue when a new version of a dependency is available? +======================================================================= + +**No.** The current Flake8 core team (of one person) is also +a core developer of pycodestyle, pyflakes, and mccabe. They are aware of +these releases. diff --git a/docs/source/glossary.rst b/docs/source/glossary.rst new file mode 100644 index 0000000..dd691b6 --- /dev/null +++ b/docs/source/glossary.rst @@ -0,0 +1,56 @@ +.. _glossary: + +================================================ + Glossary of Terms Used in Flake8 Documentation +================================================ + +.. glossary:: + :sorted: + + formatter + A :term:`plugin` that augments the output of |Flake8| when passed + to :option:`flake8 --format`. + + plugin + A package that is typically installed from PyPI to augment the + behaviour of |Flake8| either through adding one or more additional + :term:`check`\ s or providing additional :term:`formatter`\ s. + + check + A piece of logic that corresponds to an error code. A check may + be a style check (e.g., check the length of a given line against + the user configured maximum) or a lint check (e.g., checking for + unused imports) or some other check as defined by a plugin. + + error + error code + The symbol associated with a specific :term:`check`. For example, + pycodestyle implements :term:`check`\ s that look for whitespace + around binary operators and will either return an error code of + ``W503`` or ``W504``. + + warning + Typically the ``W`` class of :term:`error code`\ s from pycodestyle. + + class + error class + A larger grouping of related :term:`error code`\ s. For example, + ``W503`` and ``W504`` are two codes related to whitespace. ``W50`` + would be the most specific class of codes relating to whitespace. + ``W`` would be the warning class that subsumes all whitespace + errors. + + pyflakes + The project |Flake8| depends on to lint files (check for unused + imports, variables, etc.). This uses the ``F`` :term:`class` of + :term:`error code`\ s reported by |Flake8|. + + pycodestyle + The project |Flake8| depends on to provide style enforcement. + pycodestyle implements :term:`check`\ s for :pep:`8`. This uses the + ``E`` and ``W`` :term:`class`\ es of :term:`error code`\ s. + + mccabe + The project |Flake8| depends on to calculate the McCabe complexity + of a unit of code (e.g., a function). This uses the ``C`` + :term:`class` of :term`error code`\ s. diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..51b0189 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,131 @@ +.. flake8 documentation master file, created by + sphinx-quickstart on Tue Jan 19 07:14:10 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +=============================================== + Flake8: Your Tool For Style Guide Enforcement +=============================================== + +Quickstart +========== + +.. _installation-guide: + +Installation +------------ + +To install |Flake8|, open an interactive shell and run: + +.. code:: + + python<version> -m pip install flake8 + +If you want |Flake8| to be installed for your default Python installation, you +can instead use: + +.. code:: + + python -m pip install flake8 + +.. note:: + + It is **very** important to install |Flake8| on the *correct* version of + Python for your needs. If you want |Flake8| to properly parse new language + features in Python 3.5 (for example), you need it to be installed on 3.5 + for |Flake8| to understand those features. In many ways, Flake8 is tied to + the version of Python on which it runs. + +Using Flake8 +------------ + +To start using |Flake8|, open an interactive shell and run: + +.. code:: + + flake8 path/to/code/to/check.py + # or + flake8 path/to/code/ + +.. note:: + + If you have installed |Flake8| on a particular version of Python (or on + several versions), it may be best to instead run ``python<version> -m + flake8``. + +If you only want to see the instances of a specific warning or error, you can +*select* that error like so: + +.. code:: + + flake8 --select E123,W503 path/to/code/ + +Alternatively, if you want to *ignore* only one specific warning or error: + +.. code:: + + flake8 --ignore E24,W504 path/to/code/ + +Please read our user guide for more information about how to use and configure +|Flake8|. + +FAQ and Glossary +================ + +.. toctree:: + :maxdepth: 2 + + faq + glossary + +User Guide +========== + +All users of |Flake8| should read this portion of the documentation. This +provides examples and documentation around |Flake8|'s assortment of options +and how to specify them on the command-line or in configuration files. + +.. toctree:: + :maxdepth: 2 + + user/index + +Plugin Developer Guide +====================== + +If you're maintaining a plugin for |Flake8| or creating a new one, you should +read this section of the documentation. It explains how you can write your +plugins and distribute them to others. + +.. toctree:: + :maxdepth: 2 + + plugin-development/index + +Contributor Guide +================= + +If you are reading |Flake8|'s source code for fun or looking to contribute, +you should read this portion of the documentation. This is a mix of documenting +the internal-only interfaces |Flake8| and documenting reasoning for Flake8's +design. + +.. toctree:: + :maxdepth: 2 + + internal/index + +Release Notes and History +========================= + +.. toctree:: + :maxdepth: 2 + + release-notes/index + +General Indices +=============== + +* :ref:`genindex` +* :ref:`Index of Documented Public Modules <modindex>` +* :ref:`Glossary of terms <glossary>` diff --git a/docs/source/internal/.keep b/docs/source/internal/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/source/internal/.keep diff --git a/docs/source/internal/checker.rst b/docs/source/internal/checker.rst new file mode 100644 index 0000000..19bcf7d --- /dev/null +++ b/docs/source/internal/checker.rst @@ -0,0 +1,70 @@ +==================== + How Checks are Run +==================== + +In |Flake8| 2.x, |Flake8| delegated check running to pep8. In 3.0 |Flake8| +takes on that responsibility. This has allowed for simpler +handling of the ``--jobs`` parameter (using :mod:`multiprocessing`) and +simplified our fallback if something goes awry with concurency. +At the lowest level we have a |FileChecker|. Instances of |FileChecker| are +created for *each* file to be analyzed by |Flake8|. Each instance, has a copy +of all of the plugins registered with setuptools in the ``flake8.extension`` +entry-point group. + +The |FileChecker| instances are managed by an instance of |Manager|. The +|Manager| instance handles creating sub-processes with +:mod:`multiprocessing` module and falling back to running checks in serial if +an operating system level error arises. When creating |FileChecker| instances, +the |Manager| is responsible for determining if a particular file has been +excluded. + + +Processing Files +---------------- + +Unfortunately, since |Flake8| took over check running from pep8/pycodestyle, +it also had to take over parsing and processing files for the checkers +to use. Since it couldn't reuse pycodestyle's functionality (since it did not +separate cleanly the processing from check running) that function was isolated +into the :class:`~flake8.processor.FileProcessor` class. We moved +several helper functions into the :mod:`flake8.processor` module (see also +:ref:`Processor Utility Functions <processor_utility_functions>`). + + +API Reference +------------- + +.. autoclass:: flake8.checker.FileChecker + :members: + +.. autoclass:: flake8.checker.Manager + :members: + +.. autoclass:: flake8.processor.FileProcessor + :members: + + +.. _processor_utility_functions: + +Utility Functions +````````````````` + +.. autofunction:: flake8.processor.count_parentheses + +.. autofunction:: flake8.processor.expand_indent + +.. autofunction:: flake8.processor.is_eol_token + +.. autofunction:: flake8.processor.is_multiline_string + +.. autofunction:: flake8.processor.log_token + +.. autofunction:: flake8.processor.mutate_string + +.. autofunction:: flake8.processor.token_is_comment + +.. autofunction:: flake8.processor.token_is_newline + +.. Substitutions +.. |FileChecker| replace:: :class:`~flake8.checker.FileChecker` +.. |Manager| replace:: :class:`~flake8.checker.Manager` diff --git a/docs/source/internal/cli.rst b/docs/source/internal/cli.rst new file mode 100644 index 0000000..f203125 --- /dev/null +++ b/docs/source/internal/cli.rst @@ -0,0 +1,26 @@ +Command Line Interface +====================== + +The command line interface of |Flake8| is modeled as an application via +:class:`~flake8.main.cli.Application`. When a user runs ``flake8`` at their +command line, :func:`~flake8.main.cli.main` is run which handles +management of the application. + +User input is parsed *twice* to accomodate logging and verbosity options +passed by the user as early as possible. +This is so as much logging can be produced as possible. + +The default |Flake8| options are registered by +:func:`~flake8.main.options.register_default_options`. Trying to register +these options in plugins will result in errors. + + +API Documentation +----------------- + +.. autofunction:: flake8.main.cli.main + +.. autoclass:: flake8.main.application.Application + :members: + +.. autofunction:: flake8.main.options.register_default_options diff --git a/docs/source/internal/contributing.rst b/docs/source/internal/contributing.rst new file mode 100644 index 0000000..29afc6a --- /dev/null +++ b/docs/source/internal/contributing.rst @@ -0,0 +1,202 @@ +======================== + Contributing to Flake8 +======================== + +There are many ways to contriubte to |Flake8|, and we encourage them all: + +- contributing bug reports and feature requests + +- contributing documenation (and yes that includes this document) + +- reviewing and triaging bugs and merge requests + +Before you go any further, please allow me to reassure you that I do want +*your* contribution. If you think your contribution might not be valuable, I +reassure you that any help you can provide *is* valuable. + + +Code of Conduct +=============== + +|Flake8| adheres to the `Python Code Quality Authority's Code of Conduct`_. +Any violations of the Code of Conduct should be reported to Ian Cordasco +(graffatcolmingov [at] gmail [dot] com). + + +Setting Up A Development Environment +==================================== + +To contribute to |Flake8|'s development, you simply need: + +- Python (one of the versions we support) + +- `tox`_ + + We suggest installing this like: + + .. prompt:: bash + + pip install --user tox + + Or + + .. prompt:: bash + + python<version> -m pip install --user tox + +- your favorite editor + + +Filing a Bug +============ + +When filing a bug against |Flake8|, please fill out the issue template as it +is provided to you by `GitLab`_. If your bug is in reference to one of the +checks that |Flake8| reports by default, please do not report them to |Flake8| +unless |Flake8| is doing something to prevent the check from running or you +have some reason to believe |Flake8| is inhibiting the effectiveness of the +check. + +**Please search for closed and open bug reports before opening new ones.** + +All bug reports about checks should go to their respective projects: + +- Error codes starting with ``E`` and ``W`` should be reported to + `pycodestyle`_. + +- Error codes starting with ``F`` should be reported to `pyflakes`_ + +- Error codes starting with ``C`` should be reported to `mccabe`_ + + +Requesting a New Feature +======================== + +When requesting a new feature in |Flake8|, please fill out the issue template. +Please also note if there are any existing alternatives to your new feature +either via plugins, or combining command-line options. Please provide example +use cases. For example, do not ask for a feature like this: + + I need feature frobulate for my job. + +Instead ask: + + I need |Flake8| to frobulate these files because my team expects them to + frobulated but |Flake8| currently does not frobulate them. We tried using + ``--filename`` but we could not create a pattern that worked. + +The more you explain about *why* you need a feature, the more likely we are to +understand your needs and help you to the best of our ability. + + +Contributing Documentation +========================== + +To contribute to |Flake8|'s documentation, you might want to first read a +little about reStructuredText or Sphinx. |Flake8| has a :ref:`guide of best +practices <docs-style>` when contributing to our documentation. For the most +part, you should be fine following the structure and style of the rest of +|Flake8|'s documentation. + +All of |Flake8|'s documentation is written in reStructuredText and rendered by +Sphinx. The source (reStructuredText) lives in ``docs/source/``. To build +the documentation the way our Continuous Integration does, run: + +.. prompt:: bash + + tox -e docs + +To view the documentation locally, you can also run: + +.. prompt:: bash + + tox -e serve-docs + +You can run the latter in a separate terminal and continuously re-run the +documentation generation and refresh the documentation you're working on. + +.. note:: + + We lint our documentation just like we lint our code. + You should also run: + + .. prompt:: bash + + tox -e linters + + After making changes and before pushing them to ensure that they will + pass our CI tests. + + +Contributing Code +================= + +|Flake8| development happens on `GitLab`_. Code contributions should be +submitted there. + +Merge requests should: + +- Fix one issue and fix it well + + Fix the issue, but do not include extraneous refactoring or code + reformatting. In other words, keep the diff short, but only as short + as is necessary to fix the bug appropriately and add sufficient testing + around it. Long diffs are fine, so long as everything that it includes + is necessary to the purpose of the merge request. + +- Have descriptive titles and descriptions + + Searching old merge requests is made easier when a merge request is well + described. + +- Have commits that follow this style: + + .. code:: + + Create a short title that is 50 characters long + + Ensure the title and commit message use the imperative voice. The + commit and you are doing something. Also, please ensure that the + body of the commit message does not exceed 72 characters. + + The body may have multiple paragraphs as necessary. + + The final line of the body references the issue appropriately. + + +Reviewing and Triaging Issues and Merge Requests +================================================ + +When reviewing other people's merge requests and issues, please be +**especially** mindful of how the words you choose can be read by someone +else. We strive for professional code reviews that do not insult the +contributor's intelligence or impugn their character. The code review +should be focused on the code, it's effectiveness, and whether it is +appropriate for |Flake8|. + +If you have the ability to edit an issue or merge request's labels, please do +so to make search and prioritization easier. + +|Flake8| uses milestones with both issues and merge requests. This provides +direction for other contributors about when an issue or merge request will be +delivered. + + +.. links +.. _Python Code Quality Authority's Code of Conduct: + http://meta.pycqa.org/en/latest/code-of-conduct.html + +.. _tox: + https://tox.readthedocs.io/ + +.. _GitLab: + https://gitlab.com/pycqa/flake8 + +.. _pycodestyle: + https://github.com/pycqa/pycodestyle + +.. _pyflakes: + https://github.com/pyflakes/pyflakes + +.. _mccabe: + https://github.com/pycqa/mccabe diff --git a/docs/source/internal/formatters.rst b/docs/source/internal/formatters.rst new file mode 100644 index 0000000..c58189b --- /dev/null +++ b/docs/source/internal/formatters.rst @@ -0,0 +1,47 @@ +===================== + Built-in Formatters +===================== + +By default |Flake8| has two formatters built-in, ``default`` and ``pylint``. +These correspond to two classes |DefaultFormatter| and |PylintFormatter|. + +In |Flake8| 2.0, pep8 handled formatting of errors and also allowed users to +specify an arbitrary format string as a parameter to ``--format``. In order +to allow for this backwards compatibility, |Flake8| 3.0 made two choices: + +#. To not limit a user's choices for ``--format`` to the format class names + +#. To make the default formatter attempt to use the string provided by the + user if it cannot find a formatter with that name. + +Default Formatter +================= + +The |DefaultFormatter| continues to use the same default format string as +pep8: ``'%(path)s:%(row)d:%(col)d: %(code)s %(text)s'``. + +To provide the default functionality it overrides two methods: + +#. ``after_init`` + +#. ``format`` + +The former allows us to inspect the value provided to ``--format`` by the +user and alter our own format based on that value. The second simply uses +that format string to format the error. + +.. autoclass:: flake8.formatting.default.Default + :members: + +Pylint Formatter +================ + +The |PylintFormatter| simply defines the default Pylint format string from +pep8: ``'%(path)s:%(row)d: [%(code)s] %(text)s'``. + +.. autoclass:: flake8.formatting.default.Pylint + :members: + + +.. |DefaultFormatter| replace:: :class:`~flake8.formatting.default.Default` +.. |PylintFormatter| replace:: :class:`~flake8.formatting.default.Pylint` diff --git a/docs/source/internal/index.rst b/docs/source/internal/index.rst new file mode 100644 index 0000000..482b898 --- /dev/null +++ b/docs/source/internal/index.rst @@ -0,0 +1,26 @@ +============================== + Exploring Flake8's Internals +============================== + +While writing |Flake8| 3.0, the developers attempted to capture some reasoning +and decision information in internal documentation meant for future developers +and maintaners. Most of this information is unnecessary for users and plugin +developers. Some of it, however, is linked to from the plugin development +documentation. + +Keep in mind that not everything will be here and you may need to help pull +information out of the developers' heads and into these documents. Please +pull gently. + +.. toctree:: + :maxdepth: 2 + + contributing + writing-documentation + releases + checker + cli + formatters + option_handling + plugin_handling + utils diff --git a/docs/source/internal/option_handling.rst b/docs/source/internal/option_handling.rst new file mode 100644 index 0000000..74ecb76 --- /dev/null +++ b/docs/source/internal/option_handling.rst @@ -0,0 +1,234 @@ +Option and Configuration Handling +================================= + +Option Management +----------------- + +Command-line options are often also set in configuration files for |Flake8|. +While not all options are meant to be parsed from configuration files, many +default options are also parsed from configuration files as well as +most plugin options. + +In |Flake8| 2, plugins received a :class:`optparse.OptionParser` instance and +called :meth:`optparse.OptionParser.add_option` to register options. If the +plugin author also wanted to have that option parsed from config files they +also had to do something like: + +.. code-block:: python + + parser.config_options.append('my_config_option') + parser.config_options.extend(['config_opt1', 'config_opt2']) + +This was previously undocumented and led to a lot of confusion about why +registered options were not automatically parsed from configuration files. + +Since |Flake8| 3 was rewritten from scratch, we decided to take a different +approach to configuration file parsing. Instead of needing to know about an +undocumented attribute that pep8 looks for, |Flake8| 3 now accepts a parameter +to ``add_option``, specifically ``parse_from_config`` which is a boolean +value. + +|Flake8| does this by creating its own abstractions on top of :mod:`optparse`. +The first abstraction is the :class:`flake8.options.manager.Option` class. The +second is the :class:`flake8.options.manager.OptionManager`. In fact, we add +three new parameters: + +- ``parse_from_config`` + +- ``comma_separated_list`` + +- ``normalize_paths`` + +The last two are not specifically for configuration file handling, but they +do improve that dramatically. We found that there were options that, when +specified in a configuration file, often necessitated being spit +multiple lines and those options were almost always comma-separated. For +example, let's consider a user's list of ignored error codes for a project: + +.. code-block:: ini + + [flake8] + ignore = + # Reasoning + E111, + # Reasoning + E711, + # Reasoning + E712, + # Reasoning + E121, + # Reasoning + E122, + # Reasoning + E123, + # Reasoning + E131, + # Reasoning + E251 + +It makes sense here to allow users to specify the value this way, but, the +standard libary's :class:`configparser.RawConfigParser` class does returns a +string that looks like + +.. code-block:: python + + "\nE111, \nE711, \nE712, \nE121, \nE122, \nE123, \nE131, \nE251 " + +This means that a typical call to :meth:`str.split` with ``','`` will not be +sufficient here. Telling |Flake8| that something is a comma-separated list +(e.g., ``comma_separated_list=True``) will handle this for you. |Flake8| will +return: + +.. code-block:: python + + ["E111", "E711", "E712", "E121", "E122", "E123", "E131", "E251"] + +Next let's look at how users might like to specify their ``exclude`` list. +Presently OpenStack's Nova project has this line in their `tox.ini`_: + +.. code-block:: ini + + exclude = .venv,.git,.tox,dist,doc,*openstack/common/*,*lib/python*,*egg,build,tools/xenserver*,releasenotes + +We think we can all agree that this would be easier to read like this: + +.. code-block:: ini + + exclude = + .venv, + .git, + .tox, + dist, + doc, + *openstack/common/*, + *lib/python*, + *egg, + build, + tools/xenserver*, + releasenotes + +In this case, since these are actually intended to be paths, we would specify +both ``comma_separated_list=True`` and ``normalize_paths=True`` because we +want the paths to be provided to us with some consistency (either all absolute +paths or not). + +Now let's look at how this will actually be used. Most plugin developers +will receive an instance of :class:`~flake8.options.manager.OptionManager` so +to ease the transition we kept the same API as the +:class:`optparse.OptionParser` object. The only difference is that +:meth:`~flake8.options.manager.OptionManager.add_option` accepts the three +extra arguments we highlighted above. + +.. _tox.ini: + https://github.com/openstack/nova/blob/3eb190c4cfc0eefddac6c2cc1b94a699fb1687f8/tox.ini#L155 + +Configuration File Management +----------------------------- + +In |Flake8| 2, configuration file discovery and management was handled by +pep8. In pep8's 1.6 release series, it drastically broke how discovery and +merging worked (as a result of trying to improve it). To avoid a dependency +breaking |Flake8| again in the future, we have created our own discovery and +management. +As part of managing this ourselves, we decided to change management/discovery +for 3.0.0. We have done the following: + +- User files (files stored in a user's home directory or in the XDG directory + inside their home directory) are the first files read. For example, if the + user has a ``~/.flake8`` file, we will read that first. + +- Project files (files stored in the current directory) are read next and + merged on top of the user file. In other words, configuration in project + files takes precedence over configuration in user files. + +- **New in 3.0.0** The user can specify ``--append-config <path-to-file>`` + repeatedly to include extra configuration files that should be read and + take precedence over user and project files. + +- **New in 3.0.0** The user can specify ``--config <path-to-file>`` to so this + file is the only configuration file used. This is a change from |Flake8| 2 + where pep8 would simply merge this configuration file into the configuration + generated by user and project files (where this takes precedence). + +- **New in 3.0.0** The user can specify ``--isolated`` to disable + configuration via discovered configuration files. + +To facilitate the configuration file management, we've taken a different +approach to discovery and management of files than pep8. In pep8 1.5, 1.6, and +1.7 configuration discovery and management was centralized in `66 lines of +very terse python`_ which was confusing and not very explicit. The terseness +of this function (|Flake8|'s authors believe) caused the confusion and +problems with pep8's 1.6 series. As such, |Flake8| has separated out +discovery, management, and merging into a module to make reasoning about each +of these pieces easier and more explicit (as well as easier to test). + +Configuration file discovery is managed by the +:class:`~flake8.options.config.ConfigFileFinder` object. This object needs to +know information about the program's name, any extra arguments passed to it, +and any configuration files that should be appended to the list of discovered +files. It provides methods for finding the files and similiar methods for +parsing those fles. For example, it provides +:meth:`~flake8.options.config.ConfigFileFinder.local_config_files` to find +known local config files (and append the extra configuration files) and it +also provides :meth:`~flake8.options.config.ConfigFileFinder.local_configs` +to parse those configuration files. + +.. note:: ``local_config_files`` also filters out non-existent files. + +Configuration file merging and managemnt is controlled by the +:class:`~flake8.options.config.MergedConfigParser`. This requires the instance +of :class:`~flake8.options.manager.OptionManager` that the program is using, +the list of appended config files, and the list of extra arguments. This +object is currently the sole user of the +:class:`~flake8.options.config.ConfigFileFinder` object. It appropriately +initializes the object and uses it in each of + +- :meth:`~flake8.options.config.MergedConfigParser.parse_cli_config` +- :meth:`~flake8.options.config.MergedConfigParser.parse_local_config` +- :meth:`~flake8.options.config.MergedConfigParser.parse_user_config` + +Finally, +:meth:`~flake8.options.config.MergedConfigParser.merge_user_and_local_config` +takes the user and local configuration files that are parsed by +:meth:`~flake8.options.config.MergedConfigParser.parse_local_config` and +:meth:`~flake8.options.config.MergedConfigParser.parse_user_config`. The +main usage of the ``MergedConfigParser`` is in +:func:`~flake8.options.aggregator.aggregate_options`. + +Aggregating Configuration File and Command Line Arguments +--------------------------------------------------------- + +:func:`~flake8.options.aggregator.aggregate_options` accepts an instance of +:class:`~flake8.options.maanger.OptionManager` and does the work to parse the +command-line arguments passed by the user necessary for creating an instance +of :class:`~flake8.options.config.MergedConfigParser`. + +After parsing the configuration file, we determine the default ignore list. We +use the defaults from the OptionManager and update those with the parsed +configuration files. Finally we parse the user-provided options one last time +using the option defaults and configuration file values as defaults. The +parser merges on the command-line specified arguments for us so we have our +final, definitive, aggregated options. + +.. _66 lines of very terse python: + https://github.com/PyCQA/pep8/blob/b8088a2b6bc5b76bece174efad877f764529bc74/pep8.py#L1981..L2047 + +API Documentation +----------------- + +.. autofunction:: flake8.options.aggregator.aggregate_options + +.. autoclass:: flake8.options.manager.Option + :members: __init__, normalize, to_optparse + +.. autoclass:: flake8.options.manager.OptionManager + :members: + :special-members: + +.. autoclass:: flake8.options.config.ConfigFileFinder + :members: + :special-members: + +.. autoclass:: flake8.options.config.MergedConfigParser + :members: + :special-members: diff --git a/docs/source/internal/plugin_handling.rst b/docs/source/internal/plugin_handling.rst new file mode 100644 index 0000000..9af3182 --- /dev/null +++ b/docs/source/internal/plugin_handling.rst @@ -0,0 +1,129 @@ +Plugin Handling +=============== + +Plugin Management +----------------- + +|Flake8| 3.0 added support for two other plugins besides those which define +new checks. It now supports: + +- extra checks + +- alternative report formatters + +- listeners to auto-correct violations of checks + +To facilitate this, |Flake8| needed a more mature way of managing plugins. +Thus, we developed the |PluginManager| which accepts a namespace and will load +the plugins for that namespace. A |PluginManager| creates and manages many +|Plugin| instances. + +A |Plugin| lazily loads the underlying entry-point provided by setuptools. +The entry-point will be loaded either by calling +:meth:`~flake8.plugins.manager.Plugin.load_plugin` or accessing the ``plugin`` +attribute. We also use this abstraction to retrieve options that the plugin +wishes to register and parse. + +The only public method the |PluginManager| provides is +:meth:`~flake8.plugins.manager.PluginManager.map`. This will accept a function +(or other callable) and call it with each plugin as the first parameter. + +We build atop the |PluginManager| with the |PTM|. It is expected that users of +the |PTM| will subclass it and specify the ``namespace``, e.g., + +.. code-block:: python + + class ExamplePluginType(flake8.plugin.manager.PluginTypeManager): + namespace = 'example-plugins' + +This provides a few extra methods via the |PluginManager|'s ``map`` method. + +Finally, we create three classes of plugins: + +- :class:`~flake8.plugins.manager.Checkers` + +- :class:`~flake8.plugins.manager.Listeners` + +- :class:`~flake8.plugins.manager.ReportFormatters` + +These are used to interact with each of the types of plugins individually. + +.. note:: + + Our inspiration for our plugin handling comes from the author's extensive + experience with ``stevedore``. + +Notifying Listener Plugins +-------------------------- + +One of the interesting challenges with allowing plugins to be notified each +time an error or warning is emitted by a checker is finding listeners quickly +and efficiently. It makes sense to allow a listener to listen for a certain +class of warnings or just a specific warning. Hence, we need to allow all +plugins that listen to a specific warning or class to be notified. For +example, someone might register a listener for ``E1`` and another for ``E111`` +if ``E111`` is triggered by the code, both listeners should be notified. +If ``E112`` is returned, then only ``E1`` (and any other listeners) would be +notified. + +To implement this goal, we needed an object to store listeners in that would +allow for efficient look up - a Trie (or Prefix Tree). Given that none of the +existing packages on PyPI allowed for storing data on each node of the trie, +it was left up to write our own as :class:`~flake8.plugins._trie.Trie`. On +top of that we layer our :class:`~flake8.plugins.notifier.Notifier` class. + +Now when |Flake8| receives an error or warning, we can easily call the +:meth:`~flake8.plugins.notifier.Notifier.notify` method and let plugins act on +that knowledge. + +Default Plugins +--------------- + +Finally, |Flake8| has always provided its own plugin shim for Pyflakes. As +part of that we carry our own shim in-tree and now store that in +:mod:`flake8.plugins.pyflakes`. + +|Flake8| also registers plugins for pep8. Each check in pep8 requires +different parameters and it cannot easily be shimmed together like Pyflakes +was. As such, plugins have a concept of a "group". If you look at our +:file:`setup.py` you will see that we register pep8 checks roughly like so: + +.. code:: + + pep8.<check-name> = pep8:<check-name> + +We do this to identify that ``<check-name>>`` is part of a group. This also +enables us to special-case how we handle reporting those checks. Instead of +reporting each check in the ``--version`` output, we report ``pep8`` and check +``pep8`` the module for a ``__version__`` attribute. We only report it once +to avoid confusing users. + +API Documentation +----------------- + +.. autoclass:: flake8.plugins.manager.PluginManager + :members: + :special-members: __init__, __contains__, __getitem__ + +.. autoclass:: flake8.plugins.manager.Plugin + :members: + :special-members: __init__ + +.. autoclass:: flake8.plugins.manager.PluginTypeManager + :members: + +.. autoclass:: flake8.plugins.manager.Checkers + :members: + +.. autoclass:: flake8.plugins.manager.Listeners + :members: build_notifier + +.. autoclass:: flake8.plugins.manager.ReportFormatters + +.. autoclass:: flake8.plugins.notifier.Notifier + +.. autoclass:: flake8.plugins._trie.Trie + +.. |PluginManager| replace:: :class:`~flake8.plugins.manager.PluginManager` +.. |Plugin| replace:: :class:`~flake8.plugins.manager.Plugin` +.. |PTM| replace:: :class:`~flake8.plugins.manager.PluginTypeManager` diff --git a/docs/source/internal/releases.rst b/docs/source/internal/releases.rst new file mode 100644 index 0000000..a624930 --- /dev/null +++ b/docs/source/internal/releases.rst @@ -0,0 +1,99 @@ +================== + Releasing Flake8 +================== + +There is not much that is hard to find about how |Flake8| is released. + +- We use **major** releases (e.g., 2.0.0, 3.0.0, etc.) for big, potentially + backwards incompatible, releases. + +- We use **minor** releases (e.g., 2.1.0, 2.2.0, 3.1.0, 3.2.0, etc.) for + releases that contain features and dependency version changes. + +- We use **patch** releases (e.g., 2.1.1, 2.1.2, 3.0.1, 3.0.10, etc.) for + releases that contain *only* bug fixes. + +In this sense we follow semantic versioning. But we follow it as more of a set +of guidelines. We're also not perfect, so we may make mistakes, and that's +fine. + + +Major Releases +============== + +Major releases are often associated with backwards incompatibility. |Flake8| +hopes to avoid those, but will occasionally need them. + +Historically, |Flake8| has generated major releases for: + +- Unvendoring dependencies (2.0) + +- Large scale refactoring (2.0, 3.0) + +- Subtly breaking CLI changes (3.0) + +- Breaking changes to its plugin interface (3.0) + +Major releases can also contain: + +- Bug fixes (which may have backwards incompatible solutions) + +- New features + +- Dependency changes + + +Minor Releases +============== + +Minor releases often have new features in them, which we define roughly as: + +- New command-line flags + +- New behaviour that does not break backwards compatibility + +- New errors detected by dependencies, e.g., by raising the upper limit on + PyFlakes we introduce F405 + +- Bug fixes + + +Patch Releases +============== + +Patch releases should only ever have bug fixes in them. + +We do not update dependency constraints in patch releases. If you do not +install |Flake8| from PyPI, there is a chance that your packager is using +different requirements. Some downstream redistributors have been known to +force a new version of PyFlakes, pep8/PyCodestyle, or McCabe into place. +Occasionally this will cause breakage when using |Flake8|. There is little +we can do to help you in those cases. + + +Process +======= + +To prepare a release, we create a file in :file:`docs/source/releases/` named: +``{{ release_number }}.rst`` (e.g., ``3.0.0.rst``). We note bug fixes, +improvements, and dependency version changes as well as other items of note +for users. + +Before releasing, the following tox test environments must pass: + +- Python 2.7 (a.k.a., ``tox -e py27``) + +- Python 3.4 (a.k.a., ``tox -e py34``) + +- Python 3.5 (a.k.a., ``tox -e py35``) + +- PyPy (a.k.a., ``tox -e pypy``) + +- Linters (a.k.a., ``tox -e linters``) + +We tag the most recent commit that passes those items and contains our release +notes. + +Finally, we run ``tox -e release`` to build source distributions (e.g., +``flake8-3.0.0.tar.gz``), universal wheels, and upload them to PyPI with +Twine. diff --git a/docs/source/internal/utils.rst b/docs/source/internal/utils.rst new file mode 100644 index 0000000..1b2bb1c --- /dev/null +++ b/docs/source/internal/utils.rst @@ -0,0 +1,127 @@ +=================== + Utility Functions +=================== + +|Flake8| has a few utility functions that it uses internally. + +.. warning:: + + As should be implied by where these are documented, these are all + **internal** utility functions. Their signatures and return types + may change between releases without notice. + + Bugs reported about these **internal** functions will be closed + immediately. + + If functions are needed by plugin developers, they may be requested + in the bug tracker and after careful consideration they *may* be added + to the *documented* stable API. + +.. autofunction:: flake8.utils.parse_comma_separated_list + +:func:`~flake8.utils.parse_comma_separated_list` takes either a string like + +.. code-block:: python + + "E121,W123,F904" + "E121,\nW123,\nF804" + "E121,\n\tW123,\n\tF804" + +Or it will take a list of strings (potentially with whitespace) such as + +.. code-block:: python + + [" E121\n", "\t\nW123 ", "\n\tF904\n "] + +And converts it to a list that looks as follows + +.. code-block:: python + + ["E121", "W123", "F904"] + +This function helps normalize any kind of comma-separated input you or |Flake8| +might receive. This is most helpful when taking advantage of |Flake8|'s +additional parameters to :class:`~flake8.options.manager.Option`. + +.. autofunction:: flake8.utils.normalize_path + +This utility takes a string that represents a path and returns the absolute +path if the string has a ``/`` in it. It also removes trailing ``/``\ s. + +.. autofunction:: flake8.utils.normalize_paths + +This function utilizes :func:`~flake8.utils.parse_comma_separated_list` and +:func:`~flake8.utils.normalize_path` to normalize it's input to a list of +strings that should be paths. + +.. autofunction:: flake8.utils.stdin_get_value + +This function retrieves and caches the value provided on ``sys.stdin``. This +allows plugins to use this to retrieve ``stdin`` if necessary. + +.. autofunction:: flake8.utils.is_windows + +This provides a convenient and explicitly named function that checks if we are +currently running on a Windows (or ``nt``) operating system. + +.. autofunction:: flake8.utils.can_run_multiprocessing_on_windows + +This provides a separate and distinct check from +:func:`~flake8.utils.is_windows` that allows us to check if the version of +Python we're using can actually use multiprocessing on Windows. + +.. autofunction:: flake8.utils.is_using_stdin + +Another helpful function that is named only to be explicit given it is a very +trivial check, this checks if the user specified ``-`` in their arguments to +|Flake8| to indicate we should read from stdin. + +.. autofunction:: flake8.utils.filenames_from + +When provided an argument to |Flake8|, we need to be able to traverse +directories in a convenient manner. For example, if someone runs + +.. code:: + + $ flake8 flake8/ + +Then they want us to check all of the files in the directory ``flake8/``. This +function will handle that while also handling the case where they specify a +file like: + +.. code:: + + $ flake8 flake8/__init__.py + + +.. autofunction:: flake8.utils.fnmatch + +The standard library's :func:`fnmatch.fnmatch` is excellent at deciding if a +filename matches a single pattern. In our use case, however, we typically have +a list of patterns and want to know if the filename matches any of them. This +function abstracts that logic away with a little extra logic. + +.. autofunction:: flake8.utils.parameters_for + +|Flake8| analyzes the parameters to plugins to determine what input they are +expecting. Plugins may expect one of the following: + +- ``physical_line`` to receive the line as it appears in the file + +- ``logical_line`` to receive the logical line (not as it appears in the file) + +- ``tree`` to receive the abstract syntax tree (AST) for the file + +We also analyze the rest of the parameters to provide more detail to the +plugin. This function will return the parameters in a consistent way across +versions of Python and will handle both classes and functions that are used as +plugins. Further, if the plugin is a class, it will strip the ``self`` +argument so we can check the parameters of the plugin consistently. + +.. autofunction:: flake8.utils.parse_unified_diff + +To handle usage of :option:`flake8 --diff`, |Flake8| needs to be able +to parse the name of the files in the diff as well as the ranges indicated the +sections that have been changed. This function either accepts the diff as an +argument or reads the diff from standard-in. It then returns a dictionary with +filenames as the keys and sets of line numbers as the value. diff --git a/docs/source/internal/writing-documentation.rst b/docs/source/internal/writing-documentation.rst new file mode 100644 index 0000000..ee37517 --- /dev/null +++ b/docs/source/internal/writing-documentation.rst @@ -0,0 +1,183 @@ +.. _docs-style: + +================================== + Writing Documentation for Flake8 +================================== + +The maintainers of |Flake8| believe strongly in benefit of style guides. +Hence, for all contributors who wish to work on our documentation, we've +put together a loose set of guidelines and best practices when adding to +our documentation. + + +View the docs locally before submitting +======================================= + +You can and should generate the docs locally before you submit a pull request +with your changes. You can build the docs by running: + +.. prompt:: bash + + tox -e docs + +From the directory containing the ``tox.ini`` file (which also contains the +``docs/`` directory that this file lives in). + +.. note:: + + If the docs don't build locally, they will not build in our continuous + integration system. We will generally not merge any pull request that + fails continuous integration. + + +Run the docs linter tests before submitting +=========================================== + +You should run the ``doc8`` linter job before you're ready to commit and fix +any errors found. + + +Capitalize Flake8 in prose +========================== + +We believe that by capitalizing |Flake8| in prose, we can help reduce +confusion between the command-line usage of ``flake8`` and the project. + +We also have defined a global replacement ``|Flake8|`` that should be used +and will replace each instance with ``:program:`Flake8```. + + +Use the prompt directive for command-line examples +================================================== + +When documenting something on the command-line, use the ``.. prompt::`` +directive to make it easier for users to copy and paste into their terminal. + +Example: + +.. code-block:: restructuredtext + + .. prompt:: bash + + flake8 --select E123,W503 dir/ + flake8 --ignore E24,W504 dir + + +Wrap lines around 79 characters +=============================== + +We use a maximum line-length in our documentation that is similar to the +default in |Flake8|. Please wrap lines at 79 characters (or less). + + +Use two new-lines before new sections +===================================== + +After the final paragraph of a section and before the next section title, +use two new-lines to separate them. This makes reading the plain-text +document a little nicer. Sphinx ignores these when rendering so they have +no semantic meaning. + +Example: + +.. code-block:: restructuredtext + + Section Header + ============== + + Paragraph. + + + Next Section Header + =================== + + Paragraph. + + +Surround document titles with equal symbols +=========================================== + +To indicate the title of a document, we place an equal number of ``=`` symbols +on the lines before and after the title. For example: + +.. code-block:: restructuredtext + + ================================== + Writing Documentation for Flake8 + ================================== + +Note also that we "center" the title by adding a leading space and having +extra ``=`` symbols at the end of those lines. + + +Use the option template for new options +======================================= + +All of |Flake8|'s command-line options are documented in the User Guide. Each +option is documented individually using the ``.. option::`` directive provided +by Sphinx. At the top of the document, in a reStructuredText comment, is a +template that should be copied and pasted into place when documening new +options. + +.. note:: + + The ordering of the options page is the order that options are printed + in the output of: + + .. prompt:: bash + + flake8 --help + + Please insert your option documentation according to that order. + + +Use anchors for easy reference linking +====================================== + +Use link anchors to allow for other areas of the documentation to use the +``:ref:`` role for intralinking documentation. Example: + +.. code-block:: restructuredtext + + .. _use-anchors: + + Use anchors for easy reference linking + ====================================== + +.. code-block:: restructuredtext + + Somewhere in this paragraph we will :ref:`reference anchors + <use-anchors>`. + +.. note:: + + You do not need to provide custom text for the ``:ref:`` if the title of + the section has a title that is sufficient. + + +Keep your audience in mind +========================== + +|Flake8|'s documentation has three distinct (but not separate) audiences: + +#. Users + +#. Plugin Developers + +#. Flake8 Developers and Contributors + +At the moment, you're one of the third group (because you're contributing +or thinking of contributing). + +Consider that most Users aren't very interested in the internal working of +|Flake8|. When writing for Users, focus on how to do something or the +behaviour of a certain piece of configuration or invocation. + +Plugin developers will only care about the internals of |Flake8| as much as +they will have to interact with that. Keep discussions of internal to the +mininmum required. + +Finally, Flake8 Developers and Contributors need to know how everything fits +together. We don't need detail about every line of code, but cogent +explanations and design specifications will help future developers understand +the Hows and Whys of |Flake8|'s internal design. diff --git a/docs/source/plugin-development/.keep b/docs/source/plugin-development/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/source/plugin-development/.keep diff --git a/docs/source/plugin-development/cross-compatibility.rst b/docs/source/plugin-development/cross-compatibility.rst new file mode 100644 index 0000000..1aa45e3 --- /dev/null +++ b/docs/source/plugin-development/cross-compatibility.rst @@ -0,0 +1,150 @@ +==================================== + Writing Plugins For Flake8 2 and 3 +==================================== + +Plugins have existed for |Flake8| 2.x for a few years. There are a number of +these on PyPI already. While it did not seem reasonable for |Flake8| to attempt +to provide a backwards compatible shim for them, we did decide to try to +document the easiest way to write a plugin that's compatible across both +versions. + +.. note:: + + If your plugin does not register options, it *should* Just Work. + +The **only** breaking change in |Flake8| 3.0 is the fact that we no longer +check the option parser for a list of strings to parse from a config file. On +|Flake8| 2.x, to have an option parsed from the configuration files that +|Flake8| finds and parses you would have to do something like: + +.. code-block:: python + + parser.add_option('-X', '--example-flag', type='string', + help='...') + parser.config_options.append('example-flag') + +For |Flake8| 3.0, we have added *three* arguments to the +:meth:`~flake8.options.manager.OptionManager.add_option` method you will call +on the parser you receive: + +- ``parse_from_config`` which expects ``True`` or ``False`` + + When ``True``, |Flake8| will parse the option from the config files |Flake8| + finds. + +- ``comma_separated_list`` which expects ``True`` or ``False`` + + When ``True``, |Flake8| will split the string intelligently and handle + extra whitespace. The parsed value will be a list. + +- ``normalize_paths`` which expects ``True`` or ``False`` + + When ``True``, |Flake8| will: + + * remove trailing path separators (i.e., ``os.path.sep``) + + * return the absolute path for values that have the separator in them + +All three of these options can be combined or used separately. + + +Parsing Options from Configuration Files +======================================== + +The example from |Flake8| 2.x now looks like: + +.. code-block:: python + + parser.add_option('-X', '--example-flag', type='string', + parse_from_config=True, + help='...') + + +Parsing Comma-Separated Lists +============================= + +Now let's imagine that the option we want to add is expecting a comma-separatd +list of values from the user (e.g., ``--select E123,W503,F405``). |Flake8| 2.x +often forced users to parse these lists themselves since pep8 special-cased +certain flags and left others on their own. |Flake8| 3.0 adds +``comma_separated_list`` so that the parsed option is already a list for +plugin authors. When combined with ``parse_from_config`` this means that users +can also do something like: + +.. code-block:: ini + + example-flag = + first, + second, + third, + fourth, + fifth + +And |Flake8| will just return the list: + +.. code-block:: python + + ["first", "second", "third", "fourth", "fifth"] + + +Normalizing Values that Are Paths +================================= + +Finally, let's imagine that our new option wants a path or list of paths. To +ensure that these paths are semi-normalized (the way |Flake8| 2.x used to +work) we need only pass ``normalize_paths=True``. If you have specified +``comma_separated_list=True`` then this will parse the value as a list of +paths that have been normalized. Otherwise, this will parse the value +as a single path. + + +Option Handling on Flake8 2 and 3 +================================= + +So, in conclusion, we can now write our plugin that relies on registering +options with |Flake8| and have it work on |Flake8| 2.x and 3.x. + +.. code-block:: python + + option_args = ('-X', '--example-flag') + option_kwargs = { + 'type': 'string', + 'parse_from_config': True, + 'help': '...', + } + try: + # Flake8 3.x registration + parser.add_option(*option_args, **option_kwargs) + except TypeError: + # Flake8 2.x registration + parse_from_config = option_kwargs.pop('parse_from_config', False) + parser.add_option(*option_args, **option_kwargs) + if parse_from_config: + parser.config_options.append(option_args[-1].lstrip('-')) + + +Or, you can write a tiny helper function: + +.. code-block:: python + + def register_opt(parser, *args, **kwargs): + try: + # Flake8 3.x registration + parser.add_option(*args, **kwargs) + except TypeError: + # Flake8 2.x registration + parse_from_config = kwargs.pop('parse_from_config', False) + parser.add_option(*args, **kwargs) + if parse_from_config: + parser.config_options.append(args[-1].lstrip('-')) + +.. code-block:: python + + @classmethod + def register_options(cls, parser): + register_opt(parser, '-X', '--example-flag', type='string', + parse_from_config=True, help='...') + +The transition period is admittedly not fantastic, but we believe that this +is a worthwhile change for plugin developers going forward. We also hope to +help with the transition phase for as many plugins as we can manage. diff --git a/docs/source/plugin-development/formatters.rst b/docs/source/plugin-development/formatters.rst new file mode 100644 index 0000000..480ada0 --- /dev/null +++ b/docs/source/plugin-development/formatters.rst @@ -0,0 +1,54 @@ +.. _formatting-plugins: + +=========================================== + Developing a Formatting Plugin for Flake8 +=========================================== + +|Flake8| allowed for custom formatting plugins in version +3.0.0. Let's write a plugin together: + +.. code-block:: python + + from flake8.formatting import base + + + class Example(base.BaseFormatter): + """Flake8's example formatter.""" + + pass + +We notice, as soon as we start, that we inherit from |Flake8|'s +:class:`~flake8.formatting.base.BaseFormatter` class. If we follow the +:ref:`instructions to register a plugin <register-a-plugin>` and try to use +our example formatter, e.g., ``flake8 --format=example`` then +|Flake8| will fail because we did not implement the ``format`` method. +Let's do that next. + +.. code-block:: python + + class Example(base.BaseFormatter): + """Flake8's example formatter.""" + + def format(self, error): + return 'Example formatter: {0!r}'.format(error) + +With that we're done. Obviously this isn't a very useful formatter, but it +should highlight the simplicitly of creating a formatter with Flake8. If we +wanted to instead create a formatter that aggregated the results and returned +XML, JSON, or subunit we could also do that. |Flake8| interacts with the +formatter in two ways: + +#. It creates the formatter and provides it the options parsed from the + configuration files and command-line + +#. It uses the instance of the formatter and calls ``handle`` with the error. + +By default :meth:`flake8.formatting.base.BaseFormatter.handle` simply calls +the ``format`` method and then ``write``. Any extra handling you wish to do +for formatting purposes should override the ``handle`` method. + +API Documentation +================= + +.. autoclass:: flake8.formatting.base.BaseFormatter + :members: diff --git a/docs/source/plugin-development/index.rst b/docs/source/plugin-development/index.rst new file mode 100644 index 0000000..c3efb1d --- /dev/null +++ b/docs/source/plugin-development/index.rst @@ -0,0 +1,56 @@ +============================ + Writing Plugins for Flake8 +============================ + +Since |Flake8| 2.0, the |Flake8| tool has allowed for extensions and custom +plugins. In |Flake8| 3.0, we're expanding that ability to customize and +extend **and** we're attempting to thoroughly document it. Some of the +documentation in this section may reference third-party documentation to +reduce duplication and to point you, the developer, towards the authoritative +documentation for those pieces. + +Getting Started +=============== + +To get started writing a |Flake8| :term:`plugin` you first need: + +- An idea for a plugin + +- An available package name on PyPI + +- One or more versions of Python installed + +- A text editor or IDE of some kind + +- An idea of what *kind* of plugin you want to build: + + * Formatter + + * Check + +Once you've gathered these things, you can get started. + +All plugins for |Flake8| must be registered via `entry points`_. In this +section we cover: + +- How to register your plugin so |Flake8| can find it + +- How to make |Flake8| provide your check plugin with information (via + command-line flags, function/class parameters, etc.) + +- How to make a formatter plugin + +- How to write your check plugin so that it works with |Flake8| 2.x and 3.x + +.. toctree:: + :caption: Plugin Developer Documentation + :maxdepth: 2 + + registering-plugins + plugin-parameters + formatters + cross-compatibility + + +.. _entry points: + https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points diff --git a/docs/source/plugin-development/plugin-parameters.rst b/docs/source/plugin-development/plugin-parameters.rst new file mode 100644 index 0000000..527950c --- /dev/null +++ b/docs/source/plugin-development/plugin-parameters.rst @@ -0,0 +1,163 @@ +.. _plugin-parameters: + +========================================== + Receiving Information For A Check Plugin +========================================== + +Plugins to |Flake8| have a great deal of information that they can request +from a :class:`~flake8.processor.FileProcessor` instance. Historically, +|Flake8| has supported two types of plugins: + +#. classes that accept parsed abstract syntax trees (ASTs) + +#. functions that accept a range of arguments + +|Flake8| now does not distinguish between the two types of plugins. Any plugin +can accept either an AST or a range of arguments. Further, any plugin that has +certain callable attributes can also register options and receive parsed +options. + + +Indicating Desired Data +======================= + +|Flake8| inspects the plugin's signature to determine what parameters it +expects using :func:`flake8.utils.parameters_for`. +:attr:`flake8.plugins.manager.Plugin.parameters` caches the values so that +each plugin makes that fairly expensive call once per plugin. When processing +a file, a plugin can ask for any of the following: + +- :attr:`~flake8.processor.FileProcessor.blank_before` +- :attr:`~flake8.processor.FileProcessor.blank_lines` +- :attr:`~flake8.processor.FileProcessor.checker_state` +- :attr:`~flake8.processor.FileProcessor.indect_char` +- :attr:`~flake8.processor.FileProcessor.indent_level` +- :attr:`~flake8.processor.FileProcessor.line_number` +- :attr:`~flake8.processor.FileProcessor.logical_line` +- :attr:`~flake8.processor.FileProcessor.max_line_length` +- :attr:`~flake8.processor.FileProcessor.multiline` +- :attr:`~flake8.processor.FileProcessor.noqa` +- :attr:`~flake8.processor.FileProcessor.previous_indent_level` +- :attr:`~flake8.processor.FileProcessor.previous_logical` +- :attr:`~flake8.processor.FileProcessor.tokens` +- :attr:`~flake8.processor.FileProcessor.total_lines` +- :attr:`~flake8.processor.FileProcessor.verbose` + +Alternatively, a plugin can accept ``tree`` and ``filename``. +``tree`` will be a parsed abstract syntax tree that will be used by plugins +like PyFlakes and McCabe. + + +Registering Options +=================== + +Any plugin that has callable attributes ``provide_options`` and +``register_options`` can parse option information and register new options. + +Your ``register_options`` function should expect to receive an instance of +|OptionManager|. An |OptionManager| instance behaves very similarly to +:class:`optparse.OptionParser`. It, however, uses the layer that |Flake8| has +developed on top of :mod:`optparse` to also handle configuration file parsing. +:meth:`~flake8.options.manager.OptionManager.add_option` creates an |Option| +which accepts the same parameters as :mod:`optparse` as well as three extra +boolean parameters: + +- ``parse_from_config`` + + The command-line option should also be parsed from config files discovered + by |Flake8|. + + .. note:: + + This takes the place of appending strings to a list on the + :class:`optparse.OptionParser`. + +- ``comma_separated_list`` + + The value provided to this option is a comma-separated list. After parsing + the value, it should be further broken up into a list. This also allows us + to handle values like: + + .. code:: + + E123,E124, + E125, + E126 + +- ``normalize_paths`` + + The value provided to this option is a path. It should be normalized to be + an absolute path. This can be combined with ``comma_separated_list`` to + allow a comma-separated list of paths. + +Each of these options works individually or can be combined. Let's look at a +couple examples from |Flake8|. In each example, we will have +``option_manager`` which is an instance of |OptionManager|. + +.. code-block:: python + + option_manager.add_option( + '--max-line-length', type='int', metavar='n', + default=defaults.MAX_LINE_LENGTH, parse_from_config=True, + help='Maximum allowed line length for the entirety of this run. ' + '(Default: %default)', + ) + +Here we are adding the ``--max-line-length`` command-line option which is +always an integer and will be parsed from the configuration file. Since we +provide a default, we take advantage of :mod:`optparse`\ 's willingness to +display that in the help text with ``%default``. + +.. code-block:: python + + option_manager.add_option( + '--select', metavar='errors', default='', + parse_from_config=True, comma_separated_list=True, + help='Comma-separated list of errors and warnings to enable.' + ' For example, ``--select=E4,E51,W234``. (Default: %default)', + ) + +In adding the ``--select`` command-line option, we're also indicating to the +|OptionManager| that we want the value parsed from the config files and parsed +as a comma-separated list. + +.. code-block:: python + + option_manager.add_option( + '--exclude', metavar='patterns', default=defaults.EXCLUDE, + comma_separated_list=True, parse_from_config=True, + normalize_paths=True, + help='Comma-separated list of files or directories to exclude.' + '(Default: %default)', + ) + +Finally, we show an option that uses all three extra flags. Values from +``--exclude`` will be parsed from the config, converted from a comma-separated +list, and then each item will be normalized. + +For information about other parameters to +:meth:`~flake8.options.manager.OptionManager.add_option` refer to the +documentation of :mod:`optparse`. + + +Accessing Parsed Options +======================== + +When a plugin has a callable ``provide_options`` attribute, |Flake8| will call +it and attempt to provide the |OptionManager| instance, the parsed options +which will be an instance of :class:`optparse.Values`, and the extra arguments +that were not parsed by the |OptionManager|. If that fails, we will just pass +the :class:`optparse.Values`. In other words, your ``provide_options`` +callable will have one of the following signatures: + +.. code-block:: python + + def provide_options(option_manager, options, args): + pass + # or + def provide_options(options): + pass + +.. substitutions +.. |OptionManager| replace:: :class:`~flake8.options.manager.OptionManager` +.. |Option| replace:: :class:`~flake8.options.manager.Option` diff --git a/docs/source/plugin-development/registering-plugins.rst b/docs/source/plugin-development/registering-plugins.rst new file mode 100644 index 0000000..5d01f99 --- /dev/null +++ b/docs/source/plugin-development/registering-plugins.rst @@ -0,0 +1,115 @@ +.. _register-a-plugin: + +================================== + Registering a Plugin with Flake8 +================================== + +To register any kind of plugin with |Flake8|, you need: + +#. A way to install the plugin (whether it is packaged on its own or + as part of something else). In this section, we will use a ``setup.py`` + written for an example plugin. + +#. A name for your plugin that will (ideally) be unique. + +#. A somewhat recent version of setuptools (newer than 0.7.0 but preferably as + recent as you can attain). + +|Flake8| relies on functionality provided by setuptools called +`Entry Points`_. These allow any package to register a plugin with |Flake8| +via that package's ``setup.py`` file. + +Let's presume that we already have our plugin written and it's in a module +called ``flake8_example``. We might have a ``setup.py`` that looks something +like: + +.. code-block:: python + + from __future__ import with_statement + import setuptools + + requires = [ + "flake8 > 3.0.0", + ] + + flake8_entry_point = # ... + + setuptools.setup( + name="flake8_example", + license="MIT", + version="0.1.0", + description="our extension to flake8", + author="Me", + author_email="example@example.com", + url="https://gitlab.com/me/flake8_example", + packages=[ + "flake8_example", + ], + install_requires=requires, + entry_points={ + flake8_entry_point: [ + 'X = flake8_example:ExamplePlugin', + ], + }, + classifiers=[ + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 3", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Quality Assurance", + ], + ) + +Note specifically these lines: + +.. code-block:: python + + flake8_entry_point = # ... + + setuptools.setup( + # snip ... + entry_points={ + flake8_entry_point: [ + 'X = flake8_example:ExamplePlugin', + ], + }, + # snip ... + ) + +We tell setuptools to register our entry point "X" inside the specific +grouping of entry-points that flake8 should look in. + +|Flake8| presently looks at three groups: + +- ``flake8.extension`` + +- ``flake8.listen`` + +- ``flake8.report`` + +If your plugin is one that adds checks to |Flake8|, you will use +``flake8.extension``. If your plugin automatically fixes errors in code, you +will use ``flake8.listen``. Finally, if your plugin performs extra report +handling (formatting, filtering, etc.) it will use ``flake8.report``. + +If our ``ExamplePlugin`` is something that adds checks, our code would look +like: + +.. code-block:: python + + setuptools.setup( + # snip ... + entry_points={ + 'flake8.extension': [ + 'X = flake8_example:ExamplePlugin', + ], + }, + # snip ... + ) + + +.. _Entry Points: + https://pythonhosted.org/setuptools/pkg_resources.html#entry-points diff --git a/docs/source/release-notes/0.6.0.rst b/docs/source/release-notes/0.6.0.rst new file mode 100644 index 0000000..16590fa --- /dev/null +++ b/docs/source/release-notes/0.6.0.rst @@ -0,0 +1,4 @@ +0.6 - 2010-02-15 +---------------- + +- Fix the McCabe metric on some loops diff --git a/docs/source/release-notes/0.7.0.rst b/docs/source/release-notes/0.7.0.rst new file mode 100644 index 0000000..f842060 --- /dev/null +++ b/docs/source/release-notes/0.7.0.rst @@ -0,0 +1,6 @@ +0.7 - 2010-02-18 +---------------- + +- Fix pep8 initialization when run through Hg +- Make pep8 short options work when run through the command line +- Skip duplicates when controlling files via Hg diff --git a/docs/source/release-notes/0.8.0.rst b/docs/source/release-notes/0.8.0.rst new file mode 100644 index 0000000..66b90b5 --- /dev/null +++ b/docs/source/release-notes/0.8.0.rst @@ -0,0 +1,5 @@ +0.8 - 2011-02-27 +---------------- + +- fixed hg hook +- discard unexisting files on hook check diff --git a/docs/source/release-notes/0.9.0.rst b/docs/source/release-notes/0.9.0.rst new file mode 100644 index 0000000..be6c41b --- /dev/null +++ b/docs/source/release-notes/0.9.0.rst @@ -0,0 +1,5 @@ +0.9 - 2011-11-09 +---------------- + +- update pep8 version to 0.6.1 +- mccabe check: gracefully handle compile failure diff --git a/docs/source/release-notes/1.0.0.rst b/docs/source/release-notes/1.0.0.rst new file mode 100644 index 0000000..6882a43 --- /dev/null +++ b/docs/source/release-notes/1.0.0.rst @@ -0,0 +1,5 @@ +1.0 - 2011-11-29 +---------------- + +- Deactivates by default the complexity checker +- Introduces the complexity option in the HG hook and the command line. diff --git a/docs/source/release-notes/1.1.0.rst b/docs/source/release-notes/1.1.0.rst new file mode 100644 index 0000000..dadbe2e --- /dev/null +++ b/docs/source/release-notes/1.1.0.rst @@ -0,0 +1,8 @@ +1.1 - 2012-02-14 +---------------- + +- fixed the value returned by --version +- allow the flake8: header to be more generic +- fixed the "hg hook raises 'physical lines'" bug +- allow three argument form of raise +- now uses setuptools if available, for 'develop' command diff --git a/docs/source/release-notes/1.2.0.rst b/docs/source/release-notes/1.2.0.rst new file mode 100644 index 0000000..de86237 --- /dev/null +++ b/docs/source/release-notes/1.2.0.rst @@ -0,0 +1,6 @@ +1.2 - 2012-02-12 +---------------- + +- added a git hook +- now Python 3 compatible +- mccabe and pyflakes have warning codes like pep8 now diff --git a/docs/source/release-notes/1.3.0.rst b/docs/source/release-notes/1.3.0.rst new file mode 100644 index 0000000..0ddfe78 --- /dev/null +++ b/docs/source/release-notes/1.3.0.rst @@ -0,0 +1,4 @@ +1.3 - 2012-03-12 +---------------- + +- fixed false W402 warning on exception blocks. diff --git a/docs/source/release-notes/1.3.1.rst b/docs/source/release-notes/1.3.1.rst new file mode 100644 index 0000000..b2e34ee --- /dev/null +++ b/docs/source/release-notes/1.3.1.rst @@ -0,0 +1,4 @@ +1.3.1 - 2012-05-19 +------------------ + +- fixed support for Python 2.5 diff --git a/docs/source/release-notes/1.4.0.rst b/docs/source/release-notes/1.4.0.rst new file mode 100644 index 0000000..51f34cf --- /dev/null +++ b/docs/source/release-notes/1.4.0.rst @@ -0,0 +1,5 @@ +1.4 - 2012-07-12 +---------------- + +- git_hook: Only check staged changes for compliance +- use pep8 1.2 diff --git a/docs/source/release-notes/1.5.0.rst b/docs/source/release-notes/1.5.0.rst new file mode 100644 index 0000000..cd0a88d --- /dev/null +++ b/docs/source/release-notes/1.5.0.rst @@ -0,0 +1,9 @@ +1.5 - 2012-10-13 +---------------- + +- fixed the stdin +- make sure mccabe catches the syntax errors as warnings +- pep8 upgrade +- added max_line_length default value +- added Flake8Command and entry points if setuptools is around +- using the setuptools console wrapper when available diff --git a/docs/source/release-notes/1.6.0.rst b/docs/source/release-notes/1.6.0.rst new file mode 100644 index 0000000..658be2f --- /dev/null +++ b/docs/source/release-notes/1.6.0.rst @@ -0,0 +1,14 @@ +1.6 - 2012-11-16 +---------------- + +- changed the signatures of the ``check_file`` function in flake8/run.py, + ``skip_warning`` in flake8/util.py and the ``check``, ``checkPath`` + functions in flake8/pyflakes.py. +- fix ``--exclude`` and ``--ignore`` command flags (#14, #19) +- fix the git hook that wasn't catching files not already added to the index + (#29) +- pre-emptively includes the addition to pep8 to ignore certain lines. + Add ``# nopep8`` to the end of a line to ignore it. (#37) +- ``check_file`` can now be used without any special prior setup (#21) +- unpacking exceptions will no longer cause an exception (#20) +- fixed crash on non-existent file (#38) diff --git a/docs/source/release-notes/1.6.1.rst b/docs/source/release-notes/1.6.1.rst new file mode 100644 index 0000000..194dfa5 --- /dev/null +++ b/docs/source/release-notes/1.6.1.rst @@ -0,0 +1,7 @@ +1.6.1 - 2012-11-24 +------------------ + +- fixed the mercurial hook, a change from a previous patch was not properly + applied +- fixed an assumption about warnings/error messages that caused an exception + to be thrown when McCabe is used diff --git a/docs/source/release-notes/1.6.2.rst b/docs/source/release-notes/1.6.2.rst new file mode 100644 index 0000000..64633bd --- /dev/null +++ b/docs/source/release-notes/1.6.2.rst @@ -0,0 +1,4 @@ +1.6.2 - 2012-11-25 +------------------ + +- fixed the NameError: global name 'message' is not defined (#46) diff --git a/docs/source/release-notes/1.7.0.rst b/docs/source/release-notes/1.7.0.rst new file mode 100644 index 0000000..a3a4725 --- /dev/null +++ b/docs/source/release-notes/1.7.0.rst @@ -0,0 +1,9 @@ +1.7.0 - 2012-12-21 +------------------ + +- Fixes part of #35: Exception for no WITHITEM being an attribute of Checker + for Python 3.3 +- Support stdin +- Incorporate @phd's builtins pull request +- Fix the git hook +- Update pep8.py to the latest version diff --git a/docs/source/release-notes/2.0.0.rst b/docs/source/release-notes/2.0.0.rst new file mode 100644 index 0000000..4c1ff04 --- /dev/null +++ b/docs/source/release-notes/2.0.0.rst @@ -0,0 +1,13 @@ +2.0.0 - 2013-02-23 +------------------ + +- Pyflakes errors are prefixed by an ``F`` instead of an ``E`` +- McCabe complexity warnings are prefixed by a ``C`` instead of a ``W`` +- Flake8 supports extensions through entry points +- Due to the above support, we **require** setuptools +- We publish the `documentation <https://flake8.readthedocs.org/>`_ +- Fixes #13: pep8, pyflakes and mccabe become external dependencies +- Split run.py into main.py, engine.py and hooks.py for better logic +- Expose our parser for our users +- New feature: Install git and hg hooks automagically +- By relying on pyflakes (0.6.1), we also fixed #45 and #35 diff --git a/docs/source/release-notes/2.1.0.rst b/docs/source/release-notes/2.1.0.rst new file mode 100644 index 0000000..c9e3c60 --- /dev/null +++ b/docs/source/release-notes/2.1.0.rst @@ -0,0 +1,12 @@ +2.1.0 - 2013-10-26 +------------------ + +- Add FLAKE8_LAZY and FLAKE8_IGNORE environment variable support to git and + mercurial hooks +- Force git and mercurial hooks to repsect configuration in setup.cfg +- Only check staged files if that is specified +- Fix hook file permissions +- Fix the git hook on python 3 +- Ignore non-python files when running the git hook +- Ignore .tox directories by default +- Flake8 now reports the column number for PyFlakes messages diff --git a/docs/source/release-notes/2.2.0.rst b/docs/source/release-notes/2.2.0.rst new file mode 100644 index 0000000..357b6d2 --- /dev/null +++ b/docs/source/release-notes/2.2.0.rst @@ -0,0 +1,12 @@ +2.2.0 - 2014-06-22 +------------------ + +- New option ``doctests`` to run Pyflakes checks on doctests too +- New option ``jobs`` to launch multiple jobs in parallel +- Turn on using multiple jobs by default using the CPU count +- Add support for ``python -m flake8`` on Python 2.7 and Python 3 +- Fix Git and Mercurial hooks: issues #88, #133, #148 and #149 +- Fix crashes with Python 3.4 by upgrading dependencies +- Fix traceback when running tests with Python 2.6 +- Fix the setuptools command ``python setup.py flake8`` to read + the project configuration diff --git a/docs/source/release-notes/2.2.1.rst b/docs/source/release-notes/2.2.1.rst new file mode 100644 index 0000000..5575f8f --- /dev/null +++ b/docs/source/release-notes/2.2.1.rst @@ -0,0 +1,5 @@ +2.2.1 - 2014-06-30 +------------------ + +- Turn off multiple jobs by default. To enable automatic use of all CPUs, use + ``--jobs=auto``. Fixes #155 and #154. diff --git a/docs/source/release-notes/2.2.2.rst b/docs/source/release-notes/2.2.2.rst new file mode 100644 index 0000000..8fcff88 --- /dev/null +++ b/docs/source/release-notes/2.2.2.rst @@ -0,0 +1,5 @@ +2.2.2 - 2014-07-04 +------------------ + +- Re-enable multiprocessing by default while fixing the issue Windows users + were seeing. diff --git a/docs/source/release-notes/2.2.3.rst b/docs/source/release-notes/2.2.3.rst new file mode 100644 index 0000000..e7430f0 --- /dev/null +++ b/docs/source/release-notes/2.2.3.rst @@ -0,0 +1,4 @@ +2.2.3 - 2014-08-25 +------------------ + +- Actually turn multiprocessing on by default diff --git a/docs/source/release-notes/2.2.4.rst b/docs/source/release-notes/2.2.4.rst new file mode 100644 index 0000000..2564948 --- /dev/null +++ b/docs/source/release-notes/2.2.4.rst @@ -0,0 +1,20 @@ +2.2.4 - 2014-10-09 +------------------ + +- Fix bugs triggered by turning multiprocessing on by default (again) + + Multiprocessing is forcibly disabled in the following cases: + + - Passing something in via stdin + + - Analyzing a diff + + - Using windows + +- Fix --install-hook when there are no config files present for pep8 or + flake8. + +- Fix how the setuptools command parses excludes in config files + +- Fix how the git hook determines which files to analyze (Thanks Chris + Buccella!) diff --git a/docs/source/release-notes/2.2.5.rst b/docs/source/release-notes/2.2.5.rst new file mode 100644 index 0000000..540278f --- /dev/null +++ b/docs/source/release-notes/2.2.5.rst @@ -0,0 +1,6 @@ +2.2.5 - 2014-10-19 +------------------ + +- Flush standard out when using multiprocessing + +- Make the check for "# flake8: noqa" more strict diff --git a/docs/source/release-notes/2.3.0.rst b/docs/source/release-notes/2.3.0.rst new file mode 100644 index 0000000..120efa9 --- /dev/null +++ b/docs/source/release-notes/2.3.0.rst @@ -0,0 +1,10 @@ +2.3.0 - 2015-01-04 +------------------ + +- **Feature**: Add ``--output-file`` option to specify a file to write to + instead of ``stdout``. + +- **Bug** Fix interleaving of output while using multiprocessing + (`GitLab#17`_) + +.. _GitLab#17: https://gitlab.com/pycqa/flake8/issues/17 diff --git a/docs/source/release-notes/2.4.0.rst b/docs/source/release-notes/2.4.0.rst new file mode 100644 index 0000000..6c470cd --- /dev/null +++ b/docs/source/release-notes/2.4.0.rst @@ -0,0 +1,33 @@ +2.4.0 - 2015-03-07 +------------------ + +- **Bug** Print filenames when using multiprocessing and ``-q`` option. + (`GitLab#31`_) + +- **Bug** Put upper cap on dependencies. The caps for 2.4.0 are: + + - ``pep8 < 1.6`` (Related to `GitLab#35`_) + + - ``mccabe < 0.4`` + + - ``pyflakes < 0.9`` + + See also `GitLab#32`_ + +- **Bug** Files excluded in a config file were not being excluded when flake8 + was run from a git hook. (`GitHub#2`_) + +- **Improvement** Print warnings for users who are providing mutually + exclusive options to flake8. (`GitLab#8`_, `GitLab!18`_) + +- **Feature** Allow git hook configuration to live in ``.git/config``. + See the updated `VCS hooks docs`_ for more details. (`GitLab!20`_) + +.. _GitHub#2: https://github.com/pycqa/flake8/pull/2 +.. _GitLab#8: https://gitlab.com/pycqa/flake8/issues/8 +.. _GitLab#31: https://gitlab.com/pycqa/flake8/issues/31 +.. _GitLab#32: https://gitlab.com/pycqa/flake8/issues/32 +.. _GitLab#35: https://gitlab.com/pycqa/flake8/issues/35 +.. _GitLab!18: https://gitlab.com/pycqa/flake8/merge_requests/18 +.. _GitLab!20: https://gitlab.com/pycqa/flake8/merge_requests/20 +.. _VCS hooks docs: https://flake8.readthedocs.org/en/latest/vcs.html diff --git a/docs/source/release-notes/2.4.1.rst b/docs/source/release-notes/2.4.1.rst new file mode 100644 index 0000000..3448bc4 --- /dev/null +++ b/docs/source/release-notes/2.4.1.rst @@ -0,0 +1,12 @@ +2.4.1 - 2015-05-18 +------------------ + +- **Bug** Do not raise a ``SystemError`` unless there were errors in the + setuptools command. (`GitLab#39`_, `GitLab!23`_) + +- **Bug** Do not verify dependencies of extensions loaded via entry-points. + +- **Improvement** Blacklist versions of pep8 we know are broken + +.. _GitLab#39: https://gitlab.com/pycqa/flake8/issues/39 +.. _GitLab!23: https://gitlab.com/pycqa/flake8/merge_requests/23 diff --git a/docs/source/release-notes/2.5.0.rst b/docs/source/release-notes/2.5.0.rst new file mode 100644 index 0000000..1558fcf --- /dev/null +++ b/docs/source/release-notes/2.5.0.rst @@ -0,0 +1,25 @@ +2.5.0 - 2015-10-26 +------------------ + +- **Improvement** Raise cap on PyFlakes for Python 3.5 support + +- **Improvement** Avoid deprecation warnings when loading extensions + (`GitLab#59`_, `GitLab#90`_) + +- **Improvement** Separate logic to enable "off-by-default" extensions + (`GitLab#67`_) + +- **Bug** Properly parse options to setuptools Flake8 command (`GitLab!41`_) + +- **Bug** Fix exceptions when output on stdout is truncated before Flake8 + finishes writing the output (`GitLab#69`_) + +- **Bug** Fix error on OS X where Flake8 can no longer acquire or create new + semaphores (`GitLab#74`_) + +.. _GitLab!41: https://gitlab.com/pycqa/flake8/merge_requests/41 +.. _GitLab#59: https://gitlab.com/pycqa/flake8/issues/59 +.. _GitLab#67: https://gitlab.com/pycqa/flake8/issues/67 +.. _GitLab#69: https://gitlab.com/pycqa/flake8/issues/69 +.. _GitLab#74: https://gitlab.com/pycqa/flake8/issues/74 +.. _GitLab#90: https://gitlab.com/pycqa/flake8/issues/90 diff --git a/docs/source/release-notes/2.5.1.rst b/docs/source/release-notes/2.5.1.rst new file mode 100644 index 0000000..8a114c8 --- /dev/null +++ b/docs/source/release-notes/2.5.1.rst @@ -0,0 +1,13 @@ +2.5.1 - 2015-12-08 +------------------ + +- **Bug** Properly look for ``.flake8`` in current working directory + (`GitLab#103`_) + +- **Bug** Monkey-patch ``pep8.stdin_get_value`` to cache the actual value in + stdin. This helps plugins relying on the function when run with + multiprocessing. (`GitLab#105`_, `GitLab#107`_) + +.. _GitLab#103: https://gitlab.com/pycqa/flake8/issues/103 +.. _GitLab#105: https://gitlab.com/pycqa/flake8/issues/105 +.. _GitLab#107: https://gitlab.com/pycqa/flake8/issues/107 diff --git a/docs/source/release-notes/2.5.2.rst b/docs/source/release-notes/2.5.2.rst new file mode 100644 index 0000000..a093c9f --- /dev/null +++ b/docs/source/release-notes/2.5.2.rst @@ -0,0 +1,7 @@ +2.5.2 - 2016-01-30 +------------------ + +- **Bug** Parse ``output_file`` and ``enable_extensions`` from config files + +- **Improvement** Raise upper bound on mccabe plugin to allow for version + 0.4.0 diff --git a/docs/source/release-notes/2.5.3.rst b/docs/source/release-notes/2.5.3.rst new file mode 100644 index 0000000..85dbf33 --- /dev/null +++ b/docs/source/release-notes/2.5.3.rst @@ -0,0 +1,5 @@ +2.5.3 - 2016-02-11 +------------------ + +- **Bug** Actually parse ``output_file`` and ``enable_extensions`` from config + files diff --git a/docs/source/release-notes/2.5.4.rst b/docs/source/release-notes/2.5.4.rst new file mode 100644 index 0000000..5ba03ba --- /dev/null +++ b/docs/source/release-notes/2.5.4.rst @@ -0,0 +1,4 @@ +2.5.4 - 2016-02-11 +------------------ + +- **Bug** Missed an attribute rename during the v2.5.3 release. diff --git a/docs/source/release-notes/2.5.5.rst b/docs/source/release-notes/2.5.5.rst new file mode 100644 index 0000000..683cfb6 --- /dev/null +++ b/docs/source/release-notes/2.5.5.rst @@ -0,0 +1,7 @@ +2.5.5 - 2016-06-14 +------------------ + +- **Bug** Fix setuptools integration when parsing config files + +- **Bug** Don't pass the user's config path as the config_file when creating a + StyleGuide diff --git a/docs/source/release-notes/2.6.1.rst b/docs/source/release-notes/2.6.1.rst new file mode 100644 index 0000000..d05bd18 --- /dev/null +++ b/docs/source/release-notes/2.6.1.rst @@ -0,0 +1,6 @@ +2.6.1 - 2016-06-25 +------------------ + +- **Bug** Update the config files to search for to include ``setup.cfg`` and + ``tox.ini``. This was broken in 2.5.5 when we stopped passing + ``config_file`` to our Style Guide diff --git a/docs/source/release-notes/3.0.0.rst b/docs/source/release-notes/3.0.0.rst new file mode 100644 index 0000000..8f13cfe --- /dev/null +++ b/docs/source/release-notes/3.0.0.rst @@ -0,0 +1,42 @@ +3.0.0b1 -- 2016-06-25 +--------------------- + +- Rewrite our documentation from scratch! (http://flake8.pycqa.org) + +- Drop explicit support for Pythons 2.6, 3.2, and 3.3. + +- Remove dependence on pep8/pycodestyle for file processing, plugin + dispatching, and more. We now control all of this while keeping backwards + compatibility. + +- ``--select`` and ``--ignore`` can now both be specified and try to find the + most specific rule from each. For example, if you do ``--select E --ignore + E123`` then we will report everything that starts with ``E`` except for + ``E123``. Previously, you would have had to do ``--ignore E123,F,W`` which + will also still work, but the former should be far more intuitive. + +- Add support for in-line ``# noqa`` comments to specify **only** the error + codes to be ignored, e.g., ``# noqa: E123,W503`` + +- Add entry-point for formatters as well as a base class that new formatters + can inherit from. See the documentation for more details. + +- Add detailed verbose output using the standard library logging module. + +- Enhance our usage of optparse for plugin developers by adding new parameters + to the ``add_option`` that plugins use to register new options. + +- Update ``--install-hook`` to require the name of version control system hook + you wish to install a Flake8. + +- Stop checking sub-directories more than once via the setuptools command + +- When passing a file on standard-in, allow the caller to specify + ``--stdin-display-name`` so the output is properly formatted + +- The Git hook now uses ``sys.executable`` to format the shebang line. + This allows Flake8 to install a hook script from a virtualenv that points to + that virtualenv's Flake8 as opposed to a global one (without the virtualenv + being sourced). + +- When using ``--count``, the output is no longer written to stderr. diff --git a/docs/source/release-notes/index.rst b/docs/source/release-notes/index.rst new file mode 100644 index 0000000..d91324f --- /dev/null +++ b/docs/source/release-notes/index.rst @@ -0,0 +1,41 @@ +=========================== + Release Notes and History +=========================== + +All of the release notes that have been recorded for Flake8 are organized here +with the newest releases first. + +.. toctree:: + 3.0.0 + 2.5.5 + 2.5.4 + 2.5.3 + 2.5.2 + 2.5.1 + 2.5.0 + 2.4.1 + 2.4.0 + 2.3.0 + 2.2.5 + 2.2.4 + 2.2.3 + 2.2.2 + 2.2.1 + 2.2.0 + 2.1.0 + 2.0.0 + 1.7.0 + 1.6.2 + 1.6.1 + 1.6.0 + 1.5.0 + 1.4.0 + 1.3.1 + 1.3.0 + 1.2.0 + 1.1.0 + 1.0.0 + 0.9.0 + 0.8.0 + 0.7.0 + 0.6.0 diff --git a/docs/source/requirements.txt b/docs/source/requirements.txt new file mode 100644 index 0000000..77bd874 --- /dev/null +++ b/docs/source/requirements.txt @@ -0,0 +1,4 @@ +sphinx>=1.3.0 +sphinx_rtd_theme +sphinx-prompt +configparser diff --git a/docs/source/user/.keep b/docs/source/user/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/source/user/.keep diff --git a/docs/source/user/configuration.rst b/docs/source/user/configuration.rst new file mode 100644 index 0000000..439aeae --- /dev/null +++ b/docs/source/user/configuration.rst @@ -0,0 +1,227 @@ +.. _configuration: + +==================== + Configuring Flake8 +==================== + +Once you have learned how to :ref:`invoke <invocation>` |Flake8|, you will soon +want to learn how to configure it so you do not have to specify the same +options every time you use it. + +This section will show you how to make + +.. prompt:: bash + + flake8 + +Remember that you want to specify certain options without writing + +.. prompt:: bash + + flake8 --select E123,W456 --enable-extensions H111 + + +Configuration Locations +======================= + +|Flake8| supports storing its configuration in the following places: + +- Your top-level user directory + +- In your project in one of ``setup.cfg``, ``tox.ini``, or ``.flake8``. + + +"User" Configuration +-------------------- + +|Flake8| allows a user to use "global" configuration file to store preferences. +The user configuration file is expected to be stored somewhere in the user's +"home" directory. + +- On Windows the "home" directory will be something like + ``C:\\Users\sigmavirus24``, a.k.a, ``~\``. + +- On Linux and other Unix like systems (including OS X) we will look in + ``~/``. + +Note that |Flake8| looks for ``~\.flake8`` on Windows and ``~/.config/flake8`` +on Linux and other Unix systems. + +User configuration files use the same syntax as Project Configuration files. +Keep reading to see that syntax. + + +Project Configuration +--------------------- + +|Flake8| is written with the understanding that people organize projects into +sub-directories. Let's take for example |Flake8|'s own project structure + +.. code:: + + flake8 + ├── docs + │ ├── build + │ └── source + │ ├── _static + │ ├── _templates + │ ├── dev + │ ├── internal + │ └── user + ├── flake8 + │ ├── formatting + │ ├── main + │ ├── options + │ └── plugins + └── tests + ├── fixtures + │ └── config_files + ├── integration + └── unit + +In the top-level ``flake8`` directory (which contains ``docs``, ``flake8``, +and ``tests``) there's also ``tox.ini`` and ``setup.cfg`` files. In our case, +we keep our |Flake8| configuration in ``tox.ini``. Regardless of whether you +keep your config in ``.flake8``, ``setup.cfg``, or ``tox.ini`` we expect you +to use INI to configure |Flake8| (since each of these files already uses INI +as a format). This means that any |Flake8| configuration you wish to set needs +to be in the ``flake8`` section, which means it needs to start like so: + +.. code-block:: ini + + [flake8] + +Each command-line option that you want to specify in your config file can +be named in either of two ways: + +#. Using underscores (``_``) instead of hyphens (``-``) + +#. Simply using hyphens (without the leading hyphens) + +.. note:: + + Not every |Flake8| command-line option can be specified in the + configuration file. See :ref:`our list of options <options-list>` to + determine which options will be parsed from the configuration files. + +Let's actually look at |Flake8|'s own configuration section: + +.. code-block:: ini + + [flake8] + ignore = D203 + exclude = .git,__pycache__,docs/source/conf.py,old,build,dist + max-complexity = 10 + +This is equivalent to: + +.. prompt:: bash + + flake8 --ignore D203 \ + --exclude .git,__pycache__,docs/source/conf.py,old,build,dist \ + --max-complexity 10 + +In our case, if we wanted to, we could also do + +.. code-block:: ini + + [flake8] + ignore = D203 + exclude = + .git, + __pycache__, + docs/source/conf.py, + old, + build, + dist + max-complexity = 10 + +This would allow us to add comments for why we're excluding items, e.g., + +.. code-block:: ini + + [flake8] + ignore = D203 + exclude = + # No need to traverse our git directory + .git, + # There's no value in checking cache directories + __pycache__, + # The conf file is mostly autogenerated, ignore it + docs/source/conf.py, + # The old directory contains Flake8 2.0 + old, + # This contains our built documentation + build, + # This contains builds of flake8 that we don't want to check + dist + max-complexity = 10 + +.. note:: + + If you're using Python 2, you will notice that we download the + :mod:`configparser` backport from PyPI. That backport enables us to + support this behaviour on all supported versions of Python. + + Please do **not** open issues about this dependency to |Flake8|. + +.. note:: + + You can also specify ``--max-complexity`` as ``max_complexity = 10``. + +This is also useful if you have a long list of error codes to ignore. Let's +look at a portion of OpenStack's Swift `project configuration`_: + +.. code-block:: ini + + [flake8] + # it's not a bug that we aren't using all of hacking, ignore: + # F812: list comprehension redefines ... + # H101: Use TODO(NAME) + # H202: assertRaises Exception too broad + # H233: Python 3.x incompatible use of print operator + # H301: one import per line + # H306: imports not in alphabetical order (time, os) + # H401: docstring should not start with a space + # H403: multi line docstrings should end on a new line + # H404: multi line docstring should start without a leading new line + # H405: multi line docstring summary not separated with an empty line + # H501: Do not use self.__dict__ for string formatting + ignore = F812,H101,H202,H233,H301,H306,H401,H403,H404,H405,H501 + +They use the comments to describe the check but they could also write this as: + +.. code-block:: ini + + [flake8] + # it's not a bug that we aren't using all of hacking + ignore = + # F812: list comprehension redefines ... + F812, + # H101: Use TODO(NAME) + H101, + # H202: assertRaises Exception too broad + H202, + # H233: Python 3.x incompatible use of print operator + H233, + # H301: one import per line + H301, + # H306: imports not in alphabetical order (time, os) + H306, + # H401: docstring should not start with a space + H401, + # H403: multi line docstrings should end on a new line + H403, + # H404: multi line docstring should start without a leading new line + H404, + # H405: multi line docstring summary not separated with an empty line + H405, + # H501: Do not use self.__dict__ for string formatting + H501 + +Or they could use each comment to describe **why** they've ignored the check. +|Flake8| knows how to parse these lists and will appropriatey handle +these situations. + +.. _project configuration: + https://github.com/openstack/swift/blob/3944d820387f08372c1a29444f4af7d8e6090ae9/tox.ini#L66..L81 diff --git a/docs/source/user/ignoring-errors.rst b/docs/source/user/ignoring-errors.rst new file mode 100644 index 0000000..ff37c4a --- /dev/null +++ b/docs/source/user/ignoring-errors.rst @@ -0,0 +1,90 @@ +============================= + Ignoring Errors with Flake8 +============================= + +By default, |Flake8| has a list of error codes that it ignores. The list used +by a version of |Flake8| may be different than the list used by a different +version. To see the default list, :option:`flake8 --help` will +show the output with the current default list. + + +Changing the Ignore List +======================== + +If we want to change the list of ignored codes for a single run, we can use +:option:`flake8 --ignore` to specify a comma-separated list of codes for a +specific run on the command-line, e.g., + +.. prompt:: bash + + flake8 --ignore=E1,E23,W503 path/to/files/ path/to/more/files/ + +This tells |Flake8| to ignore any error codes starting with ``E1``, ``E23``, +or ``W503`` while it is running. + +.. note:: + + The documentation for :option:`flake8 --ignore` shows examples for how + to change the ignore list in the configuration file. See also + :ref:`configuration` as well for details about how to use configuration + files. + + +In-line Ignoring Errors +======================= + +In some cases, we might not want to ignore an error code (or class of error +codes) for the entirety of our project. Instead, we might want to ignore the +specific error code on a specific line. Let's take for example a line like + +.. code-block:: python + + example = lambda: 'example' + +Sometimes we genuinely need something this simple. We could instead define +a function like we normally would. Note, in some contexts this distracts from +what is actually happening. In those cases, we can also do: + +.. code-block:: python + + example = lambda: 'example' # noqa: E731 + +This will only ignore the error from pycodestyle that checks for lambda +assignments and generates an ``E731``. If there are other errors on the line +then those will be reported. + +.. note:: + + If we ever want to disable |Flake8| respecting ``# noqa`` comments, we can + can refer to :option:`flake8 --disable-noqa`. + +If we instead had more than one error that we wished to ignore, we could +list all of the errors with commas separating them: + +.. code-block:: python + + # noqa: E731,E123 + +Finally, if we have a particularly bad line of code, we can ignore every error +using simply ``# noqa`` with nothing after it. + + +Ignoring Entire Files +===================== + +Imagine a situation where we are adding |Flake8| to a codebase. Let's further +imagine that with the exception of a few particularly bad files, we can add +|Flake8| easily and move on with our lives. There are two ways to ignore the +file: + +#. By explicitly adding it to our list of excluded paths (see: :option:`flake8 + --exclude`) + +#. By adding ``# flake8: noqa`` to the file + +The former is the **recommended** way of ignoring entire files. By using our +exclude list, we can include it in our configuration file and have one central +place to find what files aren't included in |Flake8| checks. The latter has the +benefit that when we run |Flake8| with :option:`flake8 --disable-noqa` all of +the errors in that file will show up without having to modify our +configuration. Both exist so we can choose which is better for us. diff --git a/docs/source/user/index.rst b/docs/source/user/index.rst new file mode 100644 index 0000000..0df911e --- /dev/null +++ b/docs/source/user/index.rst @@ -0,0 +1,33 @@ +============== + Using Flake8 +============== + +|Flake8| can be used in many ways. A few: + +- invoked on the command-line + +- invoked via Python + +- called by Git or Mercurial on or around committing + +This guide will cover all of these and the nuances for using |Flake8|. + +.. note:: + + This portion of |Flake8|'s documentation does not cover installation. See + the :ref:`installation-guide` section for how to install |Flake8|. + +.. toctree:: + :maxdepth: 2 + + invocation + configuration + options + ignoring-errors + using-plugins + python-api + +.. config files +.. command-line tutorial +.. VCS usage +.. installing and using plugins diff --git a/docs/source/user/invocation.rst b/docs/source/user/invocation.rst new file mode 100644 index 0000000..383e93a --- /dev/null +++ b/docs/source/user/invocation.rst @@ -0,0 +1,144 @@ +.. _invocation: + +================= + Invoking Flake8 +================= + +Once you have :ref:`installed <installation-guide>` |Flake8|, you can begin +using it. Most of the time, you will be able to generically invoke |Flake8| +like so: + +.. prompt:: bash + + flake8 ... + +Where you simply allow the shell running in your terminal to locate |Flake8|. +In some cases, though, you may have installed |Flake8| for multiple versions +of Python (e.g., Python 2.7 and Python 3.5) and you need to call a specific +version. In that case, you will have much better results using: + +.. prompt:: bash + + python2.7 -m flake8 + +Or + +.. prompt:: bash + + python3.5 -m flake8 + +Since that will tell the correct version of Python to run |Flake8|. + +.. note:: + + Installing |Flake8| once will not install it on both Python 2.7 and + Python 3.5. It will only install it for the version of Python that + is running pip. + +It is also possible to specify command-line options directly to |Flake8|: + +.. prompt:: bash + + flake8 --select E123 + +Or + +.. prompt:: bash + + python<version> -m flake8 --select E123 + +.. note:: + + This is the last time we will show both versions of an invocation. + From now on, we'll simply use ``flake8`` and assume that the user + knows they can instead use ``python<version> -m flake8`` instead. + +It's also possible to narrow what |Flake8| will try to check by specifying +exactly the paths and directories you want it to check. Let's assume that +we have a directory with python files and sub-directories which have python +files (and may have more sub-directories) called ``my_project``. Then if +we only want errors from files found inside ``my_project`` we can do: + +.. prompt:: bash + + flake8 my_project + +And if we only want certain errors (e.g., ``E123``) from files in that +directory we can also do: + +.. prompt:: bash + + flake8 --select E123 my_project + +If you want to explore more options that can be passed on the command-line, +you can use the ``--help`` option: + +.. prompt:: bash + + flake8 --help + +And you should see something like: + +.. code:: + + Usage: flake8 [options] file file ... + + Options: + --version show program's version number and exit + -h, --help show this help message and exit + -v, --verbose Print more information about what is happening in + flake8. This option is repeatable and will increase + verbosity each time it is repeated. + -q, --quiet Report only file names, or nothing. This option is + repeatable. + --count Print total number of errors and warnings to standard + error and set the exit code to 1 if total is not + empty. + --diff Report changes only within line number ranges in the + unified diff provided on standard in by the user. + --exclude=patterns Comma-separated list of files or directories to + exclude.(Default: + .svn,CVS,.bzr,.hg,.git,__pycache__,.tox) + --filename=patterns Only check for filenames matching the patterns in this + comma-separated list. (Default: *.py) + --format=format Format errors according to the chosen formatter. + --hang-closing Hang closing bracket instead of matching indentation + of opening bracket's line. + --ignore=errors Comma-separated list of errors and warnings to ignore + (or skip). For example, ``--ignore=E4,E51,W234``. + (Default: E121,E123,E126,E226,E24,E704) + --max-line-length=n Maximum allowed line length for the entirety of this + run. (Default: 79) + --select=errors Comma-separated list of errors and warnings to enable. + For example, ``--select=E4,E51,W234``. (Default: ) + --disable-noqa Disable the effect of "# noqa". This will report + errors on lines with "# noqa" at the end. + --show-source Show the source generate each error or warning. + --statistics Count errors and warnings. + --enabled-extensions=ENABLED_EXTENSIONS + Enable plugins and extensions that are otherwise + disabled by default + --exit-zero Exit with status code "0" even if there are errors. + -j JOBS, --jobs=JOBS Number of subprocesses to use to run checks in + parallel. This is ignored on Windows. The default, + "auto", will auto-detect the number of processors + available to use. (Default: auto) + --output-file=OUTPUT_FILE + Redirect report to a file. + --append-config=APPEND_CONFIG + Provide extra config files to parse in addition to the + files found by Flake8 by default. These files are the + last ones read and so they take the highest precedence + when multiple files provide the same option. + --config=CONFIG Path to the config file that will be the authoritative + config source. This will cause Flake8 to ignore all + other configuration files. + --isolated Ignore all found configuration files. + --builtins=BUILTINS define more built-ins, comma separated + --doctests check syntax of the doctests + --include-in-doctest=INCLUDE_IN_DOCTEST + Run doctests only on these files + --exclude-from-doctest=EXCLUDE_FROM_DOCTEST + Skip these files when running doctests + + Installed plugins: pyflakes: 1.0.0, pep8: 1.7.0 diff --git a/docs/source/user/options.rst b/docs/source/user/options.rst new file mode 100644 index 0000000..acaa67c --- /dev/null +++ b/docs/source/user/options.rst @@ -0,0 +1,730 @@ +.. _options-list: + +================================================ + Full Listing of Options and Their Descriptions +================================================ + +.. + NOTE(sigmavirus24): When adding new options here, please follow the + following _rough_ template: + + .. option:: --<opt-name>[=<descriptive-name-of-parameter>] + + Active description of option's purpose (note that each description + starts with an active verb) + + Command-line usage: + + .. prompt:: bash + + flake8 --<opt-name>[=<example-parameter(s)>] [positional params] + + This **can[ not]** be specified in config files. + + (If it can be, an example using .. code-block:: ini) + + Thank you for your contribution to Flake8's documentation. + +.. program:: flake8 + +.. option:: --version + + Show |Flake8|'s version as well as the versions of all plugins + installed. + + Command-line usage: + + .. prompt:: bash + + flake8 --version + + This **can not** be specified in config files. + + +.. option:: -h, --help + + Show a description of how to use |Flake8| and its options. + + Command-line usage: + + .. prompt:: bash + + flake8 --help + flake8 -h + + This **can not** be specified in config files. + + +.. option:: -v, --verbose + + Increase the verbosity of |Flake8|'s output. Each time you specify + it, it will print more and more information. + + Command-line example: + + .. prompt:: bash + + flake8 -vv + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + verbose = 2 + + +.. option:: -q, --quiet + + Decrease the verbosity of |Flake8|'s output. Each time you specify it, + it will print less and less information. + + Command-line example: + + .. prompt:: bash + + flake8 -q + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + quiet = 1 + + +.. option:: --count + + Print the total number of errors. + + Command-line example: + + .. prompt:: bash + + flake8 --count dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + count = True + + +.. option:: --diff + + Use the unified diff provided on standard in to only check the modified + files and report errors included in the diff. + + Command-line example: + + .. prompt:: bash + + git diff -u | flake8 --diff + + This **can not** be specified in config files. + + +.. option:: --exclude=<patterns> + + Provide a comma-separated list of glob patterns to exclude from checks. + + This defaults to: ``.svn,CVS,.bzr,.hg,.git,__pycache__,.tox`` + + Example patterns: + + - ``*.pyc`` will match any file that ends with ``.pyc`` + + - ``__pycache__`` will match any path that has ``__pycache__`` in it + + - ``lib/python`` will look expand that using :func:`os.path.abspath` and + look for matching paths + + Command-line example: + + .. prompt:: bash + + flake8 --exclude=*.pyc dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + exclude = + .tox, + __pycache__ + + +.. option:: --filename=<patterns> + + Provide a comma-separate list of glob patterns to include for checks. + + This defaults to: ``*.py`` + + Example patterns: + + - ``*.py`` will match any file that ends with ``.py`` + + - ``__pycache__`` will match any path that has ``__pycache__`` in it + + - ``lib/python`` will look expand that using :func:`os.path.abspath` and + look for matching paths + + Command-line example: + + .. prompt:: bash + + flake8 --filename=*.py dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + filename = + example.py, + another-example*.py + + +.. option:: --stdin-display-name=<display_name> + + Provide the name to use to report warnings and errors from code on stdin. + + Instead of reporting an error as something like: + + .. code:: + + stdin:82:73 E501 line too long + + You can specify this option to have it report whatever value you want + instead of stdin. + + This defaults to: ``stdin`` + + Command-line example: + + .. prompt:: bash + + cat file.py | flake8 --stdin-display-name=file.py - + + This **can not** be specified in config files. + + +.. option:: --format=<format> + + Select the formatter used to display errors to the user. + + This defaults to: ``default`` + + By default, there are two formatters available: + + - default + - pylint + + Other formatters can be installed. Refer to their documentation for the + name to use to select them. Further, users can specify their own format + string. The variables available are: + + - code + - col + - path + - row + - text + + The default formatter has a format string of: + + .. code-block:: python + + '%(path)s:%(row)d:%(col)d: %(code)s %(text)s' + + Command-line example: + + .. prompt:: bash + + flake8 --format=pylint dir/ + flake8 --format='%(path)s::%(row)d,%(col)d::%(code)s::%(text)s' dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + format=pylint + format=%(path)s::%(row)d,%(col)d::%(code)s::%(text)s + + +.. option:: --hang-closing + + Toggle whether pycodestyle should enforce matching the indentation of the + opening bracket's line. When you specify this, it will prefer that you + hang the closing bracket rather than match the indentation. + + Command-line example: + + .. prompt:: bash + + flake8 --hang-closing dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + hang_closing = True + hang-closing = True + + +.. option:: --ignore=<errors> + + Specify a list of codes to ignore. The list is expected to be + comma-separated, and does not need to specify an error code exactly. + Since |Flake8| 3.0, this **can** be combined with :option:`--select`. See + :option:`--select` for more information. + + For example, if you wish to only ignore ``W234``, then you can specify + that. But if you want to ignore all codes that start with ``W23`` you + need only specify ``W23`` to ignore them. This also works for ``W2`` and + ``W`` (for example). + + This defaults to: ``E121,E123,E126,E226,E24,E704`` + + Command-line example: + + .. prompt:: bash + + flake8 --ignore=E121,E123 dir/ + flake8 --ignore=E24,E704 dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + ignore = + E121, + E123 + ignore = E121,E123 + + +.. option:: --max-line-length=<n> + + Set the maximum length that any line (with some exceptions) may be. + + Exceptions include lines that are either strings or comments which are + entirely URLs. For example: + + .. code-block:: python + + # https://some-super-long-domain-name.com/with/some/very/long/path + + url = ( + 'http://...' + ) + + This defaults to: 79 + + Command-line example: + + .. prompt:: bash + + flake8 --max-line-length 99 dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + max-line-length = 79 + + +.. option:: --select=<errors> + + Specify the list of error codes you wish |Flake8| to report. Similarly to + :option:`--ignore`. You can specify a portion of an error code to get all + that start with that string. For example, you can use ``E``, ``E4``, + ``E43``, and ``E431``. + + This defaults to: E,F,W,C + + Command-line example: + + .. prompt:: bash + + flake8 --select=E431,E5,W,F dir/ + flake8 --select=E,W dir/ + + This can also be combined with :option:`--ignore`: + + .. prompt:: bash + + flake8 --select=E --ignore=E432 dir/ + + This will report all codes that start with ``E``, but ignore ``E432`` + specifically. This is more flexibly than the |Flake8| 2.x and 1.x used + to be. + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + select = + E431, + W, + F + + +.. option:: --disable-noqa + + Report all errors, even if it is on the same line as a ``# NOQA`` comment. + ``# NOQA`` can be used to silence messages on specific lines. Sometimes, + users will want to see what errors are being silenced without editing the + file. This option allows you to see all the warnings, errors, etc. + reported. + + Command-line example: + + .. prompt:: bash + + flake8 --disable-noqa dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + disable_noqa = True + disable-noqa = True + + +.. option:: --show-source + + Print the source code generating the error/warning in question. + + Command-line example: + + .. prompt:: bash + + flake8 --show-source dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + show_source = True + show-source = True + + +.. option:: --statistics + + Count the number of occurrences of each error/warning code and + print a report. + + Command-line example: + + .. prompt:: bash + + flake8 --statistics + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + statistics = True + + +.. option:: --enable-extensions=<errors> + + Enable off-by-default extensions. + + Plugins to |Flake8| have the option of registering themselves as + off-by-default. These plugins effectively add themselves to the + default ignore list. + + Command-line example: + + .. prompt:: bash + + flake8 --enable-extensions=H111 dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + enable-extensions = + H111, + G123 + enable_extensions = + H111, + G123 + + +.. option:: --exit-zero + + Force |Flake8| to use the exit status code 0 even if there are errors. + + By default |Flake8| will exit with a non-zero integer if there are errors. + + Command-line example: + + .. prompt:: bash + + flake8 --exit-zero dir/ + + This **can not** be specified in config files. + + +.. option:: --install-hook=VERSION_CONTROL_SYSTEM + + Install a hook for your version control system that is executed before + or during commit. + + The available options are: + + - git + - mercurial + + Command-line usage: + + .. prompt:: bash + + flake8 --install-hook=git + flake8 --install-hook=mercurial + + This **can not** be specified in config files. + + +.. option:: --jobs=<n> + + Specify the number of subprocesses that |Flake8| will use to run checks in + parallel. + + .. note:: + + This option is ignored on Windows because :mod:`multiprocessing` does + not support Windows across all supported versions of Python. + + This defaults to: ``auto`` + + The default behaviour will use the number of CPUs on your machine as + reported by :func:`multiprocessing.cpu_count`. + + Command-line example: + + .. prompt:: bash + + flake8 --jobs=8 dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + jobs = 8 + + +.. option:: --output-file=<path> + + Redirect all output to the specified file. + + Command-line example: + + .. prompt:: bash + + flake8 --output-file=output.txt dir/ + flake8 -vv --output-file=output.txt dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + output-file = output.txt + output_file = output.txt + + +.. option:: --append-config=<config> + + Provide extra config files to parse in after and in addition to the files + that |Flake8| found on its own. Since these files are the last ones read + into the Configuration Parser, so it has the highest precedence if it + provides an option specified in another config file. + + Command-line example: + + .. prompt:: bash + + flake8 --append-config=my-extra-config.ini dir/ + + This **can not** be specified in config files. + + +.. option:: --config=<config> + + Provide a path to a config file that will be the only config file read and + used. This will cause |Flake8| to ignore all other config files that + exist. + + Command-line example: + + .. prompt:: bash + + flake8 --config=my-only-config.ini dir/ + + This **can not** be specified in config files. + + +.. option:: --isolated + + Ignore any config files and use |Flake8| as if there were no config files + found. + + Command-line example: + + .. prompt:: bash + + flake8 --isolated dir/ + + This **can not** be specified in config files. + + +.. option:: --builtins=<builtins> + + Provide a custom list of builtin functions, objects, names, etc. + + This allows you to let pyflakes know about builtins that it may + not immediately recognize so it does not report warnings for using + an undefined name. + + This is registered by the default PyFlakes plugin. + + Command-line example: + + .. prompt:: bash + + flake8 --builtins=_,_LE,_LW dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + builtins = + _, + _LE, + _LW + + +.. option:: --doctests + + Enable PyFlakes syntax checking of doctests in docstrings. + + This is registered by the default PyFlakes plugin. + + Command-line example: + + .. prompt:: bash + + flake8 --doctests dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + doctests = True + + +.. option:: --include-in-doctest=<paths> + + Specify which files are checked by PyFlakes for doctest syntax. + + This is registered by the default PyFlakes plugin. + + Command-line example: + + .. prompt:: bash + + flake8 --include-in-doctest=dir/subdir/file.py,dir/other/file.py dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + include-in-doctest = + dir/subdir/file.py, + dir/other/file.py + include_in_doctest = + dir/subdir/file.py, + dir/other/file.py + + +.. option:: --exclude-from-doctest=<paths> + + Specify which files are not to be checked by PyFlakes for doctest syntax. + + This is registered by the default PyFlakes plugin. + + Command-line example: + + .. prompt:: bash + + flake8 --exclude-in-doctest=dir/subdir/file.py,dir/other/file.py dir/ + + This **can** be specified in config files. + + Example config file usage: + + .. code-block:: ini + + exclude-in-doctest = + dir/subdir/file.py, + dir/other/file.py + exclude_in_doctest = + dir/subdir/file.py, + dir/other/file.py + + +.. option:: --benchmark + + Collect and print benchmarks for this run of |Flake8|. This aggregates the + total number of: + + - tokens + - physical lines + - logical lines + - files + + and the number of elapsed seconds. + + Command-line usage: + + .. prompt:: bash + + flake8 --benchmark dir/ + + This **can not** be specified in config files. diff --git a/docs/source/user/python-api.rst b/docs/source/user/python-api.rst new file mode 100644 index 0000000..214565d --- /dev/null +++ b/docs/source/user/python-api.rst @@ -0,0 +1,11 @@ +=================== + Public Python API +=================== + +|Flake8| 3.0.0 presently does not have a public, stable Python API. + +When it does it will be located in :mod:`flake8.api` and that will +be documented here. + +.. automodule:: flake8.api + :members: diff --git a/docs/source/user/using-plugins.rst b/docs/source/user/using-plugins.rst new file mode 100644 index 0000000..fad1911 --- /dev/null +++ b/docs/source/user/using-plugins.rst @@ -0,0 +1,66 @@ +================================== + Using Plugins For Fun and Profit +================================== + +|Flake8| is useful on its own but a lot of |Flake8|'s popularity is due to +its extensibility. Our community has developed :term:`plugin`\ s that augment +|Flake8|'s behaviour. Most of these plugins are uploaded to PyPI_. The +developers of these plugins often have some style they wish to enforce. + +For example, `flake8-docstrings`_ adds a check for :pep:`257` style +conformance. Others attempt to enforce consistency, like `flake8-future`_. + +.. note:: + + The accuracy or reliability of these plugins may vary wildly from plugin + to plugin and not all plugins are guaranteed to work with |Flake8| 3.0. + +To install a third-party plugin, make sure that you know which version of +Python (or pip) you used to install |Flake8|. You can then use the most +appropriate of: + +.. prompt:: bash + + pip install <plugin-name> + pip3 install <plugin-name> + python -m pip install <plugin-name> + python2.7 -m pip install <plugin-name> + python3 -m pip install <plugin-name> + python3.4 -m pip install <plugin-name> + python3.5 -m pip install <plugin-name> + +To install the plugin, where ``<plugin-name>`` is the package name on PyPI_. +To verify installation use: + +.. prompt:: bash + + flake8 --version + python<version> -m flake8 --version + +To see the plugin's name and version in the output. + +.. seealso:: :ref:`How to Invoke Flake8 <invocation>` + +After installation, most plugins immediately start reporting :term:`error`\ s. +Check the plugin's documentation for which error codes it returns and if it +disables any by default. + +.. note:: + + You can use both :option:`flake8 --select` and :option:`flake8 --ignore` + with plugins. + +Some plugins register new options, so be sure to check :option:`flake8 --help` +for new flags and documentation. These plugins may also allow these flags to +be specified in your configuration file. Hopefully, the plugin authors have +documented this for you. + +.. seealso:: :ref:`Configuring Flake8 <configuration>` + + +.. _PyPI: + https://pypi.io/ +.. _flake8-docstrings: + https://pypi.io/project/flake8-docstrings/ +.. _flake8-future: + https://pypi.io/project/flake8-future/ |
