Correctly handle inline tabs in docstrings (#1810)
The `fix_docstring` function expanded all tabs, which caused a difference in the AST representation when those tabs were inline and not leading. This changes the function to only expand leading tabs so inline tabs are preserved. Fixes #1601.
This commit is contained in:
parent
edf1c9dc0f
commit
1d8b4d766d
@ -6744,13 +6744,33 @@ def is_docstring(leaf: Leaf) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def lines_with_leading_tabs_expanded(s: str) -> List[str]:
|
||||
"""
|
||||
Splits string into lines and expands only leading tabs (following the normal
|
||||
Python rules)
|
||||
"""
|
||||
lines = []
|
||||
for line in s.splitlines():
|
||||
# Find the index of the first non-whitespace character after a string of
|
||||
# whitespace that includes at least one tab
|
||||
match = re.match(r"\s*\t+\s*(\S)", line)
|
||||
if match:
|
||||
first_non_whitespace_idx = match.start(1)
|
||||
|
||||
lines.append(
|
||||
line[:first_non_whitespace_idx].expandtabs()
|
||||
+ line[first_non_whitespace_idx:]
|
||||
)
|
||||
else:
|
||||
lines.append(line)
|
||||
return lines
|
||||
|
||||
|
||||
def fix_docstring(docstring: str, prefix: str) -> str:
|
||||
# https://www.python.org/dev/peps/pep-0257/#handling-docstring-indentation
|
||||
if not docstring:
|
||||
return ""
|
||||
# Convert tabs to spaces (following the normal Python rules)
|
||||
# and split into a list of lines:
|
||||
lines = docstring.expandtabs().splitlines()
|
||||
lines = lines_with_leading_tabs_expanded(docstring)
|
||||
# Determine minimum indentation (first line doesn't count):
|
||||
indent = sys.maxsize
|
||||
for line in lines[1:]:
|
||||
|
@ -110,6 +110,32 @@ def ignored_docstring():
|
||||
"""a => \
|
||||
b"""
|
||||
|
||||
|
||||
def docstring_with_inline_tabs_and_space_indentation():
|
||||
"""hey
|
||||
|
||||
tab separated value
|
||||
tab at start of line and then a tab separated value
|
||||
multiple tabs at the beginning and inline
|
||||
mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
|
||||
|
||||
line ends with some tabs
|
||||
"""
|
||||
|
||||
|
||||
def docstring_with_inline_tabs_and_tab_indentation():
|
||||
"""hey
|
||||
|
||||
tab separated value
|
||||
tab at start of line and then a tab separated value
|
||||
multiple tabs at the beginning and inline
|
||||
mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
|
||||
|
||||
line ends with some tabs
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# output
|
||||
|
||||
class MyClass:
|
||||
@ -223,3 +249,28 @@ def believe_it_or_not_this_is_in_the_py_stdlib():
|
||||
def ignored_docstring():
|
||||
"""a => \
|
||||
b"""
|
||||
|
||||
|
||||
def docstring_with_inline_tabs_and_space_indentation():
|
||||
"""hey
|
||||
|
||||
tab separated value
|
||||
tab at start of line and then a tab separated value
|
||||
multiple tabs at the beginning and inline
|
||||
mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
|
||||
|
||||
line ends with some tabs
|
||||
"""
|
||||
|
||||
|
||||
def docstring_with_inline_tabs_and_tab_indentation():
|
||||
"""hey
|
||||
|
||||
tab separated value
|
||||
tab at start of line and then a tab separated value
|
||||
multiple tabs at the beginning and inline
|
||||
mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
|
||||
|
||||
line ends with some tabs
|
||||
"""
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user