semantics
This commit is contained in:
106
backend/_batch_convert_defs.py
Normal file
106
backend/_batch_convert_defs.py
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Batch convert legacy [DEF:...] / [/DEF:...] annotations to #region/#endregion format.
|
||||
Handles Python, JS, and Svelte files. Removes [SECTION:...] / [/SECTION] markers.
|
||||
"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def process_file(filepath: Path) -> int:
|
||||
"""Process a single file. Returns number of DEF blocks converted."""
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
text = f.read()
|
||||
|
||||
lines = text.split('\n')
|
||||
result = []
|
||||
blocks_converted = 0
|
||||
i = 0
|
||||
n = len(lines)
|
||||
|
||||
while i < n:
|
||||
line = lines[i]
|
||||
stripped = line.rstrip()
|
||||
|
||||
# Extract leading whitespace for indentation preservation
|
||||
indent = re.match(r'^(\s*)', line).group(1)
|
||||
|
||||
# Check for [/DEF:Name] or [/DEF:Name:Type]
|
||||
m = re.match(r'^\s*(#|//)\s*\[/DEF:(\w+(?:\.\w+)*)(?::\w+)?\]\s*$', stripped)
|
||||
if m:
|
||||
name = m.group(2)
|
||||
result.append(f'{indent}# #endregion {name}')
|
||||
blocks_converted += 1
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# Check for [DEF:Name:Type]
|
||||
m = re.match(r'^\s*(#|//)\s*\[DEF:(\w+(?:\.\w+)*):(\w+)\]\s*$', stripped)
|
||||
if m:
|
||||
name = m.group(2)
|
||||
typ = m.group(3)
|
||||
result.append(f'{indent}# #region {name} [C:2] [TYPE {typ}]')
|
||||
blocks_converted += 1
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# Skip [SECTION: ...] and [/SECTION] lines entirely
|
||||
if re.match(r'^\s*(#|//)\s*\[SECTION:', stripped) or re.match(r'^\s*(#|//)\s*\[/SECTION\]', stripped):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# Fix @RELATION BELONGS_TO -> @RELATION BINDS_TO (not handled by earlier passes)
|
||||
if re.match(r'^\s*(#|//)\s*@RELATION\s+BELONGS_TO\b', stripped):
|
||||
line = re.sub(r'(@RELATION\s+)BELONGS_TO\b', r'\1BINDS_TO', line)
|
||||
|
||||
# Fix @RELATION CONTAINS -> @RELATION DEPENDS_ON (not handled by earlier passes)
|
||||
if re.match(r'^\s*(#|//)\s*@RELATION\s+CONTAINS\b', stripped):
|
||||
line = re.sub(r'(@RELATION\s+)CONTAINS\b', r'\1DEPENDS_ON', line)
|
||||
|
||||
# Pass through everything else
|
||||
result.append(line)
|
||||
i += 1
|
||||
|
||||
new_text = '\n'.join(result)
|
||||
|
||||
if new_text == text:
|
||||
return 0
|
||||
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
f.write(new_text)
|
||||
return blocks_converted
|
||||
|
||||
|
||||
def main():
|
||||
total_blocks = 0
|
||||
total_files = 0
|
||||
|
||||
# Process all test files and other files with DEF contracts
|
||||
patterns = [
|
||||
'backend/tests/**/*.py',
|
||||
'frontend/src/**/__tests__/*.js',
|
||||
'frontend/src/**/*.test.js',
|
||||
'merge_spec.py',
|
||||
]
|
||||
|
||||
for pattern in patterns:
|
||||
for filepath in sorted(ROOT.glob(pattern)):
|
||||
if '.venv' in str(filepath) or '__pycache__' in str(filepath):
|
||||
continue
|
||||
try:
|
||||
blocks = process_file(filepath)
|
||||
if blocks > 0:
|
||||
total_files += 1
|
||||
total_blocks += blocks
|
||||
rel = filepath.relative_to(ROOT)
|
||||
print(f" {rel}: {blocks} blocks converted")
|
||||
except Exception as e:
|
||||
print(f" ERROR {filepath}: {e}")
|
||||
|
||||
print(f"\nTotal: {total_files} files, {total_blocks} DEF blocks converted")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user