Skip to content

Commit 05b1c69

Browse files
committed
update to new templates
1 parent 2ede8d3 commit 05b1c69

File tree

1 file changed

+58
-56
lines changed

1 file changed

+58
-56
lines changed

scripts/validate_amendment_template.py

Lines changed: 58 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,11 @@ class Section:
6464
class AmendmentTemplateValidator:
6565
"""Validates Amendment specs against the template structure."""
6666

67-
# Map section titles to their expected subsections
68-
# Key is the section title, value is dict of subsection numbers to titles
67+
# Map section title patterns to their expected subsections
68+
# Key is a regex pattern to match section titles,
69+
# value is dict of subsection numbers to titles
6970
SECTION_TEMPLATES = {
70-
"Serialized Types": {
71+
r"SType:": {
7172
"required_subsections": {
7273
"1": "SType Value",
7374
"2": "JSON Representation",
@@ -78,7 +79,7 @@ class AmendmentTemplateValidator:
7879
"3": "Additional Accepted JSON Inputs",
7980
}
8081
},
81-
"Ledger Entries": {
82+
r"Ledger Entry:": {
8283
"required_subsections": {
8384
"1": "Object Identifier",
8485
"2": "Fields",
@@ -94,7 +95,7 @@ class AmendmentTemplateValidator:
9495
"7": "Freeze/Lock",
9596
}
9697
},
97-
"Transactions": {
98+
r"Transaction:": {
9899
"required_subsections": {
99100
"1": "Fields",
100101
"2": "Transaction Fee",
@@ -106,37 +107,46 @@ class AmendmentTemplateValidator:
106107
"5": "Metadata Fields",
107108
}
108109
},
109-
"Permissions": {
110+
r"Permission:": {
110111
"required_subsections": {},
111112
"optional_subsections": {}
112113
},
113-
"API/RPCs": {
114+
r"RPC:": {
114115
"required_subsections": {},
115116
"optional_subsections": {}
116117
},
117118
}
118119

119120
# Placeholder patterns that should not appear in final specs
121+
# These are now in italicized bracket format: _[...]_
120122
PLACEHOLDER_PATTERNS = [
121123
r'\[STypeName\]',
122124
r'\[LedgerEntryName\]',
123125
r'\[TransactionName\]',
124-
r'\[XXXX\]',
126+
r'\[PermissionName\]',
127+
r'\[rpc_method_name\]',
128+
r'0x\[XXXX\]',
125129
r'\[field_name\]',
130+
r'\[FieldName\]',
126131
r'\[api_method_name\]',
127132
r'\[CustomField\d+\]',
128133
r'\[EntryTypeValue\]',
129134
r'\[TYPE\]',
130-
r'\[Yes/No\]',
135+
r'\[Yes/No(?:/Conditional)?\]',
136+
r'\[Standard/Custom(?:/None)?\]',
131137
r'\[Value/N/A\]',
132-
r'\[Description.*?\]',
133-
r'\[Provide.*?\]',
134-
r'\[Specify.*?\]',
135-
r'\[Describe.*?\]',
136-
r'\[List.*?\]',
137-
r'\[If.*?\]',
138-
r'\[Add more.*?\]',
139-
r'\[Remove example.*?\]',
138+
r'\[r-address\]',
139+
r'\[example value\]',
140+
r'_\[Description.*?\]',
141+
r'_\[Provide.*?\]',
142+
r'_\[Specify.*?\]',
143+
r'_\[Describe.*?\]',
144+
r'_\[List.*?\]',
145+
r'_\[If .*?\]',
146+
r'_\[Add more.*?\]',
147+
r'_\[Remove example.*?\]',
148+
r'_\[Any explanatory.*?\]',
149+
r'_\[Detailed explanation.*?\]',
140150
]
141151

142152
def __init__(self, file_path: Path):
@@ -219,12 +229,15 @@ def _validate_has_required_sections(self):
219229
"""Validate that at least one template section exists."""
220230
main_sections = [s for s in self.sections if s.level == 2]
221231

222-
# Get titles of main sections
223-
section_titles = {s.title for s in main_sections}
224-
225232
# Check if at least one template section exists
226-
template_sections = set(self.SECTION_TEMPLATES.keys())
227-
has_template_section = bool(section_titles & template_sections)
233+
has_template_section = False
234+
for section in main_sections:
235+
for pattern in self.SECTION_TEMPLATES.keys():
236+
if re.search(pattern, section.title):
237+
has_template_section = True
238+
break
239+
if has_template_section:
240+
break
228241

229242
if not has_template_section:
230243
# No template sections found - this might be an old spec
@@ -236,13 +249,15 @@ def _validate_section_structure(self):
236249
# Check each main section that matches a template
237250
for section in self.sections:
238251
if section.level == 2:
239-
# Check if this section matches a template
240-
if section.title in self.SECTION_TEMPLATES:
241-
self._validate_subsections(section)
252+
# Check if this section matches a template pattern
253+
for pattern in self.SECTION_TEMPLATES.keys():
254+
if re.search(pattern, section.title):
255+
self._validate_subsections(section, pattern)
256+
break
242257

243-
def _validate_subsections(self, parent_section: Section):
258+
def _validate_subsections(self, parent_section: Section, pattern: str):
244259
"""Validate subsections for a given parent section."""
245-
template = self.SECTION_TEMPLATES.get(parent_section.title)
260+
template = self.SECTION_TEMPLATES.get(pattern)
246261
if not template:
247262
return
248263

@@ -253,39 +268,26 @@ def _validate_subsections(self, parent_section: Section):
253268
if s.number.startswith(parent_num + ".") and s.level == 3
254269
]
255270

256-
# Group subsections by their first-level parent (e.g., 2.1, 2.2)
257-
# This handles cases where there are multiple instances
258-
# (e.g., multiple ledger entries or transactions)
259-
first_level_groups = {}
260-
for s in subsections:
261-
parts = s.number.split('.')
262-
if len(parts) >= 2:
263-
first_level = f"{parts[0]}.{parts[1]}"
264-
if first_level not in first_level_groups:
265-
first_level_groups[first_level] = []
266-
first_level_groups[first_level].append(s)
267-
268-
# For each first-level group, validate required subsections
271+
# For template sections, subsections are directly under the parent
272+
# (e.g., 1.1, 1.2, 1.3 for SType section 1)
273+
# Check each required subsection
269274
required_subs = template["required_subsections"]
270275

271-
for first_level in first_level_groups:
272-
# Check each required subsection
273-
for sub_num, sub_title in required_subs.items():
274-
expected_num = f"{first_level}.{sub_num}"
276+
for sub_num, sub_title in required_subs.items():
277+
expected_num = f"{parent_num}.{sub_num}"
275278

276-
# Find this subsection in the group
277-
found = any(
278-
s.number == expected_num
279-
for s in self.sections
280-
if s.level == 4
281-
)
279+
# Find this subsection
280+
found = any(
281+
s.number == expected_num and s.title == sub_title
282+
for s in subsections
283+
)
282284

283-
if not found:
284-
self.errors.append(ValidationError(
285-
str(self.file_path), parent_section.line_number,
286-
f"Missing required subsection {expected_num} "
287-
f"'{sub_title}' under {parent_section.title}"
288-
))
285+
if not found:
286+
self.errors.append(ValidationError(
287+
str(self.file_path), parent_section.line_number,
288+
f"Missing required subsection {expected_num} "
289+
f"'{sub_title}' under {parent_section.title}"
290+
))
289291

290292
def _validate_no_placeholders(self):
291293
"""Check for template placeholder text that should be replaced."""

0 commit comments

Comments
 (0)