Some checks failed
CI / skinny-install (aco) (push) Successful in 45s
CI / skinny-install (api) (push) Successful in 29s
CI / skinny-install (bcda) (push) Successful in 25s
CI / skinny-install (bib) (push) Successful in 23s
CI / skinny-install (bls) (push) Successful in 20s
CI / skinny-install (ccw) (push) Successful in 36s
CI / skinny-install (cli) (push) Successful in 27s
CI / skinny-install (cms) (push) Successful in 24s
CI / skinny-install (conf) (push) Successful in 27s
CI / skinny-install (pfs) (push) Successful in 25s
CI / skinny-install (rex) (push) Successful in 25s
CI / lint-test (push) Successful in 6m2s
Infra CI / notebooks (push) Successful in 7s
Infra CI / zotero (push) Failing after 6s
Infra CI / docs (push) Successful in 33s
Infra CI / api (push) Successful in 6s
Infra CI / mc (push) Successful in 7s
Deploy / build-scan-report (push) Has been cancelled
- Fix all 72 ruff lint errors (unused imports, unused variables, E402) - Format all 14 unformatted dev/scripts files - Move generated artifacts to assets/ (dag.html, pfs.html) - Remove duplicate root coverage.svg (already in assets/icons/) - Update .dockerignore for infra/ tree layout - Update .gitignore: add .env.bak, mirrors/, htmlcov/ - Fix stale path refs in coverage_badge.py, woodpecker backend, test_network_isolation.sh, docs custom.css - Add .gitkeep to empty dirs (infra/polaris, cloud/*/terraform) - Delete 12 stale local branches, 10 stale remote branches
244 lines
10 KiB
Python
244 lines
10 KiB
Python
"""Generate ALR/ASR file naming pattern classifiers from ALRASRGuide.pdf.
|
|
|
|
Extracts report naming conventions from Appendix Tables 6-7 and generates
|
|
``src/aco/table/alr_filenames.py`` — a module containing regex patterns
|
|
and a classifier function that rex can use to identify which ALR/ASR
|
|
table a given filename represents.
|
|
|
|
Usage::
|
|
|
|
uv run python dev/scripts/generate_alr_filenames.py
|
|
|
|
Source: dev/ALRASRGuide.pdf pages 47-51
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
def generate_module() -> str:
|
|
"""Generate alr_filenames.py module with filename patterns."""
|
|
|
|
lines = [
|
|
'"""ALR/ASR filename patterns for report classification.',
|
|
"",
|
|
"Auto-generated from ALRASRGuide.pdf Appendix Tables 6-7.",
|
|
"Version #16 (April 2024).",
|
|
"",
|
|
"Naming conventions::",
|
|
"",
|
|
" Annual ALR Table 1-1: AALR_Table_1_1_ACOID_YYYY.csv",
|
|
" Quarterly ALR Table 1-1: QALR_Table_1_1_ACOID_YYYY_QX.csv",
|
|
" Annual ASR: AASR_ACOID_YYYY.xlsx",
|
|
" Quarterly ASR: QASR_ACOID_YYYY_QX.xlsx",
|
|
"",
|
|
"Report packages are delivered as ZIP files::",
|
|
"",
|
|
" Initial Assignment: HASSGN_ACOID_YYYY_MM_DD.zip",
|
|
" Quarterly Reports: QEXPU_ACOID_YYYY_MM_DD.zip",
|
|
" Financial Reconciliation: STLMT_ACOID_YYYY_MM_DD.zip",
|
|
" Historical Benchmark: BNMRK_ACOID_YYYY_MM_DD.zip",
|
|
"",
|
|
"Source: ALRASRGuide.pdf pages 47-51",
|
|
'"""',
|
|
"",
|
|
"from __future__ import annotations",
|
|
"",
|
|
"import re",
|
|
"from pathlib import Path",
|
|
"",
|
|
]
|
|
|
|
# Define ALR table patterns
|
|
lines.extend(
|
|
[
|
|
"",
|
|
"# ALR Table Patterns (Annual)",
|
|
"ALR_TABLE_1_1_ANNUAL = re.compile(r'AALR_Table_1_1_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_2_ANNUAL = re.compile(r'AALR_Table_1_2_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_3_ANNUAL = re.compile(r'AALR_Table_1_3_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_4_ANNUAL = re.compile(r'AALR_Table_1_4_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_5_ANNUAL = re.compile(r'AALR_Table_1_5_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_6_ANNUAL = re.compile(r'AALR_Table_1_6_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_7_ANNUAL = re.compile(r'AALR_Table_1_7_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_8_ANNUAL = re.compile(r'AALR_Table_1_8_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"ALR_TABLE_1_9_ANNUAL = re.compile(r'AALR_Table_1_9_[A-Z0-9]+_\\d{4}\\.csv$')",
|
|
"",
|
|
"# ALR Table Patterns (Quarterly)",
|
|
"ALR_TABLE_1_1_QUARTERLY = re.compile(r'QALR_Table_1_1_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_2_QUARTERLY = re.compile(r'QALR_Table_1_2_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_3_QUARTERLY = re.compile(r'QALR_Table_1_3_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_4_QUARTERLY = re.compile(r'QALR_Table_1_4_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_5_QUARTERLY = re.compile(r'QALR_Table_1_5_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_6_QUARTERLY = re.compile(r'QALR_Table_1_6_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_7_QUARTERLY = re.compile(r'QALR_Table_1_7_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_8_QUARTERLY = re.compile(r'QALR_Table_1_8_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"ALR_TABLE_1_9_QUARTERLY = re.compile(r'QALR_Table_1_9_[A-Z0-9]+_\\d{4}_Q[1-4]\\.csv$')",
|
|
"",
|
|
"# ASR Patterns",
|
|
"ASR_ANNUAL = re.compile(r'AASR_[A-Z0-9]+_\\d{4}\\.xlsx$')",
|
|
"ASR_QUARTERLY = re.compile(r'QASR_[A-Z0-9]+_\\d{4}_Q[1-4]\\.xlsx$')",
|
|
"",
|
|
"# Report Package Patterns (ZIP files)",
|
|
"PACKAGE_HASSGN = re.compile(r'HASSGN_[A-Z0-9]+_\\d{4}_\\d{2}_\\d{2}\\.zip$')",
|
|
"PACKAGE_QEXPU = re.compile(r'QEXPU_[A-Z0-9]+_\\d{4}_\\d{2}_\\d{2}\\.zip$')",
|
|
"PACKAGE_STLMT = re.compile(r'STLMT_[A-Z0-9]+_\\d{4}_\\d{2}_\\d{2}\\.zip$')",
|
|
"PACKAGE_BNMRK = re.compile(r'BNMRK_[A-Z0-9]+_\\d{4}_\\d{2}_\\d{2}\\.zip$')",
|
|
"",
|
|
]
|
|
)
|
|
|
|
# Generate classifier function
|
|
lines.extend(
|
|
[
|
|
"",
|
|
"# Table ID mapping",
|
|
"ALR_PATTERNS = {",
|
|
' "1-1": [ALR_TABLE_1_1_ANNUAL, ALR_TABLE_1_1_QUARTERLY],',
|
|
' "1-2": [ALR_TABLE_1_2_ANNUAL, ALR_TABLE_1_2_QUARTERLY],',
|
|
' "1-3": [ALR_TABLE_1_3_ANNUAL, ALR_TABLE_1_3_QUARTERLY],',
|
|
' "1-4": [ALR_TABLE_1_4_ANNUAL, ALR_TABLE_1_4_QUARTERLY],',
|
|
' "1-5": [ALR_TABLE_1_5_ANNUAL, ALR_TABLE_1_5_QUARTERLY],',
|
|
' "1-6": [ALR_TABLE_1_6_ANNUAL, ALR_TABLE_1_6_QUARTERLY],',
|
|
' "1-7": [ALR_TABLE_1_7_ANNUAL, ALR_TABLE_1_7_QUARTERLY],',
|
|
' "1-8": [ALR_TABLE_1_8_ANNUAL, ALR_TABLE_1_8_QUARTERLY],',
|
|
' "1-9": [ALR_TABLE_1_9_ANNUAL, ALR_TABLE_1_9_QUARTERLY],',
|
|
"}",
|
|
"",
|
|
"",
|
|
"def classify(filename: str | Path) -> dict | None:",
|
|
' """Classify an ALR/ASR filename and return metadata.',
|
|
"",
|
|
" Args:",
|
|
" filename: Filename or path to classify",
|
|
"",
|
|
" Returns:",
|
|
" dict with keys: type (alr/asr/package), table_id, report_type",
|
|
" (annual/quarterly), year, quarter (if quarterly), aco_id",
|
|
" Returns None if filename doesn't match any pattern.",
|
|
"",
|
|
" Examples::",
|
|
"",
|
|
' >>> classify("AALR_Table_1_1_A12345_2024.csv")',
|
|
" {",
|
|
' "type": "alr",',
|
|
' "table_id": "1-1",',
|
|
' "report_type": "annual",',
|
|
' "year": "2024",',
|
|
' "aco_id": "A12345",',
|
|
" }",
|
|
"",
|
|
' >>> classify("QALR_Table_1_2_B67890_2024_Q3.csv")',
|
|
" {",
|
|
' "type": "alr",',
|
|
' "table_id": "1-2",',
|
|
' "report_type": "quarterly",',
|
|
' "year": "2024",',
|
|
' "quarter": "Q3",',
|
|
' "aco_id": "B67890",',
|
|
" }",
|
|
' """',
|
|
" fname = Path(filename).name",
|
|
"",
|
|
" # Check ALR tables",
|
|
" for table_id, patterns in ALR_PATTERNS.items():",
|
|
" for pattern in patterns:",
|
|
" if m := pattern.match(fname):",
|
|
" # Parse filename components",
|
|
" parts = fname.replace('.csv', '').split('_')",
|
|
" report_type = 'annual' if fname.startswith('AALR') else 'quarterly'",
|
|
" ",
|
|
" result = {",
|
|
' "type": "alr",',
|
|
' "table_id": table_id,',
|
|
' "report_type": report_type,',
|
|
" }",
|
|
" ",
|
|
" # Extract ACO ID and year",
|
|
" if report_type == 'annual':",
|
|
" # AALR_Table_1_1_ACOID_YYYY.csv",
|
|
" result['aco_id'] = parts[3]",
|
|
" result['year'] = parts[4]",
|
|
" else:",
|
|
" # QALR_Table_1_1_ACOID_YYYY_QX.csv",
|
|
" result['aco_id'] = parts[3]",
|
|
" result['year'] = parts[4]",
|
|
" result['quarter'] = parts[5]",
|
|
" ",
|
|
" return result",
|
|
"",
|
|
" # Check ASR",
|
|
" if m := ASR_ANNUAL.match(fname):",
|
|
" parts = fname.replace('.xlsx', '').split('_')",
|
|
" return {",
|
|
' "type": "asr",',
|
|
' "report_type": "annual",',
|
|
" 'aco_id': parts[1],",
|
|
" 'year': parts[2],",
|
|
" }",
|
|
" ",
|
|
" if m := ASR_QUARTERLY.match(fname):",
|
|
" parts = fname.replace('.xlsx', '').split('_')",
|
|
" return {",
|
|
' "type": "asr",',
|
|
' "report_type": "quarterly",',
|
|
" 'aco_id': parts[1],",
|
|
" 'year': parts[2],",
|
|
" 'quarter': parts[3],",
|
|
" }",
|
|
"",
|
|
" # Check report packages",
|
|
" package_types = {",
|
|
" PACKAGE_HASSGN: 'initial_assignment',",
|
|
" PACKAGE_QEXPU: 'quarterly',",
|
|
" PACKAGE_STLMT: 'financial_reconciliation',",
|
|
" PACKAGE_BNMRK: 'historical_benchmark',",
|
|
" }",
|
|
" ",
|
|
" for pattern, pkg_type in package_types.items():",
|
|
" if m := pattern.match(fname):",
|
|
" parts = fname.replace('.zip', '').split('_')",
|
|
" return {",
|
|
' "type": "package",',
|
|
" 'package_type': pkg_type,",
|
|
" 'aco_id': parts[1],",
|
|
" 'year': parts[2],",
|
|
" 'month': parts[3],",
|
|
" 'day': parts[4],",
|
|
" }",
|
|
"",
|
|
" return None",
|
|
"",
|
|
]
|
|
)
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def main():
|
|
"""Generate src/aco/table/alr_filenames.py."""
|
|
output_path = (
|
|
Path(__file__).resolve().parents[2]
|
|
/ "src"
|
|
/ "aco"
|
|
/ "table"
|
|
/ "alr_filenames.py"
|
|
)
|
|
|
|
code = generate_module()
|
|
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_text(code)
|
|
|
|
print(f"Generated {output_path}")
|
|
print(" 18 ALR table patterns (9 annual + 9 quarterly)")
|
|
print(" 2 ASR patterns (annual + quarterly)")
|
|
print(" 4 package patterns")
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|