Skip to content
This repository was archived by the owner on Nov 3, 2023. It is now read-only.

Commit fda0c41

Browse files
committed
Added D211: No blank lines allowed before class docstring
1 parent 1db2853 commit fda0c41

File tree

6 files changed

+59
-12
lines changed

6 files changed

+59
-12
lines changed

docs/error_codes.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,12 @@ Grouping
66

77
.. include:: snippets/error_code_table.rst
88

9+
10+
Default Checks
11+
--------------
12+
13+
Not all error codes are checked for by default. The default behavior is to
14+
check only error codes that are part of the `PEP257
15+
<http://www.python.org/dev/peps/pep-0257/>`_ official convention.
16+
17+
All off the above error codes are checked for by default except D203.

docs/release_notes.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ New Features
1717
which could then be added one by one using `add-select`. Useful for projects
1818
new to pep257 (#132, #135).
1919

20+
* Added check D211: No blank lines allowed before class docstring. This change
21+
is a result of a change to the official PEP257 convention. Therefore, D211
22+
will now be checked by default instead of D203, which required a single
23+
blank line before a class docstring (#137).
24+
2025
Bug Fixes
2126

2227
* On Python 2.x, D302 ("Use u""" for Unicode docstrings") is not reported
@@ -27,7 +32,7 @@ Bug Fixes
2732

2833

2934
0.6.0 - July 20th, 2015
30-
---------------------------
35+
-----------------------
3136

3237
New Features
3338

src/pep257.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ def __str__(self):
143143

144144

145145
class Package(Module):
146-
147146
"""A package is a __init__.py module."""
148147

149148

@@ -190,7 +189,6 @@ class NestedClass(Class):
190189

191190

192191
class Decorator(Value):
193-
194192
"""A decorator for function, method or class."""
195193

196194
_fields = 'name arguments'.split()
@@ -252,7 +250,6 @@ def __call__(self, filelike, filename):
252250
self.stream = TokenStream(StringIO(src))
253251
self.filename = filename
254252
self.all = None
255-
# TODO: what about Python 3.x?
256253
self.future_imports = defaultdict(lambda: False)
257254
self._accumulated_decorators = []
258255
return self.parse_module()
@@ -506,7 +503,6 @@ def parse_from_import_statement(self):
506503

507504

508505
class Error(object):
509-
510506
"""Error in docstring style."""
511507

512508
# should be overridden by inheriting classes
@@ -655,6 +651,8 @@ def to_rst(cls):
655651
'be on a separate line')
656652
D210 = D2xx.create_error('D210', 'No whitespaces allowed surrounding '
657653
'docstring text')
654+
D211 = D2xx.create_error('D211', 'No blank lines allowed before class '
655+
'docstring', 'found %s')
658656

659657
D3xx = ErrorRegistry.create_group('D3', 'Quotes Issues')
660658
D300 = D3xx.create_error('D300', 'Use """triple double quotes"""',
@@ -677,7 +675,7 @@ def __getattr__(self, item):
677675

678676

679677
conventions = AttrDict({
680-
'pep257': set(ErrorRegistry.get_error_codes()),
678+
'pep257': set(ErrorRegistry.get_error_codes()) - set(['D203']),
681679
})
682680

683681

@@ -934,7 +932,6 @@ def decorator(f):
934932

935933

936934
class PEP257Checker(object):
937-
938935
"""Checker for PEP 257.
939936
940937
D10x: Missing docstrings
@@ -1053,6 +1050,8 @@ def check_blank_before_after_class(slef, class_, docstring):
10531050
blanks_after = list(map(is_blank, after.split('\n')[1:]))
10541051
blanks_before_count = sum(takewhile(bool, reversed(blanks_before)))
10551052
blanks_after_count = sum(takewhile(bool, blanks_after))
1053+
if blanks_before_count != 0:
1054+
yield D211(blanks_before_count)
10561055
if blanks_before_count != 1:
10571056
yield D203(blanks_before_count)
10581057
if not all(blanks_after) and blanks_after_count != 1:

src/tests/test_cases/test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,19 @@ class LeadingSpaceMissing:
7878
"""Leading space missing."""
7979

8080

81+
expect('WithLeadingSpace',
82+
'D211: No blank lines allowed before class docstring (found 1)')
83+
84+
85+
class WithLeadingSpace:
86+
87+
"""With leading space."""
88+
89+
8190
expect('TrailingSpace',
8291
'D204: 1 blank line required after class docstring (found 0)')
92+
expect('TrailingSpace',
93+
'D211: No blank lines allowed before class docstring (found 1)')
8394

8495

8596
class TrailingSpace:

src/tests/test_definitions.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
from ..pep257 import (StringIO, TokenStream, Parser, Error, check,
3-
Module, Class, Method, Function, NestedFunction)
3+
Module, Class, Method, Function, NestedFunction,
4+
ErrorRegistry)
45

56

67
_ = type('', (), dict(__repr__=lambda *a: '_', __eq__=lambda *a: True))()
@@ -136,7 +137,8 @@ def test_pep257():
136137
level=1)
137138
# from .test_cases import test
138139
results = list(check([os.path.join(os.path.dirname(__file__),
139-
'test_cases', test_case + '.py')]))
140+
'test_cases', test_case + '.py')],
141+
select=set(ErrorRegistry.get_error_codes())))
140142
for error in results:
141143
assert isinstance(error, Error)
142144
results = set([(e.definition.name, e.message) for e in results])

src/tests/test_pep257.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222

2323
class Pep257Env():
24-
2524
"""An isolated environment where pep257.py can be run.
2625
2726
Since running pep257.py as a script is affected by local config files, it's
@@ -80,8 +79,9 @@ def __exit__(self, *args, **kwargs):
8079
def test_pep257_conformance():
8180
relative = partial(os.path.join, os.path.dirname(__file__))
8281
errors = list(pep257.check([relative('..', 'pep257.py'),
83-
relative('test_pep257.py')]))
84-
assert errors == []
82+
relative('test_pep257.py')],
83+
select=pep257.conventions.pep257))
84+
assert errors == [], errors
8585

8686

8787
def test_ignore_list():
@@ -346,3 +346,24 @@ def foo():
346346
assert 'D100' in err
347347
assert 'D101' not in err
348348
assert 'D103' not in err
349+
350+
351+
def test_pep257_convention():
352+
"""Test that the 'pep257' convention options has the correct errors."""
353+
with Pep257Env() as env:
354+
with env.open('example.py', 'wt') as example:
355+
example.write(textwrap.dedent('''
356+
class Foo(object):
357+
358+
359+
"""Docstring for this class"""
360+
def foo():
361+
pass
362+
'''))
363+
364+
env.write_config(convention="pep257")
365+
_, err, code = env.invoke_pep257()
366+
assert code == 1
367+
assert 'D100' in err
368+
assert 'D211' in err
369+
assert 'D203' not in err

0 commit comments

Comments
 (0)