Ports the leaf data-layer modules and validates them: - mschema/ (models, eligibility, merge, render), db/ (connection, sampling, introspect, fetch_ca), rest/client.py -- renamed psdwp3->nsp, verbatim. - L0 (testcontainers, real Postgres): db connection read-only enforcement (psd_ro cannot CREATE/INSERT), introspect against a known schema (tables, columns, types, comments, FKs, enum, composite PK), sampling most-frequent values + truncation reporting. 15 tests, ~4s. - L1 (fake data): rest/client RPC contract (mocked transport -- X-API-Key header, payloads, base_url slash handling, HTTP/network error surfacing), mschema/render 3 formats (markdown, mschema-text, schema-dict) + eligibility rules (wide_text excluded, short_text/numeric/enum/temporal/ boolean eligible, annotation override wins). 25 tests. pyproject registers l0/l2 markers + addopts '-m not l2' (L2 opt-in). Deferred to their dependency-porting tasks: test_rrf.py (search needs vectorstore, B3) and the 11 CLI contract tests (need _guards/session, wired when each command lands). 'Not assumed reliable' now has real teeth for the data layer; CLI/search contracts follow.
16 lines
627 B
Python
16 lines
627 B
Python
from nsp.mschema.models import Annotations, PhysicalSchema
|
|
|
|
|
|
def find_orphans(physical: PhysicalSchema, annotations: Annotations) -> list[str]:
|
|
"""Annotazioni che puntano a oggetti spariti dal fisico. Non le rimuove mai."""
|
|
orphans: list[str] = []
|
|
for table_name, table_ann in annotations.tables.items():
|
|
table = physical.tables.get(table_name)
|
|
if table is None:
|
|
orphans.append(table_name)
|
|
continue
|
|
for column_name in table_ann.columns:
|
|
if column_name not in table.columns:
|
|
orphans.append(f"{table_name}.{column_name}")
|
|
return orphans
|