Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pycqa/pydocstyle
1 result
Show changes
Commits on Source (58)
environment:
matrix:
- TOXENV: "py27-tests"
- TOXENV: "py33-tests"
- TOXENV: "py34-tests"
- TOXENV: "py35-tests"
- TOXENV: "py36-tests"
- TOXENV: "pypy-tests"
- TOXENV: "py27-install"
- TOXENV: "py33-install"
- TOXENV: "py34-install"
- TOXENV: "py35-install"
- TOXENV: "py36-install"
- TOXENV: "pypy-install"
- TOXENV: "docs"
install:
# This takes a long time, so it's done only for pypy environments.
- ps: if($env:TOXENV -eq 'pypy-tests' -or $env:TOXENV -eq 'pypy-install') {
choco install python.pypy;
}
- pip install tox
build: off
test_script:
- tox -e %TOXENV%
[bumpversion]
current_version = 2.0.1rc
current_version = 2.1.2rc
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>.*))?
serialize =
Loading
Loading
Loading
Loading
@@ -10,14 +10,28 @@ script: tox
matrix:
include:
- python: 2.7
env: TOXENV=py27
env: TOXENV=py27-tests
- python: 3.3
env: TOXENV=py33
env: TOXENV=py33-tests
- python: 3.4
env: TOXENV=py34
env: TOXENV=py34-tests
- python: 3.5
env: TOXENV=py35
env: TOXENV=py35-tests
- python: 3.6
env: TOXENV=py36-tests
- python: pypy
env: TOXENV=pypy
env: TOXENV=pypy-tests
- python: 2.7
env: TOXENV=py27-install
- python: 3.3
env: TOXENV=py33-install
- python: 3.4
env: TOXENV=py34-install
- python: 3.5
env: TOXENV=py35-install
- python: 3.6
env: TOXENV=py36-install
- python: pypy
env: TOXENV=pypy-install
- python: 2.7
env: TOXENV=docs
pydocstyle - docstring style checker
====================================
 
.. image:: https://travis-ci.org/PyCQA/pydocstyle.svg?branch=master
:target: https://travis-ci.org/PyCQA/pydocstyle
.. image:: https://ci.appveyor.com/api/projects/status/40kkc366bmrrttca/branch/master?svg=true
:target: https://ci.appveyor.com/project/Nurdok/pydocstyle/branch/master
.. image:: https://readthedocs.org/projects/pydocstyle/badge/?version=latest
:target: https://readthedocs.org/projects/pydocstyle/?badge=latest
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/pyversions/pydocstyle.svg
:target: https://pypi.org/project/pydocstyle
(formerly pep257)
 
**pydocstyle** is a static analysis tool for checking compliance with Python
Loading
Loading
@@ -10,7 +25,7 @@ docstring conventions.
`PEP 257 <http://www.python.org/dev/peps/pep-0257/>`_ out of the box, but it
should not be considered a reference implementation.
 
**pydocstyle** supports Python 2.7, 3.3, 3.4, 3.5 and pypy.
**pydocstyle** supports Python 2.7, 3.3, 3.4, 3.5, 3.6 and pypy.
 
Quick Start
-----------
Loading
Loading
@@ -41,13 +56,6 @@ Run
Links
-----
 
.. image:: https://travis-ci.org/PyCQA/pydocstyle.svg?branch=master
:target: https://travis-ci.org/PyCQA/pydocstyle
.. image:: https://readthedocs.org/projects/pydocstyle/badge/?version=latest
:target: https://readthedocs.org/projects/pydocstyle/?badge=latest
:alt: Documentation Status
* `Read the full documentation here <http://pydocstyle.org>`_.
 
* `Fork pydocstyle on GitHub <http://github.com/PyCQA/pydocstyle>`_.
Loading
Loading
Loading
Loading
@@ -5,13 +5,31 @@ Release Notes
`Semantic Versioning <http://semver.org/>`_ specification.
 
 
Current Development Version
---------------------------
2.1.1 - October 9th, 2017
-------------------------
Bug Fixes
* Changed wheel configuration to be NOT universal, as #281 added
``configparser`` as a dependency for Python 2.7.
* Updated usage documentation.
2.1.0 - October 8th, 2017
-------------------------
 
New Features
 
