API reference¶
Top level¶
from semantido import (
semantic_table, # the decorator
SemanticDeclarativeBase, # ready-made base
SemanticBase, # mixin for your own base
SemanticLayer, # the IR
SQLAlchemySemanticBridge, # the extraction engine
)
Base classes¶
SemanticDeclarativeBase¶
SemanticBase + SQLAlchemy's DeclarativeBase. Inherit from it and you're done.
SemanticBase¶
Mixin, if you already have a base:
classmethod sync_semantic_layer(concept_registry: ConceptRegistry | None = None) -> SemanticLayer
Walks the registry and re-extracts every table, column, and relationship. No database connection. Deterministic. When a concept_registry is passed, every concept= / <column>_concept reference is validated against it — unresolved references raise ValueError listing all of them — and the registry is attached to the returned layer for export.
classmethod get_semantic_bridge() -> SQLAlchemySemanticBridge
Lazily builds the bridge by walking the MRO for the SQLAlchemy registry. Raises RuntimeError if there isn't one. You rarely need this.
Decorator¶
semantic_table(
description: str,
synonyms: list[str] | None = None,
sql_filters: list[str] | None = None,
application_context: str | None = None,
business_context: str | None = None,
time_dimension: str | None = None,
concept: str | None = None, # v0.4.0 — id of a registered concept
)
Full semantics in the semantic metadata reference.
Exporters¶
from semantido.exporters import (
to_json, to_json_file,
to_markdown, to_markdown_file,
to_osi_dict, to_osi_yaml,
)
JSON¶
to_json(semantic_layer: SemanticLayer, include_empty: bool = False) -> str
to_json_file(layer: SemanticLayer, file_path: str, include_empty: bool = False) -> None
include_empty=False prunes None, [], {} recursively. File output is indented 4.
Markdown¶
to_markdown(layer: SemanticLayer, include_empty: bool = False) -> str
to_markdown_file(layer: SemanticLayer, file_path: str,
include_empty: bool = False, table: bool = False) -> None
table=True emits the table-shaped variant instead of the nested-list one. The function behind it, to_markdown_table, is importable from semantido.exporters.markdown_exporter but isn't part of the top-level export surface — treat it as less stable.
OSI¶
to_osi_dict(
semantic_layer: SemanticLayer,
model_name: str,
description: str | None = None,
instructions: str | None = None,
audit_pattern: re.Pattern = DEFAULT_AUDIT_PATTERN,
) -> dict
to_osi_yaml(
semantic_layer: SemanticLayer,
model_name: str,
path: str | None = None,
**kwargs, # forwarded to to_osi_dict
) -> str
to_osi_yaml requires PyYAML (pip install 'semantido[osi]') and raises a clear ImportError without it. to_osi_dict doesn't. Returns the YAML text whether or not path is given.
Constants in semantido.exporters.osi_exporter:
OSI_SPEC_VERSION |
"0.2.0.dev0" |
DEFAULT_DIALECT |
"ANSI_SQL" |
VENDOR |
"SEMANTIDO" |
DEFAULT_AUDIT_PATTERN |
created/updated/modified/inserted/deleted/loaded/ingested/processed/synced/etl, optional _at/_on/_ts/_time/_timestamp/_date suffix, case-insensitive |
Data model¶
semantido.generators.semantic_layer — plain dataclasses, safe to construct and mutate.
SemanticLayer¶
tables: dict[str, Table]
relationships: list[Relationship]
application_glossary: dict[str, str]
concept_registry: ConceptRegistry | None # v0.4.0
add_table(table: Table)
add_relationship(relationship: Relationship)
to_dict(include_empty: bool = False) -> dict
Deprecated
SemanticLayer.to_json() and .to_file() are deprecated. Use semantido.exporters.to_json / to_json_file.
Table¶
name: str
description: str
columns: list[Column]
primary_key: str | None
schema: str | None = None
synonyms: list[str] | None = None
sql_filters: list[str] | None = None
application_context: str | None = None
business_context: str | None = None
time_dimension: str | None = None
concept: str | None = None # v0.4.0
Column¶
name: str
data_type: str
description: str
privacy_level: PrivacyLevel
sample_values: list[str] | None = None
synonyms: list[str] | None = None
is_foreign_key: bool = False
references: str | None = None # "table.column"
application_rules: list[str] | None = None
is_time_dimension: bool | None = False
time_grain: TimeGrain | None = None
concept: str | None = None # v0.4.0
Relationship¶
from_table: str
to_table: str
join_condition: str
relationship_type: RelationshipType
description: str
Enums¶
PrivacyLevel, TimeGrain, RelationshipType — see the metadata reference.
Concepts — semantido.concepts (v0.4.0)¶
from semantido.concepts import (
ConceptRegistry, Concept, OntologySource,
ConceptRelation, MappingRelation, ExternalMapping,
exact_match, close_match, narrow_match, broad_match, related_match,
)
semantido.concepts is the canonical import path; the same objects live at semantido.generators.concept_registry.
ConceptRegistry¶
| Method | Purpose |
|---|---|
concept(concept_id, definition, *, label=None, synonyms=None, broader=None, narrower=None, same_as=None, related=None, distinct_from=None, external=None) -> Concept |
The only authoring path. Relation kwargs take Concept handles (or iterables); symmetric relations (same_as, related, distinct_from) auto-reciprocate. |
add_source(source: OntologySource) -> None |
Registers a pinned external ontology release. |
find_homonyms() -> dict[str, list[str]] |
Labels/synonyms claimed by more than one concept → their ids. |
subset(concept_ids: set[str]) -> ConceptRegistry |
Self-contained sub-registry closed over the ids via relations. |
validate() -> None |
Referential checks; collects all violations, raises once. |
to_dict() / to_yaml(path=None) |
Serialization; YAML is the sidecar concepts.yaml form. |
Concept¶
Fields: id, label, definition, synonyms, mappings, relations, plus computed definition_checksum — a stable fingerprint of the definition text.
OntologySource¶
OntologySource(name: str, namespace: str, version: str,
location: str | None = None, profile: str | None = None)
version is required: an unpinned mapping cannot be validated or detected as stale.
Mapping helpers¶
exact_match(source, target, because=None) and siblings (close_match, narrow_match, broad_match, related_match) each build an ExternalMapping carrying its SKOS relation — an untyped mapping is unrepresentable.
Full behaviour and worked example: The concept registry.
Requirements¶
Current release: 0.4.0. Python ≥ 3.11 · SQLAlchemy ≥ 2.0 · typing-extensions ≥ 4.5
Extras: osi (PyYAML), dev, publish.