@@ -200,7 +200,7 @@ def missing_newline(physical_line):
200200 return len (physical_line ), "W292 no newline at end of file"
201201
202202
203- def maximum_line_length (physical_line , max_line_length ):
203+ def maximum_line_length (physical_line , max_line_length , multiline ):
204204 """
205205 Limit all lines to a maximum of 79 characters.
206206
@@ -216,6 +216,10 @@ def maximum_line_length(physical_line, max_line_length):
216216 line = physical_line .rstrip ()
217217 length = len (line )
218218 if length > max_line_length and not noqa (line ):
219+ # Sometimes, long lines in docstrings are hard to avoid -- like,
220+ # a long URL that can't be wrapped because it has no whitespace.
221+ if multiline and re .match (r'^\s*\S+$' , line ):
222+ return
219223 if hasattr (line , 'decode' ): # Python 2
220224 # The line could contain multi-byte characters
221225 try :
@@ -1189,6 +1193,7 @@ def __init__(self, filename=None, lines=None,
11891193 self ._logical_checks = options .logical_checks
11901194 self ._ast_checks = options .ast_checks
11911195 self .max_line_length = options .max_line_length
1196+ self .multiline = False # in a multiline string?
11921197 self .hang_closing = options .hang_closing
11931198 self .verbose = options .verbose
11941199 self .filename = filename
@@ -1237,16 +1242,9 @@ def readline(self):
12371242 self .line_number += 1
12381243 if self .line_number > len (self .lines ):
12391244 return ''
1240- return self .lines [self .line_number - 1 ]
1241-
1242- def readline_check_physical (self ):
1243- """
1244- Check and return the next physical line. This method can be
1245- used to feed tokenize.generate_tokens.
1246- """
1247- line = self .readline ()
1248- if line :
1249- self .check_physical (line )
1245+ line = self .lines [self .line_number - 1 ]
1246+ if self .indent_char is None and line [:1 ] in WHITESPACE :
1247+ self .indent_char = line [0 ]
12501248 return line
12511249
12521250 def run_check (self , check , argument_names ):
@@ -1263,8 +1261,6 @@ def check_physical(self, line):
12631261 Run all physical checks on a raw input line.
12641262 """
12651263 self .physical_line = line
1266- if self .indent_char is None and line [:1 ] in WHITESPACE :
1267- self .indent_char = line [0 ]
12681264 for name , check , argument_names in self ._physical_checks :
12691265 result = self .run_check (check , argument_names )
12701266 if result is not None :
@@ -1352,13 +1348,47 @@ def check_ast(self):
13521348 def generate_tokens (self ):
13531349 if self ._io_error :
13541350 self .report_error (1 , 0 , 'E902 %s' % self ._io_error , readlines )
1355- tokengen = tokenize .generate_tokens (self .readline_check_physical )
1351+ tokengen = tokenize .generate_tokens (self .readline )
13561352 try :
13571353 for token in tokengen :
13581354 yield token
1355+ self .maybe_check_physical (token )
13591356 except (SyntaxError , tokenize .TokenError ):
13601357 self .report_invalid_syntax ()
13611358
1359+ def maybe_check_physical (self , token ):
1360+ """
1361+ If appropriate (based on token), check current physical line(s).
1362+ """
1363+ # This is called after every token, but we only want to take action
1364+ # after a token that ends a line.
1365+ if token [0 ] in (tokenize .NEWLINE , tokenize .NL ):
1366+ # Obviously, a newline token ends a single physical line.
1367+ self .check_physical (token [4 ])
1368+ elif token [0 ] == tokenize .STRING and token [1 ].count ('\n ' ):
1369+ # Less obviously, a string that contains newlines is a
1370+ # multiline string, either triple-quoted or with internal
1371+ # newlines backslash-escaped. Check every physical line in the
1372+ # string *except* for the last one: its newline is outside of
1373+ # the multiline string, so we consider it a regular physical
1374+ # line, and will check it like any other physical line.
1375+ #
1376+ # Subtleties:
1377+ # - we don't *completely* ignore the last line; if it contains
1378+ # the magical "# noqa" comment, we disable all physical
1379+ # checks for the entire multiline string
1380+ # - have to wind self.line_number back because initially it
1381+ # points to the last line of the string, and we want
1382+ # check_physical() to give accurate feedback
1383+ if noqa (token [4 ]):
1384+ return
1385+ self .multiline = True
1386+ self .line_number = token [2 ][0 ]
1387+ for line in token [1 ].split ('\n ' )[:- 1 ]:
1388+ self .check_physical (line + '\n ' )
1389+ self .line_number += 1
1390+ self .multiline = False
1391+
13621392 def check_all (self , expected = None , line_offset = 0 ):
13631393 """
13641394 Run all checks on the input file.
0 commit comments