Warnings fixed: - datetime.utcnow() → datetime.now(UTC) across 48+ files (src/ + tests/) - datetime.utcnow (callback ref) → lambda: datetime.now(UTC) in model fields (18 files) - Pydantic class Config → model_config = ConfigDict(...) (16 files) - Pydantic .dict() → .model_dump() (8 files) - ConfigDict(allow_population_by_field_name=True) → validate_by_name=True - SQLAlchemy declarative_base() import path updated - FastAPI on_event → lifespan context manager (app.py) - Import sorting (ruff I001) auto-fixed across all files - Fixed broken re-export chains that ruff F401 cleanup broke: _validate_bcp47: service.py now imports from dictionary_validation directly job_to_response: _job_routes.py and test imports from service_utils directly fetch_datasource_metadata: restored re-export in service.py - Added missing TranslateJobService import in _job_routes.py (was deleted by F401) - Added ConfigDict(protected_namespaces=()) for DashboardDatasetItem schema field - pytest.ini: replaced deprecated importmode with asyncio_mode All 440 tests pass with zero deprecation warnings.
107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Batch convert legacy [DEF:...] / [/DEF:...] annotations to #region/#endregion format.
|
|
Handles Python, JS, and Svelte files. Removes [SECTION:...] / [/SECTION] markers.
|
|
"""
|
|
from pathlib import Path
|
|
import re
|
|
|
|
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, 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()
|