From a19a907bfa5878ac43eb9d679426134fb1d30ef7 Mon Sep 17 00:00:00 2001 From: Ron Stone Date: Thu, 4 Dec 2025 12:44:32 +0000 Subject: [PATCH] Replace normalize-includes Replace shell implementation with python script. More flexible solution that adjusts indentation of included content to offset of directive in host file. This allows greater reusability. Change-Id: Ic048f2ad950b686127710dee983ef56f688eda65 Signed-off-by: Ron Stone --- normalize-includes.py | 125 ++++++++++++++++++++++++++++++++++++++++++ tox.ini | 2 +- 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 normalize-includes.py diff --git a/normalize-includes.py b/normalize-includes.py new file mode 100644 index 000000000..a005bef2b --- /dev/null +++ b/normalize-includes.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +import os +import re +import sys +from pathlib import Path + +# Detect a pre-include directive +PRE_INCLUDE_RE = re.compile(r'^(\s*)\.\.\s+pre-include::\s+(.+)$') +# Detect options following the directive +OPTION_RE = re.compile(r'^\s*:(\w[\w-]*):\s*(.*)$') + +def read_included_content(filepath, options): + """Read included file and slice per start-after/end-before, literal, and tab-width.""" + try: + with open(filepath, "r", encoding="utf-8") as f: + lines = f.readlines() + except FileNotFoundError: + return [f".. (error: file not found: {filepath})\n"] + + # Apply start-after + if "start-after" in options: + marker = options["start-after"] + for i, line in enumerate(lines): + if marker in line: + lines = lines[i + 1 :] + break + + # Apply end-before + if "end-before" in options: + marker = options["end-before"] + for i, line in enumerate(lines): + if marker in line: + lines = lines[:i] + break + + # Handle tab-width (default 8 if not provided) + if "tab-width" in options: + try: + width = int(options["tab-width"]) if options["tab-width"] else 8 + lines = [l.expandtabs(width) for l in lines] + except ValueError: + pass # ignore malformed value + + return lines + + +def process_file(path): + """Process one file and expand all pre-include directives.""" + with open(path, "r", encoding="utf-8") as f: + lines = f.readlines() + + output_lines = [] + i = 0 + changed = False + + while i < len(lines): + line = lines[i] + m = PRE_INCLUDE_RE.match(line) + if not m: + output_lines.append(line) + i += 1 + continue + + indent, filename = m.groups() + filename = filename.strip() + options = {} + + # Gather options (start-after, end-before, literal, tab-width, etc.) + j = i + 1 + while j < len(lines): + opt_match = OPTION_RE.match(lines[j]) + if not opt_match: + break + opt_name, opt_value = opt_match.groups() + options[opt_name] = opt_value + j += 1 + + include_path = (Path(path).parent / filename).resolve() + included_lines = read_included_content(include_path, options) + + # Apply literal or standard indentation + if "literal" in options: + # For literal, ensure a blank line before and after if not present + if output_lines and output_lines[-1].strip(): + output_lines.append("\n") + output_lines.extend([indent + l for l in included_lines]) + if included_lines and included_lines[-1].strip(): + output_lines.append("\n") + else: + # Normal include: indent non-empty lines, preserve blank ones + indented = [indent + l if l.strip() else l for l in included_lines] + output_lines.extend(indented) + + changed = True + i = j # Skip over directive and its options + + if changed: + # backup_path = path + ".bak" + # os.rename(path, backup_path) + with open(path, "w", encoding="utf-8") as f: + f.writelines(output_lines) + # print(f"Processed {path} (backup saved as {backup_path})") + print(f"\u2705 Processed {path})") + else: + print(f"No pre-include directives in {path}") + + +def main(): + if len(sys.argv) != 2: + print("Usage: normalize_includes.py ") + sys.exit(1) + + root = Path(sys.argv[1]).resolve() + if not root.is_dir(): + print(f"⚠️ Error: {root} is not a directory") + sys.exit(1) + + for ext in ("*.rst", "*.rest"): + for path in root.rglob(ext): + process_file(path) + + +if __name__ == "__main__": + main() + diff --git a/tox.ini b/tox.ini index f5f5e377e..7beaddc6a 100644 --- a/tox.ini +++ b/tox.ini @@ -26,7 +26,7 @@ commands = python parser.py -l templates/logs_template.rst -e tmp/events.yaml -s 100,200,300,400,500,700,800,900 -ts = -type Log -outputPath doc/source/fault-mgmt/kubernetes/ -sort Yes -product starlingx -replace "|,OR" python parser.py -l templates/alarms_template.rst -e tmp/events.yaml -s 100,200,300,400,500,700,800,900 -ts = -type Alarm -outputPath doc/source/fault-mgmt/openstack/ -sort Yes -product openstack -replace "|,OR" python parser.py -l templates/logs_template.rst -e tmp/events.yaml -s 100,200,300,400,500,700,800,900 -ts = -type Log -outputPath doc/source/fault-mgmt/openstack/ -sort Yes -product openstack -replace "|,OR" - bash ./normalize-includes.sh + python3 ./normalize-includes.py doc/source bash ./dup-abbr-check.sh bash ./fetch-ports-files.sh python py_2_xlsx.py tmp/platform_firewall.py tmp/constants.py tmp/FW_PORTS.xlsx