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 <ronald.stone@windriver.com>
This commit is contained in:
125
normalize-includes.py
Normal file
125
normalize-includes.py
Normal file
@@ -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 <directory>")
|
||||
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()
|
||||
|
||||
2
tox.ini
2
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
|
||||
|
||||
Reference in New Issue
Block a user