mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-04 20:26:53 +00:00
Yesterday we released the flake8-polyfill package to help with Flake8 compatibility issues. This adds documentation to Flake8 to help people use that and to guide them towards it.
187 lines
6.6 KiB
ReStructuredText
187 lines
6.6 KiB
ReStructuredText
====================================
|
|
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 two** breaking changes 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 and we no longer patch pep8 or pycodestyle's ``stdin_get_value``
|
|
functions. 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
|
|
=================================
|
|
|
|
To ease the transition, the |Flake8| maintainers have released
|
|
`flake8-polyfill`_. |polyfill| provides a convenience function to help users
|
|
transition between Flake8 2 and 3 without issue. For example, if your plugin
|
|
has to work on Flake8 2.x and 3.x but you want to take advantage of some of
|
|
the new options to ``add_option``, you can do
|
|
|
|
.. code-block:: python
|
|
|
|
from flake8_polyfill import options
|
|
|
|
|
|
class MyPlugin(object):
|
|
@classmethod
|
|
def add_options(cls, parser):
|
|
options.register(
|
|
parser,
|
|
'--application-names', default='', type='string',
|
|
help='Names of the applications to be checked.',
|
|
parse_from_config=True,
|
|
comma_separated_list=True,
|
|
)
|
|
options.register(
|
|
parser,
|
|
'--style-name', default='', type='string',
|
|
help='The name of the style convention you want to use',
|
|
parse_from_config=True,
|
|
)
|
|
options.register(
|
|
parser,
|
|
'--application-paths', default='', type='string',
|
|
help='Locations of the application code',
|
|
parse_from_config=True,
|
|
comma_separated_list=True,
|
|
normalize_paths=True,
|
|
)
|
|
|
|
@classmethod
|
|
def parse_options(cls, parsed_options):
|
|
cls.application_names = parsed_options.application_names
|
|
cls.style_name = parsed_options.style_name
|
|
cls.application_paths = parsed_options.application_paths
|
|
|
|
|polyfill| will handle these extra options using *callbacks* to the option
|
|
parser. The project has direct replications of the functions that |Flake8|
|
|
uses to provide the same functionality. This means that the values you receive
|
|
should be identically parsed whether you're using Flake8 2.x or 3.x.
|
|
|
|
.. autofunction:: flake8_polyfill.options.register
|
|
|
|
|
|
Standard In Handling on Flake8 2.5, 2.6, and 3
|
|
==============================================
|
|
|
|
After releasing |Flake8| 2.6, handling standard-in became a bit trickier for
|
|
some plugins. |Flake8| 2.5 and earlier had started monkey-patching pep8's
|
|
``stdin_get_value`` function. 2.6 switched to pycodestyle and only
|
|
monkey-patched that. 3.0 has its own internal implementation and uses that but
|
|
does not directly provide anything for plugins using pep8 and pycodestyle's
|
|
``stdin_get_value`` function. |polyfill| provides this functionality for
|
|
plugin developers via it's :mod:`flake8_polyfill.stdin` module.
|
|
|
|
If a plugin needs to read the content from stdin, it can do the following:
|
|
|
|
.. code-block:: python
|
|
|
|
from flake8_polyfill import stdin
|
|
|
|
stdin.monkey_patch('pep8') # To monkey-patch only pep8
|
|
stdin.monkey_patch('pycodestyle') # To monkey-patch only pycodestyle
|
|
stdin.monkey_patch('all') # To monkey-patch both pep8 and pycodestyle
|
|
|
|
|
|
Further, when using ``all``, |polyfill| does not require both packages to be
|
|
installed but will attempt to monkey-patch both and will silently ignore the
|
|
fact that pep8 or pycodestyle is not installed.
|
|
|
|
.. autofunction:: flake8_polyfill.stdin.monkey_patch
|
|
|
|
|
|
.. links
|
|
.. _flake8-polyfill: https://pypi.io/project/flake8-polyfill/
|
|
|
|
.. |polyfill| replace:: ``flake8-polyfill``
|