Working with graphs

Patterns for multiple resources, merging graphs, and small helpers over a pyoxigraph-backed Store with type awareness.

Batch export

from triplemodel import models_to_graph

people = [
    Person(slug="alice", name="Alice"),
    Person(slug="bob", name="Bob"),
]
graph = models_to_graph(people)

Merge into an existing store (note: an empty Store() is falsy in Python — pass it explicitly):

from triplemodel import Store

existing = Store()
models_to_graph(people, existing)

Batch import

everyone = Person.all_from_graph(graph)
by_slug = {p.slug: p for p in everyone}

Only subjects with rdf:type matching Rdf.type_uri are returned. Blank-node subjects are skipped. Override the type filter with type_uri= when needed.

File helpers

from triplemodel import load_models, dump_model

people = load_models("people.ttl", Person)
dump_model(people[0], "alice.ttl", format="turtle")

See File I/O (parse and serialize) for parse_url and subclass dispatch=True.

Merge graphs

from triplemodel import merge_graphs

g_alice = Person(slug="alice", name="Alice").to_graph()
g_bob = Person(slug="bob", name="Bob").to_graph()
combined = merge_graphs(g_alice, g_bob)

When merging graphs that contain blank nodes, node identity is preserved within each parse — do not assume unrelated parses share blank-node ids.

Graph helpers

from triplemodel import graph_value, graph_set, objects_for_field

uri = person.subject_uri()
g = person.to_graph()

name = graph_value(g, uri, f"{FOAF}name", Person, "name")  # on_duplicate="first" (default)

# Match import duplicate policy:
# graph_value(..., on_duplicate="warn")  # or "error"

graph_set(g, uri, f"{FOAF}name", "Alicia")  # remove-then-add for functional property
graph_set(g, uri, f"{FOAF}age", None)       # remove all objects for predicate

nicks = objects_for_field(g, uri, Person, "nick")  # list[str] for list fields

These helpers use the model’s predicate resolution (including CURIE expansion from Rdf.prefixes).

For MultiLangString fields, graph_value returns a MultiLangString, while objects_for_field returns list[LangString]. graph_set does not accept MultiLangString — update the model and use sync_to_graph instead (see RDF lists and language-tagged literals).

Low-level triple access

triples = person.to_triples()
# list of (subject, predicate, object) — subject may be str or BNode for bnode embed
from triplemodel import model_to_triples, model_to_graph, graph_to_model

Use when building pipelines that are not method-oriented.

Serialize for debugging

print(person.to_graph().serialize(format="turtle"))

Skolemize and shared graphs

When Rdf.skolemize_export / Rdf.skolemize_import is enabled (or you pass skolemize= / de_skolemize= on to_graph, from_graph, or sync_to_graph), skolemization runs on the entire Store you pass in—not only triples owned by the resource you are loading or syncing. If multiple resources share one store, blank-node handling for one operation can affect unrelated triples. Use a dedicated store per resource, or disable skolemization, when you need isolation.