Files
stack/tests/bib/test_meta.py
kert 7dffb76801 add Pydantic field metadata, pipeline schema validation, col: tag namespace, and stack.toml config
- SQLTable: add column_meta(), field_descriptions(), to_ddl(), _resolve_type()
- generate_models.py: read DuckDB column comments, emit Field(description=...)
- run_pipeline: validate output columns against SQLTable contract (SchemaError)
- Pipeline.run: pass output class through to runner
- Tag.col(): new namespace for column-level descriptions
- bib/meta: collect_column_comments() and apply_column_comments() for Zotero→DuckDB flow
- stack.toml + src/conf/: centralised config loader with attribute access and path()
- 100% test coverage on all changed files
2026-03-12 13:03:44 -04:00

478 lines
14 KiB
Python

"""Tests for bib.meta — docstring ↔ Zotero bidirectional mapping."""
from __future__ import annotations
import duckdb
from bib.meta import (
apply_column_comments,
collect_column_comments,
expr_fn_tag,
extract_meta_details,
extract_meta_tags,
generate_docstring_refs,
tag_items_from_pipeline,
)
from bib.tag import Tag
# ── extract_meta_tags ─────────────────────────────────────────────
class TestExtractMetaTags:
def test_cclf_ip_section(self):
def fn():
"""CCLF IP Section 2.2.1 "Part A Claims Header File" (p.8-9):"""
tags = extract_meta_tags(fn)
assert len(tags) == 1
assert tags[0].label == "meta:cclf-ip-s2.2.1"
def test_multiple_cclf_sections(self):
def fn():
"""CCLF IP Section 3.1 "Matching MBIs" (p.14):
CCLF IP Section 5.1.1 "Creation of MBI field" (p.19):
"""
tags = extract_meta_tags(fn)
assert len(tags) == 2
labels = {t.label for t in tags}
assert labels == {"meta:cclf-ip-s3.1", "meta:cclf-ip-s5.1.1"}
def test_cclf_section_no_title(self):
def fn():
"""CCLF IP Section 3.1 (p.14):"""
tags = extract_meta_tags(fn)
assert len(tags) == 1
assert tags[0].label == "meta:cclf-ip-s3.1"
def test_cclf_section_no_page(self):
def fn():
"""CCLF IP Section 5.3.1"""
tags = extract_meta_tags(fn)
assert len(tags) == 1
assert tags[0].label == "meta:cclf-ip-s5.3.1"
def test_cfr_reference(self):
def fn():
"""See 42 CFR § 425.502 for details."""
tags = extract_meta_tags(fn)
assert len(tags) == 1
assert tags[0].label == "meta:42-cfr-425.502"
def test_cfr_without_section_symbol(self):
def fn():
"""See 42 CFR 425.502 for details."""
tags = extract_meta_tags(fn)
assert len(tags) == 1
assert tags[0].label == "meta:42-cfr-425.502"
def test_federal_register(self):
def fn():
"""Published at 90 FR 86252."""
tags = extract_meta_tags(fn)
assert len(tags) == 1
assert tags[0].label == "meta:fr-90-86252"
def test_mixed_citations(self):
def fn():
"""CCLF IP Section 2.2 "Part A" (p.8):
See also 42 CFR § 425.502 and 90 FR 86252.
"""
tags = extract_meta_tags(fn)
assert len(tags) == 3
labels = {t.label for t in tags}
assert "meta:cclf-ip-s2.2" in labels
assert "meta:42-cfr-425.502" in labels
assert "meta:fr-90-86252" in labels
def test_deduplication(self):
def fn():
"""CCLF IP Section 2.2 (p.8):
Another ref to CCLF IP Section 2.2 (p.8):
"""
tags = extract_meta_tags(fn)
assert len(tags) == 1
def test_no_docstring(self):
fn = lambda: None # noqa: E731
assert extract_meta_tags(fn) == []
def test_no_citations(self):
def fn():
"""Just a regular function."""
assert extract_meta_tags(fn) == []
def test_real_cclf_function(self):
from aco.express.cclf import stg_beneficiary_xref
tags = extract_meta_tags(stg_beneficiary_xref)
labels = {t.label for t in tags}
assert "meta:cclf-ip-s3.1" in labels
assert "meta:cclf-ip-s5.1.1" in labels
# ── extract_meta_details ──────────────────────────────────────────
class TestExtractMetaDetails:
def test_cclf_ip_details(self):
def fn():
"""CCLF IP Section 2.2.1 "Part A Claims Header File" (p.8-9):"""
details = extract_meta_details(fn)
assert len(details) == 1
d = details[0]
assert d["tag"] == "meta:cclf-ip-s2.2.1"
assert d["source"] == "CCLF Information Packet"
assert d["title"] == "Part A Claims Header File"
assert d["section"] == "2.2.1"
assert d["page"] == "8-9"
def test_cfr_details(self):
def fn():
"""42 CFR § 425.502"""
details = extract_meta_details(fn)
assert len(details) == 1
assert details[0]["source"] == "Code of Federal Regulations"
assert details[0]["title"] == "42 CFR § 425.502"
def test_cclf_dedup(self):
def fn():
"""CCLF IP Section 2.2 (p.8):
Again CCLF IP Section 2.2 (p.8):"""
details = extract_meta_details(fn)
assert len(details) == 1
def test_cfr_dedup(self):
def fn():
"""42 CFR § 425.502 and again 42 CFR § 425.502"""
details = extract_meta_details(fn)
assert len(details) == 1
def test_fr_details(self):
def fn():
"""Published at 90 FR 86252."""
details = extract_meta_details(fn)
assert len(details) == 1
d = details[0]
assert d["source"] == "Federal Register"
assert d["title"] == "90 FR 86252"
assert d["page"] == "86252"
assert d["section"] == ""
def test_fr_dedup(self):
def fn():
"""90 FR 86252 and again 90 FR 86252"""
details = extract_meta_details(fn)
assert len(details) == 1
# ── expr_fn_tag ───────────────────────────────────────────────────
class TestExprFnTag:
def test_intermediate_table(self):
tag = expr_fn_tag("cclf._stg_beneficiary_xref")
assert tag.label == "fn:cclf.stg_beneficiary_xref"
def test_output_table(self):
tag = expr_fn_tag("cclf.medical_claim")
assert tag.label == "fn:cclf.medical_claim"
def test_double_underscore_internal(self):
tag = expr_fn_tag("readmissions._int_encounter")
assert tag.label == "fn:readmissions.int_encounter"
# ── Tag factory methods ───────────────────────────────────────────
class TestTagFactories:
def test_meta_tag(self):
t = Tag.meta("cclf-ip-s2.2.1")
assert t.namespace == "meta"
assert t.value == "cclf-ip-s2.2.1"
assert t.label == "meta:cclf-ip-s2.2.1"
def test_fn_tag(self):
t = Tag.fn("cclf.stg_beneficiary_xref")
assert t.namespace == "fn"
assert t.value == "cclf.stg_beneficiary_xref"
assert t.label == "fn:cclf.stg_beneficiary_xref"
def test_from_label_meta(self):
t = Tag.from_label("meta:cclf-ip-s2.2.1")
assert t.namespace == "meta"
assert t.value == "cclf-ip-s2.2.1"
def test_from_label_fn(self):
t = Tag.from_label("fn:cclf.stg_beneficiary_xref")
assert t.namespace == "fn"
assert t.value == "cclf.stg_beneficiary_xref"
# ── tag_items_from_pipeline ───────────────────────────────────────
class TestTagItemsFromPipeline:
def test_table_tag_fallback(self):
"""When no refs match, falls back to table: tag lookup."""
import narwhals as nw
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(
title="Core Encounter Spec",
tags=["table:test.out"],
)
key = store.create(item)
@nw.narwhalify
def fn(df):
"""CCLF IP Section 9.9 "Fake" (p.1):"""
return df
from aco.express.base import Expr
from aco.pipe.base import Pipeline
expr = Expr(name="test.out", fn=fn, refs=[])
pipeline = Pipeline(exprs=[expr])
report = tag_items_from_pipeline(pipeline, store)
tagged = {k: v for k, v in report.items() if v}
assert len(tagged) > 0
updated = store.get(key)
fn_tags = [t for t in updated.tags if t.startswith("fn:")]
assert len(fn_tags) > 0
def test_tags_matched_items(self):
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(
title="CCLF Information Packet",
tags=["source:cms-cclf-ip", "module:aco"],
)
key = store.create(item)
from aco.pipe.cclf import pipeline
report = tag_items_from_pipeline(pipeline, store)
# At least some expressions should have tagged the item
tagged = {k: v for k, v in report.items() if v}
assert len(tagged) > 0
# Verify the item now has fn: and meta: tags
updated = store.get(key)
fn_tags = [t for t in updated.tags if t.startswith("fn:")]
meta_tags = [t for t in updated.tags if t.startswith("meta:")]
assert len(fn_tags) > 0
assert len(meta_tags) > 0
# ── generate_docstring_refs ───────────────────────────────────────
class TestGenerateDocstringRefs:
def test_no_items(self):
from bib.store import Store
store = Store(":memory:")
refs = generate_docstring_refs("cclf._stg_beneficiary_xref", store)
assert refs == ""
def test_with_tagged_item(self):
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(
title="CCLF Information Packet v41.0",
tags=["fn:cclf.stg_beneficiary_xref"],
institution="CMS",
date_published="2025-07-16",
)
store.create(item)
refs = generate_docstring_refs("cclf._stg_beneficiary_xref", store)
assert "References" in refs
assert "CCLF Information Packet" in refs
# ── generate_pipeline_bibliography ───────────────────────────────
class TestGeneratePipelineBibliography:
def test_returns_refs_for_tagged_exprs(self):
import narwhals as nw
from bib.item import Source
from bib.meta import generate_pipeline_bibliography
from bib.store import Store
store = Store(":memory:")
item = Source(
title="Test Spec",
tags=["fn:test.passthrough"],
institution="CMS",
date_published="2025-01-01",
)
store.create(item)
@nw.narwhalify
def fn(df):
return df
from aco.express.base import Expr
from aco.pipe.base import Pipeline
expr = Expr(name="test._passthrough", fn=fn)
pipeline = Pipeline(exprs=[expr])
result = generate_pipeline_bibliography(pipeline, store)
assert "test._passthrough" in result
assert "Test Spec" in result["test._passthrough"]
def test_empty_pipeline(self):
from bib.meta import generate_pipeline_bibliography
from bib.store import Store
store = Store(":memory:")
from aco.pipe.base import Pipeline
pipeline = Pipeline(exprs=[])
result = generate_pipeline_bibliography(pipeline, store)
assert result == {}
# ── collect_column_comments ──────────────────────────────────────
class TestCollectColumnComments:
def test_collects_col_tags(self):
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(title="CCLF Spec")
key = store.create(item)
store.add_tag(
key,
Tag.col("core.encounter.encounter_id", "Unique encounter ID").label,
)
store.add_tag(
key,
Tag.col("core.encounter.admit_date", "Admission date").label,
)
comments = collect_column_comments(store)
assert comments["core.encounter.encounter_id"] == "Unique encounter ID"
assert comments["core.encounter.admit_date"] == "Admission date"
def test_empty_store_returns_empty(self):
from bib.store import Store
store = Store(":memory:")
assert collect_column_comments(store) == {}
def test_ignores_malformed_col_tags(self):
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(title="Bad tags")
key = store.create(item)
# Tag without = separator
store.add_tag(key, "col:no-equals-sign")
comments = collect_column_comments(store)
assert comments == {}
# ── apply_column_comments ────────────────────────────────────────
class TestApplyColumnComments:
def test_applies_comments_to_duckdb(self):
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(title="Spec")
key = store.create(item)
store.add_tag(
key,
Tag.col("s.t.col_a", "Column A description").label,
)
con = duckdb.connect(":memory:")
con.execute("CREATE SCHEMA s")
con.execute("CREATE TABLE s.t (col_a VARCHAR, col_b INTEGER)")
stmts = apply_column_comments(con, store)
assert len(stmts) == 1
assert "Column A description" in stmts[0]
# Verify comment was actually set
rows = con.execute(
"SELECT comment FROM duckdb_columns() "
"WHERE schema_name = 's' AND table_name = 't' "
"AND column_name = 'col_a'"
).fetchall()
assert rows[0][0] == "Column A description"
con.close()
def test_skips_invalid_column_refs(self):
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(title="Bad ref")
key = store.create(item)
# Only two parts instead of three
store.add_tag(key, "col:schema.table=desc")
con = duckdb.connect(":memory:")
stmts = apply_column_comments(con, store)
assert stmts == []
con.close()
def test_skips_nonexistent_columns(self):
from bib.item import Source
from bib.store import Store
store = Store(":memory:")
item = Source(title="Spec")
key = store.create(item)
store.add_tag(
key,
Tag.col("s.t.nonexistent", "desc").label,
)
con = duckdb.connect(":memory:")
# Table doesn't exist — should not raise
stmts = apply_column_comments(con, store)
assert stmts == []
con.close()