ontolith.schema¶
ontolith.schema ¶
Schema layer - meta-model, IR, and DSL support.
This module provides schema definition capabilities: - Internal Representation (IR) - canonical JSON format - Class DSL - Python class-based schema definition (M3) - LinkML-aligned YAML front-end (M3)
JSON
module-attribute
¶
A scalar JSON-valued property/attribute type in the class DSL — any
value json.loads accepts (object, array, string, number, bool, or
null), not only a JSON object despite the DSL annotation's dict[str,
Any] typing (a caller-facing convenience, not what storage actually
validates against).
URI
module-attribute
¶
A scalar URI-or-CURIE-valued property/attribute type in the class DSL
(LinkML's uriorcurie, ADR-0013 — a full scheme:... URI or a
prefix:local-name CURIE, either is accepted).
Boolean
module-attribute
¶
A scalar boolean-valued property/attribute type in the class DSL.
Date
module-attribute
¶
A scalar ISO-8601 date-valued property/attribute type in the class DSL.
DateTime
module-attribute
¶
A scalar ISO-8601 datetime-valued property/attribute type in the class DSL.
Float
module-attribute
¶
A scalar float-valued property/attribute type in the class DSL.
Integer
module-attribute
¶
A scalar integer-valued property/attribute type in the class DSL.
Ref
module-attribute
¶
Relation target type: Ref["ConceptName"], e.g. employer: Ref["Organization"] = Relation().
Text
module-attribute
¶
A scalar string-valued property/attribute type in the class DSL.
Concept ¶
Base class for schema concepts (SPEC §6.2).
Example
class Person(Concept): name: Text born: Date | None = None
ConceptDef ¶
Bases: BaseModel
Concept definition in the IR.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Concept name (e.g., "Person", "Organization") |
properties |
dict[str, PropertyDef]
|
Property definitions |
relations |
dict[str, RelationDef]
|
Relation definitions |
description |
str | None
|
Optional description |
validate_no_property_relation_name_collision ¶
Reject a field name declared in both properties and
relations on the same concept (KI-040).
SchemaIR._resolve_field checks properties before relations,
so an unrejected collision would silently make kind_of()
(and value_type_of/temporality_of/cardinality_of) always
resolve to the property, making the relation half permanently
unreachable — every ref write to that name would be rejected as a
kind mismatch it could never satisfy. Not reachable via the class
DSL or the LinkML front-end today (both keep properties/relations
in one namespace), only via a hand-built SchemaIR.
Source code in src/ontolith/schema/ir.py
PropertyDef ¶
Bases: BaseModel
Property definition in the IR.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Property name |
value_type |
Literal['Text', 'Integer', 'Float', 'Boolean', 'Date', 'DateTime', 'URI', 'JSON']
|
Type of value (Text, Integer, Date, etc.) |
cardinality |
Literal['single', 'many']
|
Single value or many (SPEC §6) |
required |
bool
|
Whether the property is required |
temporality |
Literal['static', 'time_varying']
|
How conflicts are handled (static vs time_varying) |
description |
str | None
|
Optional description |
RelationDef ¶
Bases: BaseModel
Relation definition in the IR.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Relation name |
target_concept |
str
|
Target concept name |
cardinality |
Literal['single', 'many']
|
Single reference or many (SPEC §6) |
required |
bool
|
Whether the relation is required |
temporality |
Literal['static', 'time_varying']
|
How conflicts are handled |
inverse |
str | None
|
Inverse relation name (optional) |
description |
str | None
|
Optional description |
SchemaIR ¶
Bases: BaseModel
Complete schema definition in Internal Representation.
This is the canonical format for schema. All DSLs compile to this.
Attributes:
| Name | Type | Description |
|---|---|---|
namespace |
str
|
Namespace this schema belongs to |
version |
int
|
Schema version (monotonically increasing) |
concepts |
dict[str, ConceptDef]
|
Concept definitions by name |
metadata |
dict[str, Any]
|
Optional metadata |
validate_relation_targets ¶
Validate that all relation targets reference existing concepts.
Source code in src/ontolith/schema/ir.py
has_predicate ¶
Return whether a dotted "Concept.field" predicate is declared in this schema.
has_concept ¶
temporality_of ¶
Resolve the declared temporality of a predicate (SPEC §10.1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
predicate
|
str
|
Dotted predicate, e.g. "Person.name" or "Person.employer" |
required |
Returns:
| Type | Description |
|---|---|
Literal['static', 'time_varying']
|
The property's or relation's declared temporality, or "static" |
Literal['static', 'time_varying']
|
(SPEC's stated default) if unresolvable. |
Source code in src/ontolith/schema/ir.py
cardinality_of ¶
Resolve the declared cardinality of a predicate (SPEC §4, ADR-0017).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
predicate
|
str
|
Dotted predicate, e.g. "Person.name" or "Person.phone" |
required |
Returns:
| Type | Description |
|---|---|
Literal['single', 'many']
|
The property's or relation's declared cardinality, or "single" |
Literal['single', 'many']
|
(the schema default) if unresolvable. |
Source code in src/ontolith/schema/ir.py
value_type_of ¶
Resolve the declared value_type of a literal property predicate (SPEC §4, KI-031).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
predicate
|
str
|
Dotted predicate, e.g. "Person.name" or "Person.age" |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The declared value_type, or None if the predicate is |
str | None
|
unresolvable or resolves to a RelationDef — relations have no |
str | None
|
value_type. Use |
str | None
|
directly (KI-040) rather than inferring it from a |
Source code in src/ontolith/schema/ir.py
kind_of ¶
Resolve whether a predicate is declared a property or a relation (SPEC §4, KI-040).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
predicate
|
str
|
Dotted predicate, e.g. "Person.name" or "Person.employer" |
required |
Returns:
| Type | Description |
|---|---|
Literal['property', 'relation'] | None
|
|
Literal['property', 'relation'] | None
|
unresolvable (schema-less namespace, or not declared in this |
Literal['property', 'relation'] | None
|
schema version). |
Source code in src/ontolith/schema/ir.py
to_json ¶
from_json
classmethod
¶
Property ¶
Property(
*,
cardinality: Cardinality = "single",
required: bool | None = None,
temporality: Temporality = "static",
description: str | None = None,
) -> Any
Field spec for a property, used as a class-body default.
Plain annotations (name: Text) are sufficient for static, single-valued,
optional properties. Use Property(...) to declare temporality="time_varying",
non-default cardinality, or a description on a property.
required defaults to None, meaning "infer from the annotation" — a bare
Integer is required, Integer | None is optional — exactly as if no
Property(...) spec were attached at all. Pass required=True/False
explicitly only to override what the annotation itself already states.
Example
salary: Integer = Property(temporality="time_varying")
Source code in src/ontolith/schema/dsl.py
Relation ¶
Relation(
*,
inverse: str | None = None,
cardinality: Cardinality = "single",
required: bool | None = None,
temporality: Temporality = "static",
description: str | None = None,
) -> Any
Field spec for a relation, used as a class-body default (SPEC §6.2).
required defaults to None, meaning "infer from the annotation" — a
bare Ref["X"] is required, Ref["X"] | None is optional — exactly like
a relation with no Relation(...) spec at all. Pass required=True/False
explicitly only to override what the annotation itself already states.
Example
employer: Ref["Organization"] = Relation(inverse="employees")
Source code in src/ontolith/schema/dsl.py
compile_schema ¶
compile_schema(
namespace: str,
version: int,
*concepts: type[Concept],
metadata: dict[str, Any] | None = None,
) -> SchemaIR
Compile Concept subclasses into a SchemaIR (SPEC §6.1: classes -> IR).
Explicit — takes the concepts to include rather than tracking every
Concept subclass ever defined in a hidden global registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
namespace
|
str
|
Namespace this schema belongs to |
required |
version
|
int
|
Schema version (monotonically increasing) |
required |
concepts
|
type[Concept]
|
Concept subclasses to compile |
()
|
metadata
|
dict[str, Any] | None
|
Optional schema-level metadata |
None
|
Returns:
| Type | Description |
|---|---|
SchemaIR
|
SchemaIR containing the compiled concepts |
Raises:
| Type | Description |
|---|---|
SchemaError
|
If a relation references a concept not among |
Source code in src/ontolith/schema/dsl.py
generate_class_stubs ¶
Decompile a SchemaIR into Concept subclass source text (SPEC §6.1: IR -> classes).
Output is deterministic (concepts sorted by name, fields in declaration order as stored in the IR dicts) so repeated calls on the same IR are byte-identical.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
schema
|
SchemaIR
|
SchemaIR to decompile |
required |
Returns:
| Type | Description |
|---|---|
str
|
Formatted Python source defining one Concept subclass per concept |