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

Commit dbf8d5f

Browse files
committed
Merge remote-tracking branch 'PyCQA/master'
2 parents 41b6cdb + c3cd2dc commit dbf8d5f

File tree

7 files changed

+236
-18
lines changed

7 files changed

+236
-18
lines changed

docs/error_codes.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ Not all error codes are checked for by default. The default behavior is to
1414
check only error codes that are part of the `PEP257
1515
<http://www.python.org/dev/peps/pep-0257/>`_ official convention.
1616

17-
All of the above error codes are checked for by default except for D203.
17+
All of the above error codes are checked for by default except for D203,
18+
D212 and D213.

docs/release_notes.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ Release Notes
44
**pydocstyle** version numbers follow the
55
`Semantic Versioning <http://semver.org/>`_ specification.
66

7+
Current Development Version
8+
---------------------------
9+
10+
* Added the optional error codes D212 and D213, for checking whether
11+
the summary of a multi-line docstring starts at the first line,
12+
respectively at the second line (#174).
13+
14+
* The error code D300 is now also being reported if a docstring has
15+
uppercase literals (``R`` or ``U``) as prefix (#176).
16+
717
1.0.0 - January 30th, 2016
818
--------------------------
919

src/pydocstyle.py

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,10 @@ def to_rst(cls):
683683
'docstring text')
684684
D211 = D2xx.create_error('D211', 'No blank lines allowed before class '
685685
'docstring', 'found %s')
686+
D212 = D2xx.create_error('D212', 'Multi-line docstring summary should start '
687+
'at the first line')
688+
D213 = D2xx.create_error('D213', 'Multi-line docstring summary should start '
689+
'at the second line')
686690

687691
D3xx = ErrorRegistry.create_group('D3', 'Quotes Issues')
688692
D300 = D3xx.create_error('D300', 'Use """triple double quotes"""',
@@ -707,7 +711,8 @@ def __getattr__(self, item):
707711

708712

709713
conventions = AttrDict({
710-
'pep257': set(ErrorRegistry.get_error_codes()) - set(['D203']),
714+
'pep257': set(ErrorRegistry.get_error_codes()) - set(['D203', 'D212',
715+
'D213'])
711716
})
712717

713718

@@ -1541,6 +1546,30 @@ def check_surrounding_whitespaces(self, definition, docstring):
15411546
len(lines) == 1 and lines[0].endswith(' '):
15421547
return D210()
15431548

1549+
@check_for(Definition)
1550+
def check_multi_line_summary_start(self, definition, docstring):
1551+
"""D21{2,3}: Multi-line docstring summary style check.
1552+
1553+
A multi-line docstring summary should start either at the first,
1554+
or separately at the second line of a docstring.
1555+
1556+
"""
1557+
if docstring:
1558+
start_triple = [
1559+
'"""', "'''",
1560+
'u"""', "u'''",
1561+
'r"""', "r'''",
1562+
'ur"""', "ur'''"
1563+
]
1564+
1565+
lines = ast.literal_eval(docstring).split('\n')
1566+
if len(lines) > 1:
1567+
first = docstring.split("\n")[0].strip().lower()
1568+
if first in start_triple:
1569+
return D212()
1570+
else:
1571+
return D213()
1572+
15441573
@check_for(Definition)
15451574
def check_triple_double_quotes(self, definition, docstring):
15461575
r'''D300: Use """triple double quotes""".
@@ -1554,15 +1583,17 @@ def check_triple_double_quotes(self, definition, docstring):
15541583
""" quotes in its body.
15551584
15561585
'''
1557-
if (docstring and '"""' in ast.literal_eval(docstring) and
1558-
docstring.startswith(("'''", "r'''", "u'''", "ur'''"))):
1559-
# Allow ''' quotes if docstring contains """, because otherwise """
1560-
# quotes could not be expressed inside docstring. Not in PEP 257.
1561-
return
1562-
if docstring and not docstring.startswith(
1563-
('"""', 'r"""', 'u"""', 'ur"""')):
1564-
quotes = "'''" if "'''" in docstring[:4] else "'"
1565-
return D300(quotes)
1586+
if docstring:
1587+
opening = docstring[:5].lower()
1588+
if '"""' in ast.literal_eval(docstring) and opening.startswith(
1589+
("'''", "r'''", "u'''", "ur'''")):
1590+
# Allow ''' quotes if docstring contains """, because
1591+
# otherwise """ quotes could not be expressed inside
1592+
# docstring. Not in PEP 257.
1593+
return
1594+
if not opening.startswith(('"""', 'r"""', 'u"""', 'ur"""')):
1595+
quotes = "'''" if "'''" in opening else "'"
1596+
return D300(quotes)
15661597

15671598
@check_for(Definition)
15681599
def check_backslashes(self, definition, docstring):
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
"""Module to check different multi-line docstring flavors."""
2+
3+
from .expected import Expectation
4+
5+
expectation = Expectation()
6+
expect = expectation.expect
7+
8+
_D212 = 'D212: Multi-line docstring summary should start at the first line'
9+
_D213 = 'D213: Multi-line docstring summary should start at the second line'
10+
11+
_D300 = 'D300: Use """triple double quotes""" (found \'\'\'-quotes)'
12+
_D301 = 'D301: Use r""" if any backslashes in a docstring'
13+
14+
15+
@expect(_D212)
16+
def multi_line_starts_second_line():
17+
"""
18+
Summary.
19+
20+
Description.
21+
22+
"""
23+
24+
25+
@expect(_D212)
26+
@expect(_D300)
27+
def multi_line_starts_second_line_single_quote():
28+
'''
29+
Summary.
30+
31+
Description.
32+
33+
'''
34+
35+
36+
@expect(_D212)
37+
def multi_line_starts_second_line_raw():
38+
r"""
39+
Summary.
40+
41+
Description with \backslash\.
42+
43+
"""
44+
45+
46+
@expect(_D212)
47+
@expect(_D301)
48+
def multi_line_starts_second_line_upper_raw():
49+
R"""
50+
Summary.
51+
52+
Description with \backslash\.
53+
54+
"""
55+
56+
57+
@expect(_D212)
58+
@expect(_D300)
59+
def multi_line_starts_second_line_raw_single_quote():
60+
r'''
61+
Summary.
62+
63+
Description with \backslash\.
64+
65+
'''
66+
67+
68+
@expect(_D212)
69+
@expect(_D300)
70+
@expect(_D301)
71+
def multi_line_starts_second_line_upper_raw_single_quote():
72+
R'''
73+
Summary.
74+
75+
Description with \backslash\.
76+
77+
'''
78+
79+
80+
@expect(_D213)
81+
def multi_line_starts_first_line():
82+
"""Summary.
83+
84+
Description.
85+
86+
"""
87+
88+
89+
@expect(_D213)
90+
@expect(_D300)
91+
def multi_line_starts_first_line_single_quote():
92+
'''Summary.
93+
94+
Description.
95+
96+
'''
97+
98+
99+
@expect(_D213)
100+
def multi_line_starts_first_line_raw():
101+
r"""Summary.
102+
103+
Description with \backslash\.
104+
105+
"""
106+
107+
108+
@expect(_D213)
109+
@expect(_D301)
110+
def multi_line_starts_first_line_upper_raw():
111+
R"""Summary.
112+
113+
Description with \backslash\.
114+
115+
"""
116+
117+
118+
@expect(_D213)
119+
@expect(_D300)
120+
def multi_line_starts_first_line_raw_single_quote():
121+
r'''Summary.
122+
123+
Description with \backslash\.
124+
125+
'''
126+
127+
128+
@expect(_D213)
129+
@expect(_D300)
130+
@expect(_D301)
131+
def multi_line_starts_first_line_upper_raw_single_quote():
132+
R'''Summary.
133+
134+
Description with \backslash\.
135+
136+
'''

0 commit comments

Comments
 (0)