@@ -102,6 +102,7 @@ def lru_cache(maxsize=128): # noqa as it's a fake implementation.
102102 # Methods and nested class and function.
103103 'method' : 1 ,
104104}
105+ MAX_DOC_LENGTH = 72
105106REPORT_FORMAT = {
106107 'default' : '%(path)s:%(row)d:%(col)d: %(code)s %(text)s' ,
107108 'pylint' : '%(path)s:%(row)d: [%(code)s] %(text)s' ,
@@ -1585,9 +1586,64 @@ def python_3000_async_await_keywords(logical_line, tokens):
15851586 )
15861587
15871588
1588- ##############################################################################
1589+ ########################################################################
1590+ @register_check
1591+ def maximum_doc_length (logical_line , max_doc_length , noqa , tokens ):
1592+ r"""Limit all doc lines to a maximum of 72 characters.
1593+
1594+ For flowing long blocks of text (docstrings or comments), limiting
1595+ the length to 72 characters is recommended.
1596+
1597+ Reports warning W505
1598+ """
1599+ if max_doc_length is None or noqa :
1600+ return
1601+
1602+ prev_token = None
1603+ skip_lines = set ()
1604+ # Skip lines that
1605+ for token_type , text , start , end , line in tokens :
1606+ if token_type not in SKIP_COMMENTS .union ([tokenize .STRING ]):
1607+ skip_lines .add (line )
1608+
1609+ for token_type , text , start , end , line in tokens :
1610+ # Skip lines that aren't pure strings
1611+ if token_type == tokenize .STRING and skip_lines :
1612+ continue
1613+ if token_type in (tokenize .STRING , tokenize .COMMENT ):
1614+ # Only check comment-only lines
1615+ if prev_token is None or prev_token in SKIP_TOKENS :
1616+ lines = line .splitlines ()
1617+ for line_num , physical_line in enumerate (lines ):
1618+ if hasattr (physical_line , 'decode' ): # Python 2
1619+ # The line could contain multi-byte characters
1620+ try :
1621+ physical_line = physical_line .decode ('utf-8' )
1622+ except UnicodeError :
1623+ pass
1624+ if start [0 ] + line_num == 1 and line .startswith ('#!' ):
1625+ return
1626+ length = len (physical_line )
1627+ chunks = physical_line .split ()
1628+ if token_type == tokenize .COMMENT :
1629+ if (len (chunks ) == 2 and
1630+ length - len (chunks [- 1 ]) < MAX_DOC_LENGTH ):
1631+ continue
1632+ if len (chunks ) == 1 and line_num + 1 < len (lines ):
1633+ if (len (chunks ) == 1 and
1634+ length - len (chunks [- 1 ]) < MAX_DOC_LENGTH ):
1635+ continue
1636+ if length > max_doc_length :
1637+ doc_error = (start [0 ] + line_num , max_doc_length )
1638+ yield (doc_error , "W505 doc line too long "
1639+ "(%d > %d characters)"
1640+ % (length , max_doc_length ))
1641+ prev_token = token_type
1642+
1643+
1644+ ########################################################################
15891645# Helper functions
1590- ##############################################################################
1646+ ########################################################################
15911647
15921648
15931649if sys .version_info < (3 ,):
@@ -1758,6 +1814,7 @@ def __init__(self, filename=None, lines=None,
17581814 self ._logical_checks = options .logical_checks
17591815 self ._ast_checks = options .ast_checks
17601816 self .max_line_length = options .max_line_length
1817+ self .max_doc_length = options .max_doc_length
17611818 self .multiline = False # in a multiline string?
17621819 self .hang_closing = options .hang_closing
17631820 self .verbose = options .verbose
@@ -2324,8 +2381,8 @@ def get_parser(prog='pycodestyle', version=__version__):
23242381 usage = "%prog [options] input ..." )
23252382 parser .config_options = [
23262383 'exclude' , 'filename' , 'select' , 'ignore' , 'max-line-length' ,
2327- 'hang-closing' , 'count' , 'format' , 'quiet' , 'show-pep8 ' ,
2328- 'show-source' , 'statistics' , 'verbose' ]
2384+ 'max-doc-length' , ' hang-closing' , 'count' , 'format' , 'quiet' ,
2385+ 'show-pep8' , 'show- source' , 'statistics' , 'verbose' ]
23292386 parser .add_option ('-v' , '--verbose' , default = 0 , action = 'count' ,
23302387 help = "print status messages, or debug with -vv" )
23312388 parser .add_option ('-q' , '--quiet' , default = 0 , action = 'count' ,
@@ -2361,6 +2418,10 @@ def get_parser(prog='pycodestyle', version=__version__):
23612418 default = MAX_LINE_LENGTH ,
23622419 help = "set maximum allowed line length "
23632420 "(default: %default)" )
2421+ parser .add_option ('--max-doc-length' , type = 'int' , metavar = 'n' ,
2422+ default = None ,
2423+ help = "set maximum allowed doc line length and perform "
2424+ "these checks (unchecked if not set)" )
23642425 parser .add_option ('--hang-closing' , action = 'store_true' ,
23652426 help = "hang closing bracket instead of matching "
23662427 "indentation of opening bracket's line" )
0 commit comments