summaryrefslogtreecommitdiffstats
path: root/Tools/clinic/libclinic
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend@python.org>2024-02-15 22:52:20 (GMT)
committerGitHub <noreply@github.com>2024-02-15 22:52:20 (GMT)
commit58cb634632cd4d27e1348320665bcfa010e9cbb2 (patch)
treec69e29c1945af307c1c12bed8e2d0aa246b5a775 /Tools/clinic/libclinic
parentfd2bb4be3dd802b1957cf37fe68a3634ab054b2e (diff)
downloadcpython-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__.py2
-rw-r--r--Tools/clinic/libclinic/formatting.py50
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])