* Public nested classes missing a docstring are now reported as D106 instead
of D101 (#198, #261).
* ``__init__`` methods missing a docstring are now reported as D107 instead of
D102 (#273, #277).
* Added support for Python 3.6 (#270).
* Specifying an invalid error code prefix (e.g., ``--select=D9``) will print
a warning message to ``stderr`` (#253, #279).
* Configuration files now support multiple-lined entries (#250, #281).
* Improved description of how error selection works in the help section
(#231, #283).
 
Bug Fixes
 
Loading
Loading
@@ -20,6 +38,9 @@ Bug Fixes
* Fixed an issue where if a first word in a docstring had Unicode characters
and the docstring was not a unicode string, an exception would be raised
(#258, #264).
* Configuration files that were specified by CLI and don't contain a valid
section name will now issue a warning to ``stderr`` (#276, #280).
* Removed D107 from the numpy convention (#288).
 
 
2.0.0 - April 18th, 2017
Loading
Loading
Loading
Loading
@@ -16,21 +16,6 @@ Usage
-v, --verbose print status information
--count print total number of errors to stdout
--config=<path> use given config file and disable config discovery
--select=<codes> choose the basic list of checked errors by specifying
which errors to check for (with a list of comma-
separated error codes or prefixes). for example:
--select=D101,D2
--ignore=<codes> choose the basic list of checked errors by specifying
which errors to ignore (with a list of comma-separated
error codes or prefixes). for example:
--ignore=D101,D2
--convention=<name> choose the basic list of checked errors by specifying
an existing convention. Possible conventions: pep257,
numpy
--add-select=<codes> amend the list of errors to check for by specifying
more error codes to check.
--add-ignore=<codes> amend the list of errors to check for by specifying
more error codes to ignore.
--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
Loading
Loading
@@ -45,6 +30,36 @@ Usage
regular expression; default is --ignore-decorators=''
which does not ignore any decorated functions.
 
Error Check Options:
Only one of --select, --ignore or --convention can be specified. If
none is specified, defaults to `--convention=pep257`. These three
options select the "basic list" of error codes to check. If you wish
to change that list (for example, if you selected a known convention
but wish to ignore a specific error from it or add a new one) you can
use `--add-[ignore/select]` in order to do so.
--select=<codes> choose the basic list of checked errors by specifying
which errors to check for (with a list of comma-
separated error codes or prefixes). for example:
--select=D101,D2
--ignore=<codes> choose the basic list of checked errors by specifying
which errors to ignore out of all of the available
error codes (with a list of comma-separated error
codes or prefixes). for example: --ignore=D101,D2
--convention=<name>
choose the basic list of checked errors by specifying
an existing convention. Possible conventions: pep257,
numpy.
--add-select=<codes>
add extra error codes to check to the basic list of
errors previously set by --select, --ignore or
--convention.
--add-ignore=<codes>
ignore extra error codes by removing them from the
basic list previously set by --select, --ignore or
--convention.
.. note::
 
When using any of the ``--select``, ``--ignore``, ``--add-select``, or
Loading
Loading
sphinxcontrib-issuetracker
sphinx_rtd_theme
# Pinned to 1.6.2 due to a bug in 1.6.3. See GitHub PR #270 for details.
# TODO: remove this restriction once 1.6.4 or later is released.
sphinx==1.6.2
snowballstemmer==1.2.1
configparser==3.5.0
[wheel]
universal = 1
from __future__ import with_statement
from setuptools import setup
import sys
 
# Do not update the version manually - it is managed by `bumpversion`.
version = '2.0.1rc'
version = '2.1.2rc'
requirements = [
'snowballstemmer',
'six',
]
# Python3 to Python2 backport support.
if sys.version_info[0] == 2:
requirements.append('configparser')
 
setup(
name='pydocstyle',
Loading
Loading
@@ -16,8 +29,14 @@ setup(
classifiers=[
'Intended Audience :: Developers',
'Environment :: Console',
'Development Status :: 5 - Production/Stable',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Operating System :: OS Independent',
'License :: OSI Approved :: MIT License',
],
Loading
Loading
@@ -25,10 +44,7 @@ setup(
packages=('pydocstyle',),
package_dir={'': 'src'},
package_data={'pydocstyle': ['data/*.txt']},
install_requires=[
'snowballstemmer',
'six',
],
install_requires=requirements,
entry_points={
'console_scripts': [
'pydocstyle = pydocstyle.cli:main',
Loading
Loading
Loading
Loading
@@ -116,7 +116,8 @@ class ConventionChecker(object):
Class: violations.D101,
NestedClass: violations.D106,
Method: (lambda: violations.D105() if definition.is_magic
else violations.D102()),
else (violations.D107() if definition.is_init
else violations.D102())),
Function: violations.D103,
NestedFunction: violations.D103,
Package: violations.D104}
Loading
Loading
Loading
Loading
@@ -90,5 +90,7 @@ def setup_stream_handlers(conf):
log.addHandler(stdout_handler)
 
stderr_handler = logging.StreamHandler(sys.stderr)
msg_format = "%(levelname)s: %(message)s"
stderr_handler.setFormatter(logging.Formatter(fmt=msg_format))
stderr_handler.setLevel(logging.WARNING)
log.addHandler(stderr_handler)
Loading
Loading
@@ -7,10 +7,7 @@ from collections import Set, namedtuple
from re import compile as re
 
 
try: # Python 3.x
from ConfigParser import RawConfigParser
except ImportError: # Python 2.x
from configparser import RawConfigParser
from configparser import RawConfigParser
 
 
from .utils import __version__, log
Loading
Loading
@@ -129,7 +126,7 @@ class ConfigurationParser(object):
def get_files_to_check(self):
"""Generate files and error codes to check on each one.
 
Walk dir trees under `self._arguments` and generate yield filnames
Walk dir trees under `self._arguments` and yield file names
that `match` under each directory that `match_dir`.
The method locates the configuration for each file name and yields a
tuple of (filename, [error_codes]).
Loading
Loading
@@ -155,7 +152,7 @@ class ConfigurationParser(object):
for name in self._arguments:
if os.path.isdir(name):
for root, dirs, filenames in os.walk(name):
config = self._get_config(root)
config = self._get_config(os.path.abspath(root))
match, match_dir = _get_matches(config)
ignore_decorators = _get_ignore_decorators(config)
 
Loading
Loading
@@ -168,7 +165,7 @@ class ConfigurationParser(object):
yield (full_path, list(config.checked_codes),
ignore_decorators)
else:
config = self._get_config(name)
config = self._get_config(os.path.abspath(name))
match, _ = _get_matches(config)
ignore_decorators = _get_ignore_decorators(config)
if match(name):
Loading
Loading
@@ -256,10 +253,17 @@ class ConfigurationParser(object):
raise IllegalConfiguration('Configuration file {!r} specified '
'via --config was not found.'
.format(self._run_conf.config))
if None in self._cache:
return self._cache[None]
options, _ = self._read_configuration_file(self._run_conf.config)
config = self._create_check_config(options)
if options is None:
log.warning('Configuration file does not contain a '
'pydocstyle section. Using default configuration.')
config = self._create_check_config(self._options)
else:
config = self._create_check_config(options)
 
# Make the CLI always win
final_config = {}
Loading
Loading
@@ -294,13 +298,17 @@ class ConfigurationParser(object):
Returns (options, should_inherit).
 
"""
parser = RawConfigParser()
parser = RawConfigParser(inline_comment_prefixes=('#', ';'))
options = None
should_inherit = True
 
if parser.read(path) and self._get_section_name(parser):
all_options = self._parser.option_list[:]
for group in self._parser.option_groups:
all_options.extend(group.option_list)
option_list = dict([(o.dest, o.type or o.action)
for o in self._parser.option_list])
for o in all_options])
 
# First, read the default values
new_options, _ = self._parse_args([])
Loading
Loading
@@ -446,12 +454,18 @@ class ConfigurationParser(object):
 
try:
for part in code_parts:
if len(part) < 4:
for code in codes:
if code.startswith(part):
expanded_codes.add(code)
else:
expanded_codes.add(part)
# Dealing with split-lined configurations; The part might begin
# with a whitespace due to the newline character.
part = part.strip()
if not part:
continue
codes_to_add = {code for code in codes
if code.startswith(part)}
if not codes_to_add:
log.warn('Error code passed is not a prefix of any known '
'errors: %s', part)
expanded_codes.update(codes_to_add)
except TypeError as e:
raise IllegalConfiguration(e)
 
Loading
Loading
@@ -496,8 +510,8 @@ class ConfigurationParser(object):
return any([getattr(options, opt) is not None for opt in
cls.BASE_ERROR_SELECTION_OPTIONS])
 
@staticmethod
def _fix_set_options(options):
@classmethod
def _fix_set_options(cls, options):
"""Alter the set options from None/strings to sets in place."""
optional_set_options = ('ignore', 'select')
mandatory_set_options = ('add_ignore', 'add_select')
Loading
Loading
@@ -506,9 +520,11 @@ class ConfigurationParser(object):
"""Split `value_str` by the delimiter `,` and return a set.
 
Removes any occurrences of '' in the set.
Also expand error code prefixes, to avoid doing this for every
file.
 
"""
return set(value_str.split(',')) - {''}
return cls._expand_error_codes(set(value_str.split(',')) - {''})
 
for opt in optional_set_options:
value = getattr(options, opt)
Loading
Loading
@@ -530,7 +546,7 @@ class ConfigurationParser(object):
@classmethod
def _create_option_parser(cls):
"""Return an option parser to parse the command line arguments."""
from optparse import OptionParser
from optparse import OptionParser, OptionGroup
 
parser = OptionParser(
version=__version__,
Loading
Loading
@@ -552,27 +568,44 @@ class ConfigurationParser(object):
option('--config', metavar='<path>', default=None,
help='use given config file and disable config discovery')
 
check_group = OptionGroup(
parser,
'Error Check Options',
'Only one of --select, --ignore or --convention can be '
'specified. If none is specified, defaults to '
'`--convention=pep257`. These three options select the "basic '
'list" of error codes to check. If you wish to change that list '
'(for example, if you selected a known convention but wish to '
'ignore a specific error from it or add a new one) you can '
'use `--add-[ignore/select]` in order to do so.')
add_check = check_group.add_option
# Error check options
option('--select', metavar='<codes>', default=None,
help='choose the basic list of checked errors by '
'specifying which errors to check for (with a list of '
'comma-separated error codes or prefixes). '
'for example: --select=D101,D2')
option('--ignore', metavar='<codes>', default=None,
help='choose the basic list of checked errors by '
'specifying which errors to ignore (with a list of '
'comma-separated error codes or prefixes). '
'for example: --ignore=D101,D2')
option('--convention', metavar='<name>', default=None,
help='choose the basic list of checked errors by specifying an '
'existing convention. Possible conventions: {}'
.format(', '.join(conventions)))
option('--add-select', metavar='<codes>', default=None,
help='amend the list of errors to check for by specifying '
'more error codes to check.')
option('--add-ignore', metavar='<codes>', default=None,
help='amend the list of errors to check for by specifying '
'more error codes to ignore.')
add_check('--select', metavar='<codes>', default=None,
help='choose the basic list of checked errors by '
'specifying which errors to check for (with a list of '
'comma-separated error codes or prefixes). '
'for example: --select=D101,D2')
add_check('--ignore', metavar='<codes>', default=None,
help='choose the basic list of checked errors by '
'specifying which errors to ignore out of all of the '
'available error codes (with a list of '
'comma-separated error codes or prefixes). '
'for example: --ignore=D101,D2')
add_check('--convention', metavar='<name>', default=None,
help='choose the basic list of checked errors by specifying '
'an existing convention. Possible conventions: {}.'
.format(', '.join(conventions)))
add_check('--add-select', metavar='<codes>', default=None,
help='add extra error codes to check to the basic list of '
'errors previously set by --select, --ignore or '
'--convention.')
add_check('--add-ignore', metavar='<codes>', default=None,
help='ignore extra error codes by removing them from the '
'basic list previously set by --select, --ignore '
'or --convention.')
parser.add_option_group(check_group)
 
# Match clauses
option('--match', metavar='<pattern>', default=None,
Loading
Loading
Loading
Loading
@@ -166,6 +166,11 @@ class Method(Function):
self.name.endswith('__') and
self.name not in VARIADIC_MAGIC_METHODS)
 
@property
def is_init(self):
"""Return True iff this method is `__init__`."""
return self.name == '__init__'
@property
def is_public(self):
"""Return True iff this method should be considered public."""
Loading
Loading
Loading
Loading
@@ -8,7 +8,7 @@ except ImportError:
 
 
# Do not update the version manually - it is managed by `bumpversion`.
__version__ = '2.0.1rc'
__version__ = '2.1.2rc'
log = logging.getLogger(__name__)
 
 
Loading
Loading
Loading
Loading
@@ -159,6 +159,7 @@ D103 = D1xx.create_error('D103', 'Missing docstring in public function')
D104 = D1xx.create_error('D104', 'Missing docstring in public package')
D105 = D1xx.create_error('D105', 'Missing docstring in magic method')
D106 = D1xx.create_error('D106', 'Missing docstring in public nested class')
D107 = D1xx.create_error('D107', 'Missing docstring in __init__')
 
D2xx = ErrorRegistry.create_group('D2', 'Whitespace Issues')
D200 = D2xx.create_error('D200', 'One-line docstring should fit on one line '
Loading
Loading
@@ -241,5 +242,5 @@ conventions = AttrDict({
'pep257': all_errors - {'D203', 'D212', 'D213', 'D214', 'D215', 'D404',
'D405', 'D406', 'D407', 'D408', 'D409', 'D410',
'D411'},
'numpy': all_errors - {'D203', 'D212', 'D213', 'D402', 'D413'}
'numpy': all_errors - {'D107', 'D203', 'D212', 'D213', 'D402', 'D413'}
})
Loading
Loading
@@ -27,6 +27,10 @@ class class_:
pass
 
@expect('D102: Missing docstring in public method')
def __new__(self=None):
pass
@expect('D107: Missing docstring in __init__')
def __init__(self=None):
pass
 
Loading
Loading
Loading
Loading
@@ -110,11 +110,9 @@ def install_package(request):
script.
"""
cwd = os.path.join(os.path.dirname(__file__), '..', '..')
install_cmd = "python setup.py develop"
uninstall_cmd = install_cmd + ' --uninstall'
subprocess.check_call(shlex.split(install_cmd), cwd=cwd)
subprocess.check_call(shlex.split("pip install -e ."), cwd=cwd)
yield
subprocess.check_call(shlex.split(uninstall_cmd), cwd=cwd)
subprocess.check_call(shlex.split("pip uninstall ."), cwd=cwd)
 
 
@pytest.yield_fixture(scope="function")
Loading
Loading
@@ -251,6 +249,55 @@ def test_config_file(env):
assert 'D103' not in err
 
 
def test_sectionless_config_file(env):
"""Test that config files without a valid section name issue a warning."""
with env.open('config.ini', 'wt') as conf:
conf.write('[pdcstl]')
config_path = conf.name
_, err, code = env.invoke('--config={}'.format(config_path))
assert code == 0
assert 'Configuration file does not contain a pydocstyle section' in err
with env.open('example.py', 'wt') as example:
example.write(textwrap.dedent("""\
def foo():
pass
"""))
with env.open('tox.ini', 'wt') as conf:
conf.write('[pdcstl]\n')
conf.write('ignore = D100')
out, err, code = env.invoke()
assert code == 1
assert 'D100' in out
assert 'file does not contain a pydocstyle section' not in err
def test_multiple_lined_config_file(env):
"""Test that .ini files with multi-lined entries are parsed correctly."""
with env.open('example.py', 'wt') as example:
example.write(textwrap.dedent("""\
class Foo(object):
"Doc string"
def foo():
pass
"""))
select_string = ('D100,\n'
' #D103,\n'
' D204, D300 # Just remember - don\'t check D103!')
env.write_config(select=select_string)
out, err, code = env.invoke()
assert code == 1
assert 'D100' in out
assert 'D204' in out
assert 'D300' in out
assert 'D103' not in out
def test_config_path(env):
"""Test that options are correctly loaded from a specific config file.
 
Loading
Loading
@@ -414,7 +461,9 @@ def test_bad_wildcard_add_ignore_cli(env):
assert code == 1
assert 'D203' in out
assert 'D300' in out
assert 'D3034' not in out
assert 'D3004' not in out
assert ('Error code passed is not a prefix of any known errors: D3004'
in err)
 
 
def test_conflicting_select_ignore_config(env):
Loading
Loading
@@ -558,11 +607,14 @@ def test_numpy_convention(env):
returns
------
"""
def __init__(self):
pass
'''))
 
env.write_config(convention="numpy")
out, err, code = env.invoke()
assert code == 1
assert 'D107' not in out
assert 'D213' not in out
assert 'D215' in out
assert 'D405' in out
Loading
Loading
Loading
Loading
@@ -4,7 +4,7 @@
# install tox" and then run "tox" from this directory.
 
[tox]
envlist = py27, py33, py34, py35, pypy, docs
envlist = {py27, py33, py34, py35, py36, pypy}-{tests, install}, docs
 
[testenv]
# Make sure reading the UTF-8 from test.py works regardless of the locale used.
Loading
Loading
@@ -16,6 +16,36 @@ deps =
-rrequirements/runtime.txt
-rrequirements/tests.txt
 
[testenv:py27-install]
skip_install = True
commands =
python setup.py bdist_wheel
pip install --no-index --find-links=dist pydocstyle
pydocstyle --help
# There's no way to generate sub-sections in tox.
# The following sections are all references to the `py27-install`.
[testenv:py33-install]
skip_install = {[testenv:py27-install]skip_install}
commands = {[testenv:py27-install]commands}
[testenv:py34-install]
skip_install = {[testenv:py27-install]skip_install}
commands = {[testenv:py27-install]commands}
[testenv:py35-install]
skip_install = {[testenv:py27-install]skip_install}
commands = {[testenv:py27-install]commands}
[testenv:py36-install]
skip_install = {[testenv:py27-install]skip_install}
commands = {[testenv:py27-install]commands}
[testenv:pypy-install]
skip_install = {[testenv:py27-install]skip_install}
commands = {[testenv:py27-install]commands}
[testenv:docs]
changedir=docs
deps =
Loading
Loading