pep257

a static linter for docstring conventions

Amir Rachum
PyWeb-IL 45

In [ ]:
# kennethreitz/requests

"""
Determines appropriate setting for a given request, taking into account the
explicit setting on that request, and the setting in the session. If a
setting is a dictionary, they will be merged together using `dict_class`
"""
In [ ]:
# cool-RR/python_toolbox

'''
Defines the `profile_ready` decorator.

See its documentation for more details.
'''
In [ ]:
# docopt/docopt

"""Expand pattern into an (almost) equivalent one, but with single Either.

Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d)
Quirks: [-a] => (-a), (-a...) => (-a -a)

"""
In [ ]:
# django/django

"""
Output the approximate number of changed/added strings in the en catalog.
"""
In [ ]:
# kumar303/disable-docstring

 """THIS IS FAIL"""

Who can say which convention is better?

Guido. Guido can.

PEP257 Examples

  • One-liners should fit on one line.
  • All public modules, classes, methods and functions should be documented.
  • 1 blank line required after class docstring.
  • The first line of a method or function docstring should begin with an imperative verb.
  • And so forth...
In [4]:
%%bash
pep257 test.py 2>&1 >/dev/null | head
test.py:1 at module level:
        D100: Missing docstring in public module
test.py:22 in public class `class_`:
        D101: Missing docstring in public class
test.py:26 in private nested class `meta`:
        D101: Missing docstring in public class
test.py:30 in public method `method`:
        D102: Missing docstring in public method
test.py:37 in public method `__init__`:
        D102: Missing docstring in public method
In [8]:
%%bash
pep257 test.py --explain 2>&1 >/dev/null | head
test.py:1 at module level:
        D100: Missing docstring in public module

        All modules should normally have docstrings.  [...] all functions and
        classes exported by a module should also have docstrings. Public
        methods (including the __init__ constructor) should also have
        docstrings.
        Note: Public (exported) definitions are either those with names listed
              in __all__ variable (if present), or those that do not start
              with a single underscore.
In [16]:
%%bash
pep257 test.py --source --ignore=D100,D101,D102,D103 2>&1 >/dev/null | head -n8
test.py:54 in public function `asdlkfasd`:
        D200: One-line docstring should fit on one line with quotes (found 3)

    54: def asdlkfasd():
    55:     """
    56:     Wrong.
    57:     """

In [17]:
%%bash
pep257 --help
Usage: pep257 [options] [<file|dir>...]

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -e, --explain         show explanation of each error
  -s, --source          show source for each error
  --ignore=<codes>      ignore a list comma-separated error codes, for
                        example: --ignore=D101,D202
  --match=<pattern>     check only files that exactly match <pattern> regular
                        expression; default is --match='(?!test_).*\.py' which
                        matches files that don't start with 'test_' but end
                        with '.py'
  --match-dir=<pattern>
                        search only dirs that exactly match <pattern> regular
                        expression; default is --match-dir='[^\.].*', which
                        matches all dirs that don't start with a dot
  -d, --debug           print debug information
  -v, --verbose         print status information
  --count               print total number of errors to stdout

What Else?

  • Static analysis - it does not import your code (safe from side effects)
  • No dependencies (for now). Install via pip install pep257.
  • Integrates with flake8 via flake8-docstrings.
  • Coming up: better error selection, to support several "convention sets", such as pep257, numpy, your own.
  • Authored by Vladimir Keleshev (of docopt notoriety)
  • I am currently the sole maintainer

In conclusion:

Conventions are arbitrary,

so use this one.

Thanks for listening

https://github.com/GreenSteam/pep257

Amir Rachum
amir@rachum.com