@@ -95,6 +95,10 @@ def leading_space(string):
95
95
class Value (object ):
96
96
97
97
def __init__ (self , * args ):
98
+ if len (self ._fields ) != len (args ):
99
+ raise ValueError ('got %s arguments for %s fields for %s: %s'
100
+ % (len (args ), len (self ._fields ),
101
+ self .__class__ .__name__ , self ._fields ))
98
102
vars (self ).update (zip (self ._fields , args ))
99
103
100
104
def __hash__ (self ):
@@ -112,7 +116,7 @@ def __repr__(self):
112
116
class Definition (Value ):
113
117
114
118
_fields = ('name' , '_source' , 'start' , 'end' , 'decorators' , 'docstring' ,
115
- 'children' , 'parent' )
119
+ 'children' , 'parent' , 'skips' )
116
120
117
121
_human = property (lambda self : humanize (type (self ).__name__ ))
118
122
kind = property (lambda self : self ._human .split ()[- 1 ])
@@ -140,13 +144,16 @@ def is_empty_or_comment(line):
140
144
return '' .join (reversed (list (filtered_src )))
141
145
142
146
def __str__ (self ):
143
- return 'in %s %s `%s`' % (self ._publicity , self ._human , self .name )
147
+ out = 'in %s %s `%s`' % (self ._publicity , self ._human , self .name )
148
+ if self .skips :
149
+ out += ' (skipping %s)' % self .skips
150
+ return out
144
151
145
152
146
153
class Module (Definition ):
147
154
148
155
_fields = ('name' , '_source' , 'start' , 'end' , 'decorators' , 'docstring' ,
149
- 'children' , 'parent' , '_all' , 'future_imports' )
156
+ 'children' , 'parent' , '_all' , 'future_imports' , 'skips' )
150
157
is_public = True
151
158
_nest = staticmethod (lambda s : {'def' : Function , 'class' : Class }[s ])
152
159
module = property (lambda self : self )
@@ -433,7 +440,7 @@ def parse_module(self):
433
440
if self .filename .endswith ('__init__.py' ):
434
441
cls = Package
435
442
module = cls (self .filename , self .source , start , end ,
436
- [], docstring , children , None , self .all )
443
+ [], docstring , children , None , self .all , None , '' )
437
444
for child in module .children :
438
445
child .parent = module
439
446
module .future_imports = self .future_imports
@@ -462,7 +469,15 @@ def parse_definition(self, class_):
462
469
self .leapfrog (tk .OP , value = ":" )
463
470
else :
464
471
self .consume (tk .OP )
472
+ skips = ''
465
473
if self .current .kind in (tk .NEWLINE , tk .COMMENT ):
474
+ if self .current .kind == tk .COMMENT :
475
+ if self .current .value .startswith ('# noqa' ) or \
476
+ 'pydocstyle: noqa' in self .current .value :
477
+ skips = 'all'
478
+ elif 'pydocstyle: ' in self .current .value :
479
+ skips = '' .join (self .current .value .split (
480
+ 'pydocstyle: ' )[1 :])
466
481
self .leapfrog (tk .INDENT )
467
482
assert self .current .kind != tk .INDENT
468
483
docstring = self .parse_docstring ()
@@ -479,7 +494,7 @@ def parse_definition(self, class_):
479
494
end = self .line
480
495
self .leapfrog (tk .NEWLINE )
481
496
definition = class_ (name , self .source , start , end ,
482
- decorators , docstring , children , None )
497
+ decorators , docstring , children , None , skips )
483
498
for child in definition .children :
484
499
child .parent = definition
485
500
log .debug ("finished parsing %s '%s'. Next token is %r (%s)" ,
@@ -1400,7 +1415,10 @@ def check_source(self, source, filename):
1400
1415
for check in self .checks :
1401
1416
terminate = False
1402
1417
if isinstance (definition , check ._check_for ):
1403
- error = check (None , definition , definition .docstring )
1418
+ if definition .skips != 'all' :
1419
+ error = check (None , definition , definition .docstring )
1420
+ else :
1421
+ error = None
1404
1422
errors = error if hasattr (error , '__iter__' ) else [error ]
1405
1423
for error in errors :
1406
1424
if error is not None :
@@ -1441,7 +1459,10 @@ def check_docstring_missing(self, definition, docstring):
1441
1459
Method : (lambda : D105 () if is_magic (definition .name )
1442
1460
else D102 ()),
1443
1461
Function : D103 , NestedFunction : D103 , Package : D104 }
1444
- return codes [type (definition )]()
1462
+ code = codes [type (definition )]
1463
+ if code .__name__ in definition .skips :
1464
+ return
1465
+ return code ()
1445
1466
1446
1467
@check_for (Definition )
1447
1468
def check_one_liners (self , definition , docstring ):
@@ -1451,6 +1472,8 @@ def check_one_liners(self, definition, docstring):
1451
1472
This looks better for one-liners.
1452
1473
1453
1474
"""
1475
+ if 'D200' in definition .skips :
1476
+ return
1454
1477
if docstring :
1455
1478
lines = ast .literal_eval (docstring ).split ('\n ' )
1456
1479
if len (lines ) > 1 :
@@ -1472,9 +1495,11 @@ def check_no_blank_before(self, function, docstring): # def
1472
1495
blanks_before_count = sum (takewhile (bool , reversed (blanks_before )))
1473
1496
blanks_after_count = sum (takewhile (bool , blanks_after ))
1474
1497
if blanks_before_count != 0 :
1475
- yield D201 (blanks_before_count )
1498
+ if 'D201' not in function .skips :
1499
+ yield D201 (blanks_before_count )
1476
1500
if not all (blanks_after ) and blanks_after_count != 0 :
1477
- yield D202 (blanks_after_count )
1501
+ if 'D202' not in function .skips :
1502
+ yield D202 (blanks_after_count )
1478
1503
1479
1504
@check_for (Class )
1480
1505
def check_blank_before_after_class (self , class_ , docstring ):
@@ -1502,11 +1527,12 @@ def check_blank_before_after_class(self, class_, docstring):
1502
1527
blanks_after = list (map (is_blank , after .split ('\n ' )[1 :]))
1503
1528
blanks_before_count = sum (takewhile (bool , reversed (blanks_before )))
1504
1529
blanks_after_count = sum (takewhile (bool , blanks_after ))
1505
- if blanks_before_count != 0 :
1530
+ if 'D211' not in class_ . skips and blanks_before_count != 0 :
1506
1531
yield D211 (blanks_before_count )
1507
- if blanks_before_count != 1 :
1532
+ if 'D203' not in class_ . skips and blanks_before_count != 1 :
1508
1533
yield D203 (blanks_before_count )
1509
- if not all (blanks_after ) and blanks_after_count != 1 :
1534
+ if 'D204' not in class_ .skips and (not all (blanks_after ) and
1535
+ blanks_after_count != 1 ):
1510
1536
yield D204 (blanks_after_count )
1511
1537
1512
1538
@check_for (Definition )
@@ -1521,6 +1547,8 @@ def check_blank_after_summary(self, definition, docstring):
1521
1547
1522
1548
"""
1523
1549
if docstring :
1550
+ if 'D205' in definition .skips :
1551
+ return
1524
1552
lines = ast .literal_eval (docstring ).strip ().split ('\n ' )
1525
1553
if len (lines ) > 1 :
1526
1554
post_summary_blanks = list (map (is_blank , lines [1 :]))
@@ -1543,13 +1571,16 @@ def check_indent(self, definition, docstring):
1543
1571
if len (lines ) > 1 :
1544
1572
lines = lines [1 :] # First line does not need indent.
1545
1573
indents = [leading_space (l ) for l in lines if not is_blank (l )]
1546
- if set (' \t ' ) == set ('' .join (indents ) + indent ):
1547
- yield D206 ()
1548
- if (len (indents ) > 1 and min (indents [:- 1 ]) > indent or
1549
- indents [- 1 ] > indent ):
1550
- yield D208 ()
1551
- if min (indents ) < indent :
1552
- yield D207 ()
1574
+ if 'D206' not in definition .skips :
1575
+ if set (' \t ' ) == set ('' .join (indents ) + indent ):
1576
+ yield D206 ()
1577
+ if 'D208' not in definition .skips :
1578
+ if (len (indents ) > 1 and min (indents [:- 1 ]) > indent or
1579
+ indents [- 1 ] > indent ):
1580
+ yield D208 ()
1581
+ if 'D207' not in definition .skips :
1582
+ if min (indents ) < indent :
1583
+ yield D207 ()
1553
1584
1554
1585
@check_for (Definition )
1555
1586
def check_newline_after_last_paragraph (self , definition , docstring ):
@@ -1559,7 +1590,7 @@ def check_newline_after_last_paragraph(self, definition, docstring):
1559
1590
quotes on a line by themselves.
1560
1591
1561
1592
"""
1562
- if docstring :
1593
+ if docstring and 'D209' not in definition . skips :
1563
1594
lines = [l for l in ast .literal_eval (docstring ).split ('\n ' )
1564
1595
if not is_blank (l )]
1565
1596
if len (lines ) > 1 :
@@ -1569,7 +1600,7 @@ def check_newline_after_last_paragraph(self, definition, docstring):
1569
1600
@check_for (Definition )
1570
1601
def check_surrounding_whitespaces (self , definition , docstring ):
1571
1602
"""D210: No whitespaces allowed surrounding docstring text."""
1572
- if docstring :
1603
+ if docstring and 'D210' not in definition . skips :
1573
1604
lines = ast .literal_eval (docstring ).split ('\n ' )
1574
1605
if lines [0 ].startswith (' ' ) or \
1575
1606
len (lines ) == 1 and lines [0 ].endswith (' ' ):
@@ -1595,9 +1626,11 @@ def check_multi_line_summary_start(self, definition, docstring):
1595
1626
if len (lines ) > 1 :
1596
1627
first = docstring .split ("\n " )[0 ].strip ().lower ()
1597
1628
if first in start_triple :
1598
- return D212 ()
1629
+ if 'D212' not in definition .skips :
1630
+ return D212 ()
1599
1631
else :
1600
- return D213 ()
1632
+ if 'D213' not in definition .skips :
1633
+ return D213 ()
1601
1634
1602
1635
@check_for (Definition )
1603
1636
def check_triple_double_quotes (self , definition , docstring ):
@@ -1612,7 +1645,7 @@ def check_triple_double_quotes(self, definition, docstring):
1612
1645
""" quotes in its body.
1613
1646
1614
1647
'''
1615
- if docstring :
1648
+ if docstring and 'D300' not in definition . skips :
1616
1649
opening = docstring [:5 ].lower ()
1617
1650
if '"""' in ast .literal_eval (docstring ) and opening .startswith (
1618
1651
("'''" , "r'''" , "u'''" , "ur'''" )):
@@ -1634,8 +1667,8 @@ def check_backslashes(self, definition, docstring):
1634
1667
'''
1635
1668
# Just check that docstring is raw, check_triple_double_quotes
1636
1669
# ensures the correct quotes.
1637
- if docstring and '\\ ' in docstring and not docstring . startswith (
1638
- ('r' , 'ur' )):
1670
+ if docstring and 'D301' not in definition . skips and \
1671
+ ' \\ ' in docstring and not docstring . startswith ( ('r' , 'ur' )):
1639
1672
return D301 ()
1640
1673
1641
1674
@check_for (Definition )
@@ -1650,7 +1683,8 @@ def check_unicode_docstring(self, definition, docstring):
1650
1683
1651
1684
# Just check that docstring is unicode, check_triple_double_quotes
1652
1685
# ensures the correct quotes.
1653
- if docstring and sys .version_info [0 ] <= 2 :
1686
+ if docstring and sys .version_info [0 ] <= 2 and \
1687
+ 'D302' not in definition .skips :
1654
1688
if not is_ascii (docstring ) and not docstring .startswith (
1655
1689
('u' , 'ur' )):
1656
1690
return D302 ()
@@ -1662,7 +1696,7 @@ def check_ends_with_period(self, definition, docstring):
1662
1696
The [first line of a] docstring is a phrase ending in a period.
1663
1697
1664
1698
"""
1665
- if docstring :
1699
+ if docstring and 'D400' not in definition . skips :
1666
1700
summary_line = ast .literal_eval (docstring ).strip ().split ('\n ' )[0 ]
1667
1701
if not summary_line .endswith ('.' ):
1668
1702
return D400 (summary_line [- 1 ])
@@ -1676,7 +1710,7 @@ def check_imperative_mood(self, function, docstring): # def context
1676
1710
"Returns the pathname ...".
1677
1711
1678
1712
"""
1679
- if docstring :
1713
+ if docstring and 'D401' not in function . skips :
1680
1714
stripped = ast .literal_eval (docstring ).strip ()
1681
1715
if stripped :
1682
1716
first_word = stripped .split ()[0 ]
@@ -1691,7 +1725,7 @@ def check_no_signature(self, function, docstring): # def context
1691
1725
function/method parameters (which can be obtained by introspection).
1692
1726
1693
1727
"""
1694
- if docstring :
1728
+ if docstring and 'D402' not in function . skips :
1695
1729
first_line = ast .literal_eval (docstring ).strip ().split ('\n ' )[0 ]
1696
1730
if function .name + '(' in first_line .replace (' ' , '' ):
1697
1731
return D402 ()
@@ -1703,7 +1737,7 @@ def check_capitalized(self, function, docstring):
1703
1737
The [first line of a] docstring is a phrase ending in a period.
1704
1738
1705
1739
"""
1706
- if docstring :
1740
+ if docstring and 'D403' not in function . skips :
1707
1741
first_word = ast .literal_eval (docstring ).split ()[0 ]
1708
1742
if first_word == first_word .upper ():
1709
1743
return
@@ -1721,7 +1755,7 @@ def check_starts_with_this(self, function, docstring):
1721
1755
with "This class is [..]" or "This module contains [..]".
1722
1756
1723
1757
"""
1724
- if docstring :
1758
+ if docstring and 'D404' not in function . skips :
1725
1759
first_word = ast .literal_eval (docstring ).split ()[0 ]
1726
1760
if first_word .lower () == 'this' :
1727
1761
return D404 ()
0 commit comments