in src/doc_builder/style_doc.py [0:0]
def style_docstring(docstring, max_len):
"""
Style a docstring by making sure there is no useless whitespace and the maximum horizontal space is used.
Args:
docstring (`str`): The docstring to style.
max_len (`int`): The maximum length of each line.
Returns:
`str`: The styled docstring
"""
if is_empty_line(docstring):
return docstring
lines = docstring.split("\n")
new_lines = []
# Initialization
current_paragraph = None
current_indent = -1
in_code = False
param_indent = -1
prefix = ""
black_errors = []
# Special case for docstrings that begin with continuation of Args with no Args block.
idx = 0
while idx < len(lines) and is_empty_line(lines[idx]):
idx += 1
if (
len(lines[idx]) > 1
and lines[idx].rstrip().endswith(":")
and find_indent(lines[idx + 1]) > find_indent(lines[idx])
):
param_indent = find_indent(lines[idx])
idx = 0
while idx < len(lines):
line = lines[idx]
# Doing all re searches once for the ones we need to repeat.
list_search = _re_list.search(line)
code_search = _re_code.search(line)
args_search = _re_args.search(line)
tip_search = _re_tip.search(line)
# Are we starting a new paragraph?
# New indentation or new line:
new_paragraph = find_indent(line) != current_indent or is_empty_line(line)
# List item
new_paragraph = new_paragraph or list_search is not None
# Code block beginning
new_paragraph = new_paragraph or code_search is not None
# Beginning/end of tip
new_paragraph = new_paragraph or tip_search is not None
# Beginning of Args
new_paragraph = new_paragraph or args_search is not None
# In this case, we treat the current paragraph
if not in_code and new_paragraph and current_paragraph is not None and len(current_paragraph) > 0:
paragraph = " ".join(current_paragraph)
new_lines.append(format_text(paragraph, max_len, prefix=prefix, min_indent=current_indent))
# A blank line may be missing before the start of an argument block
if args_search is not None and not is_empty_line(current_paragraph[-1]):
new_lines.append("")
current_paragraph = None
if code_search is not None:
if not in_code:
current_paragraph = []
current_indent = len(code_search.groups()[0])
current_code = code_search.groups()[1]
prefix = ""
if current_indent < param_indent:
param_indent = -1
else:
current_indent = -1
code = "\n".join(current_paragraph)
if current_code in ["py", "python"]:
formatted_code, error = format_code_example(code, max_len, in_docstring=True)
new_lines.append(formatted_code)
if len(error) > 0:
black_errors.append(error)
else:
new_lines.append(code)
current_paragraph = None
new_lines.append(line)
in_code = not in_code
elif in_code:
current_paragraph.append(line)
elif is_empty_line(line):
current_paragraph = None
current_indent = -1
prefix = ""
new_lines.append(line)
elif list_search is not None:
prefix = list_search.groups()[0]
current_indent = len(prefix)
current_paragraph = [line[current_indent:]]
elif args_search:
new_lines.append(line)
idx += 1
while idx < len(lines) and is_empty_line(lines[idx]):
idx += 1
if idx < len(lines):
param_indent = find_indent(lines[idx])
# We still need to treat that line
idx -= 1
elif tip_search:
# Add a new line before if not present
if not is_empty_line(new_lines[-1]):
new_lines.append("")
new_lines.append(line)
# Add a new line after if not present
if idx < len(lines) - 1 and not is_empty_line(lines[idx + 1]):
new_lines.append("")
elif current_paragraph is None or find_indent(line) != current_indent:
indent = find_indent(line)
# Special behavior for parameters intros.
if indent == param_indent:
# Special rules for some docstring where the Returns blocks has the same indent as the parameters.
if _re_returns.search(line) is not None:
param_indent = -1
new_lines.append(line)
elif len(line) < max_len:
new_lines.append(line)
else:
intro, description = split_line_on_first_colon(line)
new_lines.append(intro + ":")
if len(description) != 0:
if find_indent(lines[idx + 1]) > indent:
current_indent = find_indent(lines[idx + 1])
else:
current_indent = indent + 4
current_paragraph = [description.strip()]
prefix = ""
else:
# Check if we have exited the parameter block
if indent < param_indent:
param_indent = -1
current_paragraph = [line.strip()]
current_indent = find_indent(line)
prefix = ""
elif current_paragraph is not None:
current_paragraph.append(line.lstrip())
idx += 1
if current_paragraph is not None and len(current_paragraph) > 0:
paragraph = " ".join(current_paragraph)
new_lines.append(format_text(paragraph, max_len, prefix=prefix, min_indent=current_indent))
return "\n".join(new_lines), "\n\n".join(black_errors)