There's no domain code to strip — you supply your core namespace and your spec table. Wiring it into your stack is three steps.
The generator resolves each spec's bound class local-name against a namespace
IRI. Default is the neutral http://example.org/ontology/core/; pass your own:
from ontology_config_generator import generate_configs
NS = "https://ontology.acme.example/core/" # YOUR core ontology IRI
generate_configs(spec_table, "extension.ttl", "out/", namespace=NS)A class local-name "Region" in a spec then binds to <NS>Region in the graph.
Each row says: which file, which JSON key holds the extracted list, and which class(es) feed it. Keep it in one place — it is the auditable map from ontology concepts to config files.
from ontology_config_generator import ConfigSpec
SPEC_TABLE = [
ConfigSpec(filename="regions.json", extract={"regions": "Region"}),
ConfigSpec(filename="roles.json", extract={"roles": "Role"}),
# one key can pull from SEVERAL classes (extractions are concatenated):
ConfigSpec(filename="parties.json", extract={"parties": ["Person", "Organization"]}),
# a config the TTL has nothing to extract for keeps a fixed shape:
ConfigSpec(filename="glossary.json", static={"terms": [], "synonyms": []}),
]Or keep it as JSON and load it (handy for non-engineer review / version control):
python -m ontology_config_generator \
--extension extension.ttl --spec-table specs.json \
--output-dir out/ --namespace https://ontology.acme.example/core/If your runtime expects a fixed JSON shape even when the ontology has nothing to
contribute yet, keep read-only starter templates and pass starter_dir=. The
starter is the base; a non-empty extraction overrides its list, an empty one
leaves it intact:
generate_configs(spec_table, "extension.ttl", "out/",
namespace=NS, starter_dir="config_templates/")For each bound class, extract_named returns every named subclass and
named individual as {"id", "label", "description"}:
id— the IRI's last path/fragment segment (the local name);label—rdfs:labelif present, elseid;description—rdfs:commentif present, else"".
Blank nodes are skipped and each subject appears once. If you need richer fields
(extra data properties, etc.), wrap or replace extract_named and keep the
generate_configs flow — the merge + provenance stamping is independent of the
row shape.
- Determinism — don't introduce an LLM or randomness into the compile; the whole point is that configs are a reproducible function of the graph.
- Degrade-open — keep the missing/unparseable-extension path yielding valid starter-shaped configs, so the step is safe to run unconditionally in a pipeline.
- The lazy
rdflibimport — keep heavy imports inside the functions that parse a graph soimport ontology_config_generatorworks without rdflib. - The
_generatedprovenance block — it's what makes a generated config traceable back to its source graph.