@@ -96,9 +96,9 @@ class Value(object):
9696
9797 def __init__ (self , * args ):
9898 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 ))
99+ raise ValueError ('got {0} arguments for {1} fields for {2}: {3} '
100+ . format (len (args ), len (self ._fields ),
101+ self .__class__ .__name__ , self ._fields ))
102102 vars (self ).update (zip (self ._fields , args ))
103103
104104 def __hash__ (self ):
@@ -116,7 +116,7 @@ def __repr__(self):
116116class Definition (Value ):
117117
118118 _fields = ('name' , '_source' , 'start' , 'end' , 'decorators' , 'docstring' ,
119- 'children' , 'parent' , 'skips ' )
119+ 'children' , 'parent' , 'skipped_error_codes ' )
120120
121121 _human = property (lambda self : humanize (type (self ).__name__ ))
122122 kind = property (lambda self : self ._human .split ()[- 1 ])
@@ -145,15 +145,16 @@ def is_empty_or_comment(line):
145145
146146 def __str__ (self ):
147147 out = 'in %s %s `%s`' % (self ._publicity , self ._human , self .name )
148- if self .skips :
149- out += ' (skipping %s)' % self .skips
148+ if self .skipped_error_codes :
149+ out += ' (skipping {0})' . format ( self .skipped_error_codes )
150150 return out
151151
152152
153153class Module (Definition ):
154154
155155 _fields = ('name' , '_source' , 'start' , 'end' , 'decorators' , 'docstring' ,
156- 'children' , 'parent' , '_all' , 'future_imports' , 'skips' )
156+ 'children' , 'parent' , '_all' , 'future_imports' ,
157+ 'skipped_error_codes' )
157158 is_public = True
158159 _nest = staticmethod (lambda s : {'def' : Function , 'class' : Class }[s ])
159160 module = property (lambda self : self )
@@ -469,13 +470,8 @@ def parse_definition(self, class_):
469470 self .leapfrog (tk .OP , value = ":" )
470471 else :
471472 self .consume (tk .OP )
472- skips = ''
473473 if self .current .kind in (tk .NEWLINE , tk .COMMENT ):
474- if self .current .kind == tk .COMMENT :
475- if 'noqa: ' in self .current .value :
476- skips = '' .join (self .current .value .split ('noqa: ' )[1 :])
477- elif self .current .value .startswith ('# noqa' ):
478- skips = 'all'
474+ skipped_error_codes = self .parse_skip_comment ()
479475 self .leapfrog (tk .INDENT )
480476 assert self .current .kind != tk .INDENT
481477 docstring = self .parse_docstring ()
@@ -486,20 +482,33 @@ def parse_definition(self, class_):
486482 log .debug ("finished parsing nested definitions for '%s'" , name )
487483 end = self .line - 1
488484 else : # one-liner definition
485+ skipped_error_codes = ''
489486 docstring = self .parse_docstring ()
490487 decorators = [] # TODO
491488 children = []
492489 end = self .line
493490 self .leapfrog (tk .NEWLINE )
494491 definition = class_ (name , self .source , start , end ,
495- decorators , docstring , children , None , skips )
492+ decorators , docstring , children , None ,
493+ skipped_error_codes )
496494 for child in definition .children :
497495 child .parent = definition
498496 log .debug ("finished parsing %s '%s'. Next token is %r (%s)" ,
499497 class_ .__name__ , name , self .current .kind ,
500498 self .current .value )
501499 return definition
502500
501+ def parse_skip_comment (self ):
502+ """Parse a definition comment for noqa skips."""
503+ skipped_error_codes = ''
504+ if self .current .kind == tk .COMMENT :
505+ if 'noqa: ' in self .current .value :
506+ skipped_error_codes = '' .join (
507+ self .current .value .split ('noqa: ' )[1 :])
508+ elif self .current .value .startswith ('# noqa' ):
509+ skipped_error_codes = 'all'
510+ return skipped_error_codes
511+
503512 def check_current (self , kind = None , value = None ):
504513 msg = textwrap .dedent ("""
505514 Unexpected token at line {self.line}:
@@ -1413,13 +1422,14 @@ def check_source(self, source, filename):
14131422 for check in self .checks :
14141423 terminate = False
14151424 if isinstance (definition , check ._check_for ):
1416- if definition .skips != 'all' :
1425+ if definition .skipped_error_codes != 'all' :
14171426 error = check (None , definition , definition .docstring )
14181427 else :
14191428 error = None
14201429 errors = error if hasattr (error , '__iter__' ) else [error ]
14211430 for error in errors :
1422- if error is not None :
1431+ if error is not None and error .code not in \
1432+ definition .skipped_error_codes :
14231433 partition = check .__doc__ .partition ('.\n ' )
14241434 message , _ , explanation = partition
14251435 error .set_context (explanation = explanation ,
@@ -1457,10 +1467,7 @@ def check_docstring_missing(self, definition, docstring):
14571467 Method : (lambda : D105 () if is_magic (definition .name )
14581468 else D102 ()),
14591469 Function : D103 , NestedFunction : D103 , Package : D104 }
1460- code = codes [type (definition )]
1461- if code .__name__ in definition .skips :
1462- return
1463- return code ()
1470+ return codes [type (definition )]()
14641471
14651472 @check_for (Definition )
14661473 def check_one_liners (self , definition , docstring ):
@@ -1470,8 +1477,6 @@ def check_one_liners(self, definition, docstring):
14701477 This looks better for one-liners.
14711478
14721479 """
1473- if 'D200' in definition .skips :
1474- return
14751480 if docstring :
14761481 lines = ast .literal_eval (docstring ).split ('\n ' )
14771482 if len (lines ) > 1 :
@@ -1493,11 +1498,9 @@ def check_no_blank_before(self, function, docstring): # def
14931498 blanks_before_count = sum (takewhile (bool , reversed (blanks_before )))
14941499 blanks_after_count = sum (takewhile (bool , blanks_after ))
14951500 if blanks_before_count != 0 :
1496- if 'D201' not in function .skips :
1497- yield D201 (blanks_before_count )
1501+ yield D201 (blanks_before_count )
14981502 if not all (blanks_after ) and blanks_after_count != 0 :
1499- if 'D202' not in function .skips :
1500- yield D202 (blanks_after_count )
1503+ yield D202 (blanks_after_count )
15011504
15021505 @check_for (Class )
15031506 def check_blank_before_after_class (self , class_ , docstring ):
@@ -1525,12 +1528,11 @@ def check_blank_before_after_class(self, class_, docstring):
15251528 blanks_after = list (map (is_blank , after .split ('\n ' )[1 :]))
15261529 blanks_before_count = sum (takewhile (bool , reversed (blanks_before )))
15271530 blanks_after_count = sum (takewhile (bool , blanks_after ))
1528- if 'D211' not in class_ . skips and blanks_before_count != 0 :
1531+ if blanks_before_count != 0 :
15291532 yield D211 (blanks_before_count )
1530- if 'D203' not in class_ . skips and blanks_before_count != 1 :
1533+ if blanks_before_count != 1 :
15311534 yield D203 (blanks_before_count )
1532- if 'D204' not in class_ .skips and (not all (blanks_after ) and
1533- blanks_after_count != 1 ):
1535+ if not all (blanks_after ) and blanks_after_count != 1 :
15341536 yield D204 (blanks_after_count )
15351537
15361538 @check_for (Definition )
@@ -1545,8 +1547,6 @@ def check_blank_after_summary(self, definition, docstring):
15451547
15461548 """
15471549 if docstring :
1548- if 'D205' in definition .skips :
1549- return
15501550 lines = ast .literal_eval (docstring ).strip ().split ('\n ' )
15511551 if len (lines ) > 1 :
15521552 post_summary_blanks = list (map (is_blank , lines [1 :]))
@@ -1569,16 +1569,13 @@ def check_indent(self, definition, docstring):
15691569 if len (lines ) > 1 :
15701570 lines = lines [1 :] # First line does not need indent.
15711571 indents = [leading_space (l ) for l in lines if not is_blank (l )]
1572- if 'D206' not in definition .skips :
1573- if set (' \t ' ) == set ('' .join (indents ) + indent ):
1574- yield D206 ()
1575- if 'D208' not in definition .skips :
1576- if (len (indents ) > 1 and min (indents [:- 1 ]) > indent or
1577- indents [- 1 ] > indent ):
1578- yield D208 ()
1579- if 'D207' not in definition .skips :
1580- if min (indents ) < indent :
1581- yield D207 ()
1572+ if set (' \t ' ) == set ('' .join (indents ) + indent ):
1573+ yield D206 ()
1574+ if (len (indents ) > 1 and min (indents [:- 1 ]) > indent or
1575+ indents [- 1 ] > indent ):
1576+ yield D208 ()
1577+ if min (indents ) < indent :
1578+ yield D207 ()
15821579
15831580 @check_for (Definition )
15841581 def check_newline_after_last_paragraph (self , definition , docstring ):
@@ -1588,7 +1585,7 @@ def check_newline_after_last_paragraph(self, definition, docstring):
15881585 quotes on a line by themselves.
15891586
15901587 """
1591- if docstring and 'D209' not in definition . skips :
1588+ if docstring :
15921589 lines = [l for l in ast .literal_eval (docstring ).split ('\n ' )
15931590 if not is_blank (l )]
15941591 if len (lines ) > 1 :
@@ -1598,7 +1595,7 @@ def check_newline_after_last_paragraph(self, definition, docstring):
15981595 @check_for (Definition )
15991596 def check_surrounding_whitespaces (self , definition , docstring ):
16001597 """D210: No whitespaces allowed surrounding docstring text."""
1601- if docstring and 'D210' not in definition . skips :
1598+ if docstring :
16021599 lines = ast .literal_eval (docstring ).split ('\n ' )
16031600 if lines [0 ].startswith (' ' ) or \
16041601 len (lines ) == 1 and lines [0 ].endswith (' ' ):
@@ -1624,11 +1621,9 @@ def check_multi_line_summary_start(self, definition, docstring):
16241621 if len (lines ) > 1 :
16251622 first = docstring .split ("\n " )[0 ].strip ().lower ()
16261623 if first in start_triple :
1627- if 'D212' not in definition .skips :
1628- return D212 ()
1624+ return D212 ()
16291625 else :
1630- if 'D213' not in definition .skips :
1631- return D213 ()
1626+ return D213 ()
16321627
16331628 @check_for (Definition )
16341629 def check_triple_double_quotes (self , definition , docstring ):
@@ -1643,7 +1638,7 @@ def check_triple_double_quotes(self, definition, docstring):
16431638 """ quotes in its body.
16441639
16451640 '''
1646- if docstring and 'D300' not in definition . skips :
1641+ if docstring :
16471642 opening = docstring [:5 ].lower ()
16481643 if '"""' in ast .literal_eval (docstring ) and opening .startswith (
16491644 ("'''" , "r'''" , "u'''" , "ur'''" )):
@@ -1665,8 +1660,8 @@ def check_backslashes(self, definition, docstring):
16651660 '''
16661661 # Just check that docstring is raw, check_triple_double_quotes
16671662 # ensures the correct quotes.
1668- if docstring and 'D301' not in definition . skips and \
1669- ' \\ ' in docstring and not docstring . startswith ( ('r' , 'ur' )):
1663+ if docstring and '\\ ' in docstring and not docstring . startswith (
1664+ ('r' , 'ur' )):
16701665 return D301 ()
16711666
16721667 @check_for (Definition )
@@ -1681,8 +1676,7 @@ def check_unicode_docstring(self, definition, docstring):
16811676
16821677 # Just check that docstring is unicode, check_triple_double_quotes
16831678 # ensures the correct quotes.
1684- if docstring and sys .version_info [0 ] <= 2 and \
1685- 'D302' not in definition .skips :
1679+ if docstring and sys .version_info [0 ] <= 2 :
16861680 if not is_ascii (docstring ) and not docstring .startswith (
16871681 ('u' , 'ur' )):
16881682 return D302 ()
@@ -1694,7 +1688,7 @@ def check_ends_with_period(self, definition, docstring):
16941688 The [first line of a] docstring is a phrase ending in a period.
16951689
16961690 """
1697- if docstring and 'D400' not in definition . skips :
1691+ if docstring :
16981692 summary_line = ast .literal_eval (docstring ).strip ().split ('\n ' )[0 ]
16991693 if not summary_line .endswith ('.' ):
17001694 return D400 (summary_line [- 1 ])
@@ -1708,7 +1702,7 @@ def check_imperative_mood(self, function, docstring): # def context
17081702 "Returns the pathname ...".
17091703
17101704 """
1711- if docstring and 'D401' not in function . skips :
1705+ if docstring :
17121706 stripped = ast .literal_eval (docstring ).strip ()
17131707 if stripped :
17141708 first_word = stripped .split ()[0 ]
@@ -1723,7 +1717,7 @@ def check_no_signature(self, function, docstring): # def context
17231717 function/method parameters (which can be obtained by introspection).
17241718
17251719 """
1726- if docstring and 'D402' not in function . skips :
1720+ if docstring :
17271721 first_line = ast .literal_eval (docstring ).strip ().split ('\n ' )[0 ]
17281722 if function .name + '(' in first_line .replace (' ' , '' ):
17291723 return D402 ()
@@ -1735,7 +1729,7 @@ def check_capitalized(self, function, docstring):
17351729 The [first line of a] docstring is a phrase ending in a period.
17361730
17371731 """
1738- if docstring and 'D403' not in function . skips :
1732+ if docstring :
17391733 first_word = ast .literal_eval (docstring ).split ()[0 ]
17401734 if first_word == first_word .upper ():
17411735 return
@@ -1753,7 +1747,7 @@ def check_starts_with_this(self, function, docstring):
17531747 with "This class is [..]" or "This module contains [..]".
17541748
17551749 """
1756- if docstring and 'D404' not in function . skips :
1750+ if docstring :
17571751 first_word = ast .literal_eval (docstring ).split ()[0 ]
17581752 if first_word .lower () == 'this' :
17591753 return D404 ()
0 commit comments