diff options
author | Erlend E. Aasland <erlend@python.org> | 2024-02-15 22:52:20 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-15 22:52:20 (GMT) |
commit | 58cb634632cd4d27e1348320665bcfa010e9cbb2 (patch) | |
tree | c69e29c1945af307c1c12bed8e2d0aa246b5a775 /Tools/clinic/libclinic | |
parent | fd2bb4be3dd802b1957cf37fe68a3634ab054b2e (diff) | |
download | cpython-58cb634632cd4d27e1348320665bcfa010e9cbb2.zip cpython-58cb634632cd4d27e1348320665bcfa010e9cbb2.tar.gz cpython-58cb634632cd4d27e1348320665bcfa010e9cbb2.tar.bz2 |
gh-113317: Argument Clinic: move linear_format into libclinic (#115518)
Diffstat (limited to 'Tools/clinic/libclinic')
-rw-r--r-- | Tools/clinic/libclinic/__init__.py | 2 | ||||
-rw-r--r-- | Tools/clinic/libclinic/formatting.py | 50 |
2 files changed, 52 insertions, 0 deletions
diff --git a/Tools/clinic/libclinic/__init__.py b/Tools/clinic/libclinic/__init__.py index 1b300b5..6237809 100644 --- a/Tools/clinic/libclinic/__init__.py +++ b/Tools/clinic/libclinic/__init__.py @@ -9,6 +9,7 @@ from .formatting import ( docstring_for_c_string, format_escape, indent_all_lines, + linear_format, normalize_snippet, pprint_words, suffix_all_lines, @@ -33,6 +34,7 @@ __all__ = [ "docstring_for_c_string", "format_escape", "indent_all_lines", + "linear_format", "normalize_snippet", "pprint_words", "suffix_all_lines", diff --git a/Tools/clinic/libclinic/formatting.py b/Tools/clinic/libclinic/formatting.py index 8b3ad7b..873ece6 100644 --- a/Tools/clinic/libclinic/formatting.py +++ b/Tools/clinic/libclinic/formatting.py @@ -4,6 +4,8 @@ import functools import textwrap from typing import Final +from libclinic import ClinicError + SIG_END_MARKER: Final = "--" @@ -171,3 +173,51 @@ def wrap_declarations(text: str, length: int = 78) -> str: lines.append(line.rstrip()) prefix = spaces return "\n".join(lines) + + +def linear_format(text: str, **kwargs: str) -> str: + """ + Perform str.format-like substitution, except: + * The strings substituted must be on lines by + themselves. (This line is the "source line".) + * If the substitution text is empty, the source line + is removed in the output. + * If the field is not recognized, the original line + is passed unmodified through to the output. + * If the substitution text is not empty: + * Each line of the substituted text is indented + by the indent of the source line. + * A newline will be added to the end. + """ + lines = [] + for line in text.split("\n"): + indent, curly, trailing = line.partition("{") + if not curly: + lines.extend([line, "\n"]) + continue + + name, curly, trailing = trailing.partition("}") + if not curly or name not in kwargs: + lines.extend([line, "\n"]) + continue + + if trailing: + raise ClinicError( + f"Text found after '{{{name}}}' block marker! " + "It must be on a line by itself." + ) + if indent.strip(): + raise ClinicError( + f"Non-whitespace characters found before '{{{name}}}' block marker! " + "It must be on a line by itself." + ) + + value = kwargs[name] + if not value: + continue + + stripped = [line.rstrip() for line in value.split("\n")] + value = textwrap.indent("\n".join(stripped), indent) + lines.extend([value, "\n"]) + + return "".join(lines[:-1]) |