TripleModel roadmap

Roadmap for the triplemodel package on PyPI (base class TripleModel). This document tracks planned releases from the current 0.12.0 beta through a stable 1.0.0. Versions follow Semantic Versioning: breaking API changes only on major releases; minors add features; patches fix bugs.

Engine reference: pyoxigraph 0.5.x documentation (model, I/O, store, SPARQL results, migration guide).

Vision: Make RDF a natural persistence and interchange layer for Pydantic-shaped domain models — typed in Python, portable as triples, without bespoke mapping code per project.

Ecosystem: TripleModel is the stateless mapping layer (file parse/serialize from 0.4). SparqlModel (sparqlmodel) is the session, query, and ORM layer and already depends on triplemodel>=0.9,<2. SM-6 tracks SparqlModel 0.4 unified model (SPARQLModel subclasses TripleModel). TripleModel must never depend on SparqlModel.

Document

Purpose

Changelog

Release history

Migrating to TripleModel 0.11.0

0.11.0 breaking changes (rdflib/SHACL removal)

Releasing

PyPI publish checklist

TripleModel project plan

Strategy, principles, priorities

TripleModel and SparqlModel — separation of responsibilities

Boundary contract (both packages)

SparqlModel ecosystem guide (for SparqlModel development)

SparqlModel maintainer guide (copy to SparqlModel repo)

Pre-1.0 commitment: Every 0.x release adds capability until TripleModel exposes all pyoxigraph / Oxigraph features that sensibly map to typed Pydantic models. We orchestrate pyoxigraph; we do not reimplement parsers, stores, or SPARQL engines. We do not build sessions, query compilers, or cascade put semantics — that stays in SparqlModel. 1.0.0 is API stability and production hardening — not further engine churn.

Matrix legend: SM in release sections = required for SparqlModel’s planned triplemodel dependency (see integration milestones).


SparqlModel integration milestones

SparqlModel 0.3 uses an interim _triple.py adapter; 0.4 (Option A) makes SPARQLModel a TripleModel subclass and removes the adapter. TripleModel keeps mapping; SparqlModel keeps session, compiler, and cascade policy.

Milestone

triplemodel deliverable

SparqlModel outcome

SM-0

0.1.x mapping, subject IRI fixes

Historical optional dev pin

SM-1

0.2 — sync/remove, nested models, multi-value, Rdf.prefixes, vocab

Interim adapter wiring

SM-2

0.3 — blanks, RDF lists

Hydration via TripleModel loaders

SM-3

0.4parse / serialize, base URI

Retire duplicate serializers (SparqlModel 0.6)

SM-4

0.5Dataset (if named graphs on models)

Store uses TripleModel dataset helpers

SM-5

0.9–1.0 — API freeze, py.typed, semver

sparqlmodel requires triplemodel>=0.9,<2 (shipped)

SM-6

Subclass-safe mapping API (no SparqlModel code change required)

SparqlModel 0.4SPARQLModel(TripleModel); delete _triple.py

See SparqlModel ROADMAP — 0.4 unified model.

TripleModel will not implement: SPARQLSession, Python where(Model.field == x), SPARQL expression compiler, identity map, FastAPI, or HTTP store — see ECOSYSTEM.md.

0.6 SPARQL helpers (select_models, etc.) are optional conveniences for TripleModel-only users; SparqlModel keeps its own compiler and may use raw graph.query internally.


Oxigraph / pyoxigraph coverage matrix

Status key: done · partial · TBD · out of scope (—)

Oxigraph area

Capability

TripleModel surface

Ver

Terms

URIRef, Literal, XSD datatypes

python_to_term / term_to_python

0.1 done

BNode, anonymous subjects/objects

Rdf.blank_node_policy ("fresh" | "stable"), skolemize on export

0.3 done

Language tags (Literal.lang)

LangString, Annotated[..., Lang("en")]

0.3 done

rdf:HTML / rdf:XMLLiteral literals

preserve via OpaqueLiteral / registry

0.3 partial

Custom / unknown datatypes

pluggable Literal converters

0.2 done

term.bind() (Python ↔ datatype)

shared registry with rdflib bind()

0.2 done

Variable

SPARQL result binding only (not model fields)

0.6 done

RDF-star / quoted triples

pyoxigraph 0.5 dropped RDF-star; RDF 1.2 Triple terms TBD

TBD

Literal.direction (RDF 1.2 base direction)

extend LangString / literal registry

0.11 done

Multiple @lang on one predicate

MultiLangString field type

0.12 done

Per-object XSD datatypes on one predicate

TypedLiteral, set / list

0.12 done

Multi-valued URI refs

set[ResourceRef], list[ResourceRef]

0.12 done

OWL/RDFS ontology hints

OntologyRegistry, apply_hints_to_model

0.12 done

Paired inverse field metadata

BackPopulates, inverse_pair, navigation helpers

0.12 done

RDF Containers (Bag / Seq / Alt)

out of scope (prefer rdf:List in 0.3)

Graph API

add / triple iterators

to_graph, model_to_triples

0.1 done

remove / set

sync cleared fields; functional-property set

0.2 done

value()

read single object for 0..1 cardinality fields

0.2 done

__contains__

Graph.has_triple / membership in tests

0.2 done

set ops + - & ^

merge_graphs + documented BNode policy

0.2 done

slice / __getitem__ triple patterns

out of scope (rdflib convenience sugar)

bind, namespaces, compute_qname, qname

Rdf.prefixes, Namespace helpers on models

0.2 done

bind_namespaces strategies (core / none)

passthrough when creating Graph / Dataset

0.2 done

parse / serialize (all registered formats)

TripleModel.parse, .serialize, load_* / dump_*

0.4 done

parse base URI (base_iri)

Rdf.base_uri / parse(..., base=); Store.parse(base_iri=)

0.4 done

parse options (lenient, without_named_graphs, rename_blank_nodes)

first-class kwargs on parse helpers

0.11 done

RdfFormat.from_extension / from_media_type

strengthen infer_format

0.11 done

canonical N-Triples serialize

document / expose via serialize(format=...)

0.11 done

query (SELECT, ASK, CONSTRUCT, DESCRIBE)

select_models, ask, construct_models

0.6 done

query dataset options (use_default_graph_as_union, default_graph, named_graphs)

run_sparql / prepare_model_query passthrough

0.11 done

SPARQL result files (parse_query_results, QueryResultsFormat)

load/serialize SELECT/ASK/CONSTRUCT result docs

0.11 done

QuerySolutions.serialize / QueryBoolean.serialize

SparqlResult.serialize(...)

0.11 done

SPARQL SERVICE (federated)

Graph.query / guide 13 patterns

0.6 done

SPARQL UPDATE

apply_update + reload

0.6 done

prepareQuery, initNs, initBindings

prepare_model_query, init_ns_from_model, init_bindings_from_model

0.6 done

cbd (concise bounded description)

cbd_model, cbd_graph

0.7 done

skolemize / de_skolemize

export/import options on to_graph / from_graph

0.3 done

isomorphic / graph comparison

graphs_equal, graph_diff, model_diff

0.7 done

transitiveClosure, transitive_*

transitive_subjects, transitive_objects, subject_type_closure

0.7 done

collection (RDF lists)

list[T]rdf:List

0.3 done

resource()

ResourceRef fields

0.3 done

Property-based typing (wdt:P31, dbo:type, …)

Rdf.instance_of, discovery without rdf:type only

0.4.1 done

XSD gYear / gMonth / gMonthDay

literal registry + field import for partial dates

0.4.1 done

Multi-class document load (one parse)

load_models(graph, *classes) / ParseBundle

0.4.1 done

Mapping validation (predicate vs prefix)

model __pydantic_init_subclass__ checks

0.4.1 done

URI foreign-key hydration

ResourceRef → nested model, ref_field

0.4.1 done

Dataset / named graphs

@graph context on Rdf, Dataset I/O

0.5 done

quads(), get_context()

named-graph read/write in dataset helpers

0.5 done

ConjunctiveGraph

use Dataset only (rdflib deprecation)

0.5 done

Formats

Turtle, Trig, N-Triples, N-Quads

serialize(format=...)

0.4 done

RDF/XML, N3

same

0.4 done

JSON-LD

same; optional jsonld extra if needed

0.4 done

TriG, N-Quads, Turtle, RDF/XML, N3, JSON-LD

done (pyoxigraph)

0.10 done

TriX, HexTuples, longTurtle

out of scope in 0.10 (pyoxigraph; were rdflib-era formats)

0.10 out of scope

Microdata, RDFa

out of scope (HTML scraping, not domain modeling)

Stores

Memory (default, memory)

default Graph() / Dataset()

0.1 done

Remote SPARQL read (SPARQLStore)

removed in 0.10; use SparqlModel or load into Store

0.10 out of scope

Remote SPARQL read-write (SPARQLUpdateStore)

same

0.10 out of scope

BerkeleyDB, SQLAlchemy (rdflib stores)

removed; use open_graph("disk", path)

0.10 out of scope

LevelDB, Kyoto Cabinet (rdflib plugins)

out of scope for core; link in cookbook

open / close / destroy on store

graph_store_session, destroy_store

0.8 done

Store transactions (commit / rollback / open)

store_commit, store_rollback (no-ops on pyoxigraph; documented)

0.8 done

Store.bulk_load

fast ingest into disk Store without full in-memory parse

0.11 done

Store.dump / Store.load

snapshot export/import of on-disk store

0.11 done

Store.backup

on-disk store backup helper

0.11 done

Store.optimize

compact on-disk store after bulk edits

0.11 done

Store.flush

explicit flush before Graph.close on disk stores

0.11 done

Named-graph lifecycle (add_graph, remove_graph, clear_graph, named_graphs)

Dataset / Store helpers beyond get_graph_context

0.11 done

Store.quads_for_pattern

low-level quad pattern iterator (integrators)

0.11 done

In-memory pyoxigraph.Dataset class

out of scope — use RdfDataset view over Store

Dataset.canonicalize (URDNA2015)

canonicalize_quads in-memory helper for diffing

0.11 done

Import

Chunked / streaming model load

iter_graph_to_models, load_models_streaming

0.8 done

Import

Strict / warn on unmapped predicates

Rdf.strict_import, Rdf.warn_unmapped_fields

0.8 done

Performance

Predicate-map cache per class

predicate_map_for_class, owned_predicates_for_class

0.8 done

Tools

OWL/RDFS stub codegen (experimental)

triplemodel-codegen CLI

0.8 done

Namespace

Namespace, DefinedNamespace, bundled vocabs

from triplemodel.vocab import FOAF, SKOS, ...

0.2 done

Security

untrusted parse URLs / files

safe defaults on parse_url; document risks

1.0

Plugins

Register custom Parser/Serializer/Store

removed in 0.10; literals/resolvers only

0.10 out of scope

SHACL

Validation (pyshacl)

removed in 0.11.0 — use pyshacl directly

0.11 out of scope

Interop

oxrdflib rdflib store

out of scope — no rdflib dependency

contrib

GraphDB, RDF4J clients

out of scope for core; link in cookbook only

Tools

rdflib.tools CLI (csv2rdf, etc.)

out of scope (use rdflib directly)

Paths

Path algebra

out of scope (graph traversal, not ORM)

Before 1.0.0, the matrix above must be done or explicitly out of scope with rationale in this file — no silent gaps.


0.1.0 — Foundation

Status: Released (historical alpha classifier) — on PyPI as triplemodel==0.1.0

Area

Delivered

Core

TripleModel base, Rdf config class, rdf_field() / Predicate

Graph I/O

to_graph(), from_graph(), all_from_graph(), models_to_graph()

Terms

XSD scalars; IRI-like strURIRef (RFC 3986 schemes)

Identity

Subject IRI from Rdf.namespace + Rdf.id_field; subject_base / id_from_subject_uri; explicit uri= override

Store

In-memory Graph only

rdflib parity: minimal Graph.add path via serialization; most of the matrix still open.

0.1.x hardening (done): Safe subject-id extraction (subject_base / id_from_subject_uri); percent-encoding on export; BNode rejected for str fields; contextual import errors; xsd:string for plain literals; str_strip_whitespace=False on TripleModel; CI + py.typed + 100% coverage; MRO-inherited Rdf config; validate_type on import; duplicate-predicate warning (on_duplicate); unified validation error messages; Annotated import coercion; RFC 3986 IRI schemes on export; OnDuplicate public export.

SparqlModel (SM-0): Optional local/dev pin on triplemodel==0.1.* for experiments; no required triplemodel dependency in sparqlmodel until 0.2 (SM-1).


0.2.0 — Terms, fields, and namespaces

Status: Released (historical alpha classifier) — on PyPI as triplemodel==0.2.0

Theme: Everything needed for ordinary RDF-shaped Pydantic models on a single default graph.

  • Multi-valued fieldslist[T], set[T] ↔ multiple objects per predicate (0.3+: set[T] only; list[T] is rdf:List)

  • Nested TripleModel — blank node or named IRI embedding (configurable)

  • Optional & null semantics — omit vs explicit empty; remove prior triples when a field is cleared on re-export

  • Custom Literal datatypes — register converters (Decimal, UUID, Enum, …); wire rdflib term.bind()

  • Namespace helpers — CURIE expansion, Rdf.prefixesGraph.bind

  • DefinedNamespace vocabs — re-export common rdflib namespaces from triplemodel.vocab

  • bind_namespaces strategies — passthrough core / rdflib / none when constructing graphs

  • Graph merge policies — replace / patch / add when writing into existing Graph

  • Graph set operationsmerge_graphs() helper; BNode identity documented in docstrings

  • Graph.set / Graph.valuegraph_set / graph_value helpers

  • Graph iterator helpersobjects_for_field

  • Duplicate predicate warning — scalars use on_duplicate; collections import all values

Exit criteria: FOAF Person with multiple nick values and embedded mbox round-trips; prefixes appear in serialized Turtle; clearing age=None removes foaf:age triples on re-export.

SparqlModel (SM-1): Ship sync_to_graph / model_to_graph(..., mode="replace"|"patch") (or equivalent) for owned-predicate replacement; Rdf.prefixes + CURIE expansion aligned with SparqlModel __prefixes__; optional explicit IRI id field alongside id_field + namespace; document triple-ownership boundaries for cascade layers.


0.3.0 — Literals, blanks, lists, and identity

Status: Released (historical alpha classifier) — on PyPI as triplemodel==0.3.0

Theme: Full rdflib term expressiveness for model fields.

  • LangString / per-language fieldsLiteral.lang round-trip

  • Typed XML/HTML literalsrdf:XMLLiteral, rdf:HTML as str; unknown datatypes via OpaqueLiteral

  • Arbitrary datatype literals — preserve unknown datatype URIs via OpaqueLiteral

  • Blank nodes — import/export; skolemize / de_skolemize on to_graph / from_graph

  • RDF collectionslist[T]rdf:List; set[T] = multiple objects (breaking vs 0.2)

  • ResourceRef — validated IRI resource fields

  • BNode stabilityRdf.blank_node_policy (fresh | stable)

Exit criteria: Dublin Core title with language tags; blank-node Address; RDF list of nick values all round-trip (examples/exit_criteria_03.py).

SparqlModel (SM-2): Hydration can delegate single-resource load to TripleModel before relationship expansion; blank-node strategy documented for embedded SPARQLModel values.


0.4.0 — Parsing, serialization, and validation

Status: Released (beta) — on PyPI as triplemodel==0.4.0

Theme: All rdflib syntaxes that make sense for documents (not HTML).

  • TripleModel.parse / .serialize — delegate to Graph.parse / Graph.serialize

  • Format support — Turtle, Trig, N-Triples, N-Quads, RDF/XML, N3, JSON-LD, TriX, HexTuples, longTurtle (rdflib-era; TriX/HexTuples/longTurtle removed in 0.10 — see Migrating to TripleModel 0.10.0 (pyoxigraph))

  • Format autodetection — filename suffix and format= / media type passthrough

  • Base URI on parse — rdflib 7 publicID semantics: Rdf.base_uri for resolving relative IRIs (not named-graph id)

  • parse_file / parse_url — parse RDF from path or URL into list[TripleModel]

  • parse(data=...) — load from string (Turtle/JSON-LD snippets in apps and tests)

  • JSON-LD context — optional @context on Rdf class for compaction; passthrough compact/expand kwargs

  • SHACL (optional extra) — validate before to_graph() via pyshacl or equivalent

  • Inverse predicates — import via inverse predicate; export and sync clear forward links; replace/patch remove stale inverse triples on other subjects

  • Subclass dispatch — multiple type_uri; import picks most specific registered model

Exit criteria: Same Person instance equivalent from Turtle file, JSON-LD string, and in-memory Graph; invalid data fails SHACL when extra installed (examples/exit_criteria_04.py).

SparqlModel (SM-3): export_model / file load paths call TripleModel; remove parallel format registry from SparqlModel.

Real-world validation (2026): examples/realworld exercises Nobel linked data, DCAT catalogs, Wikidata excerpts, and Schema.org NGO records. The examples run offline in CI and surfaced gaps between “RDF works” and “feels Pythonic in application code.” See Real-world ergonomics (0.4.1+) below.


0.4.1 — Real-world ergonomics

Status: Released (beta) — on PyPI as triplemodel==0.4.1

Theme: Close the gap between typed records and linked-data workflows—without waiting for Dataset (0.5) or full SPARQL helpers (0.6). Informed by examples/realworld.

Priority

Feature

Status

P0

Single-pass multi-class load (load_graph, load_models, load_models_from_graph)

Done

P0

Mapping validation (predicate local name; prefix namespace warning)

Done

P0

XSD partial dates (gYear, gMonth, gMonthDay; literal_datatype=)

Done

P1

Property-based typing (Rdf.instance_of, instance_type_uri)

Done

P1

URI FK hydration (ref_field)

Done

P1

Linked object graphs in examples (cookbook / nested embed patterns)

Docs (optional nested links in examples)

P1

Refactor in-repo examples

Done

P2

Lang-tagged label defaults

rdfs:label@en is ubiquitous; users must know LangString vs plain str

P2

QID / slug conventions

Wikidata IDs (Q90) vs full IRIs — IriId works but examples need boilerplate

P2

Optional inverse export

Import reads inverse; export is forward-only (by design) but some portals expect bidirectional edges

P3

Refresh-from-endpoint recipe

Wikidata excerpt maintenance via SPARQL CONSTRUCT

Exit criteria: Nobel + DCAT examples use one parse/load_models call per file; Wikidata capitals use instance_of or documented discovery without hard-coded QID loops; Schema.org NGOs import foundingDate without manual str workaround; invalid rdf_predicate in rdf_field fails at class definition with a clear error.

Example updates (ship with 0.4.1): Each feature lands with corresponding example refactors—no “API only” release.

Example

After 0.4.1

examples/realworld/nobel_laureates.py

load_models (or single graph + multi-class load); optional nested NobelPrize on Laureate

examples/realworld/dcat_data_catalog.py

One parse/load for catalog, dataset, distribution; nested catalog → dataset where data allows

examples/realworld/wikidata_capitals.py

Rdf.instance_of / discovery instead of COUNTRY_QIDS; ResourceRef or ref_field for country

examples/realworld/schema_org_ngos.py

Typed foundingDate via XSD gYear (not plain str)

examples/readme_examples.py, examples/doc/snippets/

Touch only where a 0.4.1 API is demonstrated (mapping validation demo, load_models, etc.)

docs/examples.md, cookbook drafts

Runnable commands match refactored scripts

CI: tests/test_realworld_examples.py must exercise the new APIs (not only stdout smoke tests).

Not in 0.4.1 (later releases): SPARQL SELECT/CONSTRUCT loaders (0.6), CBD for subgraph extract (0.7), named graphs (0.5), inverse export default-on (stay forward-only unless opted in).


0.5.0 — Datasets and named graphs

Status: Released (beta) — on PyPI as triplemodel==0.5.0

Theme: rdflib Dataset (replacing deprecated ConjunctiveGraph).

  • Rdf.graph_iri / @graph — map model class or instance to a named graph IRI

  • to_dataset / from_dataset — serialize models into correct named graphs

  • Dataset.get_context() / quads() — read and write via named-graph helpers

  • all_from_dataset — load by rdf:type within a graph context

  • Default graph vs union — document query/import behavior (union default in rdflib)

  • Trig / N-Quads round-trip — named graph boundaries preserved

  • Migrate from ConjunctiveGraph — document rdflib 6→7 / publicID changes for dataset users

Exit criteria: Two model types in different named graphs round-trip through Trig without collision.

SparqlModel (SM-4): Only if SparqlModel models gain named-graph context; otherwise defer.


0.6.0 — SPARQL and remote graphs

Status: Released (beta) — on PyPI as triplemodel==0.6.0 (see 0.8.0 for latest)

Theme: rdflib query and SPARQL store integration (TripleModel passthrough — not a Python query DSL).

  • select_models — SPARQL SELECT → list[TripleModel] with variable→field mapping

  • construct_models — CONSTRUCT/DESCRIBE → target model class

  • ask — thin wrapper returning bool

  • SPARQL UPDATEapply_update(graph, query) with documented interaction with models

  • load_sparqlSPARQLStore / read-only endpoint into models (historical, rdflib 0.6; removed in 0.10 — raises NotImplementedError)

  • SPARQLUpdateStore — read-write remote graph pattern (optional extra if needed)

  • Federated SERVICE — document querying remote endpoints inside SPARQL

  • Prepared queriesprepareQuery() + initNs from model Rdf.prefixes

  • initBindings — pre-bind subject URI or field values in prepared model queries

  • Result types — handle all rdflib result kinds (bindings, boolean, graph, JSON)

Exit criteria: Load Person rows from a public SPARQL endpoint in ≤10 lines; UPDATE example in docs.

SparqlModel: Not required for integration gate — SparqlModel owns app-side SPARQL ergonomics. TripleModel may expose thin helpers; SparqlModel keeps compiler + HttpStore roadmap.


0.7.0 — Graph algorithms and RDFS ✅

Status: Released (beta) — on PyPI as triplemodel==0.7.0

Theme: rdflib graph operations that help modeling, not replace reasoners.

  • cbd wrappercbd_graph, cbd_model, TripleModel.cbd

  • Transitive helperstransitive_objects / transitive_subjects; Transitive / rdf_field(..., transitive=True) on import

  • graphs_equalisomorphic + optional BNode normalization for tests

  • model_diff / graph diffgraph_diff, model_diff, GraphDiff

  • Safe graph merge — documented in Graph algorithms and RDFS and Working with graphs

  • RDFS subclass importresolve_model_class_with_rdfs; Rdf.resolve_subclass (default true)

  • Vocabulary registryVocabularyRegistry

  • Codegen (experimental) — deferred from 0.7; shipped in 0.8 as triplemodel-codegen

  • hydrate_refs / model_join — batch-load shared ref URIs; Wikidata capitals example updated

  • Catalog & registry patterns — doc pointers in guide 14 to examples/realworld/

Exit criteria:examples/exit_criteria_07.py (subclass dispatch + CBD); Wikidata capitals uses hydrate_refs.


0.8.0 — Stores, scale, and ergonomics ✅

Status: Released (beta) — on PyPI as triplemodel==0.8.0

Theme: rdflib stores and production-sized graphs.

  • SPARQL store adapter — documented pattern in guide 15 + guide 13 (persistent remote graphs)

  • Optional extrassqlalchemy, berkeleydb store backends with examples (removed in 0.10; use open_graph("disk", path))

  • Store lifecycleopen_graph, graph_store_session, destroy_store

  • Store transactionsstore_commit / store_rollback passthrough

  • Batch importiter_graph_to_models, load_models_streaming, parse_into_store_graph

  • Caching — predicate maps per model class (metadata/predicate_map.py)

  • Strict modeRdf.strict_import, warn_unmapped_fields

  • Plugin hookstriplemodel.plugins (pre-0.9 full registry)

  • Codegen (experimental)triplemodel-codegen CLI

Exit criteria:examples/exit_criteria_08.py (chunked/streaming benchmark); disk store via open_graph("disk", ...).


0.10.0 — pyoxigraph engine

Theme: Replace rdflib with pyoxigraph as the runtime RDF store; keep mapping API stable.

  • Engine swappyoxigraph.Store via triplemodel.Store / RdfGraph

  • TermsNamedNode, Literal, BlankNode; manual rdf:List; skolemize/CBD helpers

  • File I/O — parse/serialize through pyoxigraph (Turtle, TriG, N-Triples, N-Quads, RDF/XML, N3, JSON-LD)

  • Dataset — named graphs on one store (RdfDataset)

  • SPARQLStore.query / update passthrough; remote SPARQLStore out of scope

  • Storesmemory and disk (open_graph); drop rdflib-sqlalchemy extra

  • Plugins — remove rdflib register_parser / register_serializer / register_store

  • SHACL — optional bridge in [shacl] extra (removed in 0.11.0)

  • Migration guideMigrating to TripleModel 0.10.0 (pyoxigraph)

  • API stability exception — graph type break documented in API stability (0.9+)

Exit criteria: Core quickstart round-trip; pytest green; docs and compat CI updated.

SparqlModel (SM-7): Downstream pin triplemodel>=0.10,<2 when SparqlModel adopts Store (see SparqlModel ecosystem guide (for SparqlModel development)).


0.11.0 — rdflib removal ✅

Status: Released (beta) — on PyPI as triplemodel==0.11.0

Theme: Remove the last rdflib integration; align naming with pyoxigraph.

  • SHACL removedtriplemodel[shacl] extra, validate_graph, shacl_shapes=

  • API renames**rdflib_kwargs**format_kwargs; publicIDbase_iri on Store.parse

  • bind_namespaces — drop strategy="rdflib" (use "core")

  • MigrationMigrating to TripleModel 0.11.0

Exit criteria: No import rdflib in package source; make ci green.


0.11.0 — pyoxigraph surface completion ✅

Status: Shipped in 0.11.0 (additive APIs on the same release line as rdflib removal)

Theme: Expose remaining pyoxigraph 0.5.x store, I/O, and SPARQL-result APIs that help typed-model workflows — without reintroducing sessions, remote SPARQL graphs, or rdflib.

Reference sections: RDF Model · Parsing and Serialization · RDF Store · SPARQL utility objects.

Store operations (disk / scale)

  • bulk_loadbulk_load_into_graph(graph, path, format=, base_iri=, to_graph=) wrapping Store.bulk_load

  • dump / loaddump_store / load_store for on-disk store snapshots

  • backupbackup_store(target_directory, graph=) for RocksDB-backed stores

  • optimizeoptimize_store(graph=) after bulk import or heavy sync_to_graph workloads

  • flushstore_flush(graph); Graph.close flushes when supported

  • Named-graph lifecyclelist_named_graphs, ensure_named_graph, clear_named_graph, remove_named_graph

  • quads_for_patterniter_quads_for_pattern over Store.quads_for_pattern

Parse / serialize (I/O)

  • Parse flagslenient=, without_named_graphs=, rename_blank_nodes= on parse_into_graph, dataset/model parse helpers

  • RdfFormat discoveryinfer_format falls back to RdfFormat.from_extension / from_media_type; format_supports_datasets / format_supports_rdf_star

  • Serialize prefixesGraph.serialize passes bound prefixes (regression-tested for Turtle/TriG)

  • Canonical N-Triples — pyoxigraph canonical NT for stable graph comparison (see guide 10)

SPARQL results

  • parse_query_results — load saved SPARQL result files (JSON/XML/CSV/TSV) into SparqlResult

  • Result serializationSparqlResult.serialize(format=) for SELECT/ASK results

  • Advanced Store.queryuse_default_graph_as_union, default_graph, named_graphs, base_iri on run_sparql / PreparedModelQuery.execute

Terms / RDF 1.2

  • Literal.direction — optional direction on LangString and Lang metadata (pyoxigraph ltr / rtl / auto)

  • RDF 1.2 triple termsout of scope for 0.11.0 — use raw pyoxigraph.Triple; TripleModel fields stay resource-oriented (see TripleModel project plan)

Explicitly deferred in 0.11.x

pyoxigraph API

TripleModel stance

Store.query / update custom_functions, custom_aggregate_functions

Expert SPARQL extension — use raw Store

In-memory pyoxigraph.Dataset (non-store)

Use RdfDataset over Store

oxrdflib

No rdflib dependency

Remote SPARQL endpoint store

out of scope (0.10); SparqlModel or load-then-query

SHACL / pyshacl

out of scope (0.11.0); external validation

Exit criteria: Matrix rows marked 0.11 are done or out of scope; guide 15 documents disk bulk_load / backup / optimize; one example script under examples/stores/.

SparqlModel: Disk-store helpers are optional for SM-7; session-level remote graphs remain in SparqlModel.


0.9.0 — rdflib parity audit and API freeze (historical)

Theme: Close the matrix; stabilize public API.

  • Coverage audit — every row in the matrix done, partial, TBD, or out of scope (see matrix above)

  • Plugin passthroughregister_parser / register_serializer / register_store in triplemodel.plugins

  • API audit__all__ freeze documented in docs/API_STABILITY.md

  • Migration guideN/A (no production adopters; CHANGELOG is historical record)

  • Full API reference — Sphinx docs/api/ + autodoc on triplemodel and submodules

  • Cookbookdocs/cookbook/ (formats, SPARQL/Fuseki, Dataset, SHACL, stores, real-world)

  • Typingpy.typed + ty check in CI (canonical checker; not mypy)

  • Compatibility matrix — pinned pydantic / pyoxigraph ranges in CI compat job

Exit criteria: No open matrix gaps except TBD / out of scope; beta on PyPI. (examples/exit_criteria_09.py is now 0.10 Store + disk smoke — not 0.9 plugin registry.)

SparqlModel (SM-5): Compatibility range in ECOSYSTEM_SPARQLMODEL.md; SparqlModel-side migration when pinning triplemodel (optional cross-package CI deferred).


1.0.0 — Stable release

Theme: Trustworthy default for Pydantic ↔ RDF in production. No new engine surface — only fixes, docs, and governance.

Requirement

Detail

pyoxigraph coverage

Matrix complete per 0.9/0.10 audit (see matrix above)

API stability

Semver commitment; deprecations required ≥1 minor earlier

Security

Safe parser defaults; document XML/URL fetch risks

Quality

≥90% coverage on core; integration tests per supported format and SPARQL

Packaging

PyPI wheels; extras: dev, docs

Governance

CONTRIBUTING.md, CODE_OF_CONDUCT, Keep a Changelog

Celebration criteria: A downstream app can depend on triplemodel~=1.0 knowing pyoxigraph store/I/O/SPARQL features needed for typed models are exposed (per matrix), SparqlModel can pin this release for mapping, and patch releases are safe.


Explicitly out of scope (even pre-1.0)

rdflib areas TripleModel does not wrap

Use rdflib directly, SparqlModel, or another integration package:

Item

Rationale

HTML Microdata / RDFa parsers

Scraping workflow, not domain model I/O

RDF Containers (Bag / Seq / Alt)

Legacy container model; use rdf:List (0.3) instead

Graph slice / g[s:p:o] syntax

rdflib REPL sugar; use explicit triples() / helpers

rdflib.paths property-path operators

Graph traversal DSL, not Pydantic ORM

rdflib.contrib.graphdb / RDF4J clients

Vendor-specific; belongs in integrations

LevelDB / Kyoto Cabinet store plugins

Third-party rdflib extensions; cookbook only

rdflib.tools CLI utilities

CLI is rdflib’s job

Custom SPARQL algebra (CUSTOM_EVALS)

Expert extension point; use rdflib directly

Full OWL reasoning

Use dedicated reasoners

Replacing rdflib parsers, stores, or SPARQL engine

TripleModel orchestrates, never forks

Application features owned by SparqlModel (not TripleModel)

Item

Package

SPARQLSession, identity map, unit-of-work

SparqlModel

Python query DSL (Model.field == value)

SparqlModel

SPARQL WHERE compiler

SparqlModel

put / delete cascade and orphan cleanup

SparqlModel

HTTP SPARQL store (HttpStore)

SparqlModel

FastAPI integration

SparqlModel optional extra


Ecosystem summary

triplemodel

sparqlmodel

Role

Mapping + files

Session + queries

State

Stateless

Stateful

Base class

TripleModel

SPARQLModel

Depends on

pyoxigraph, pydantic

pydantic; triplemodel (from 0.2)

Full boundaries: ECOSYSTEM.md · Strategy: PLAN.md · SparqlModel dev copy: ECOSYSTEM_SPARQLMODEL.md


How to influence the roadmap

  1. Open an issue with the label roadmap describing your use case.

  2. If requesting a new pyoxigraph feature, name the API (Store.method, parse flag, RdfFormat, etc.) and link to the pyoxigraph docs.

  3. For SparqlModel integration needs, reference milestone SM-* and whether the feature belongs in TripleModel or SparqlModel per ECOSYSTEM.md.

  4. Link vocabularies, sample data, or validation shapes when possible.


Version summary

Version

Focus

rdflib layers

SparqlModel

0.1.0

Flat models, in-memory graph round-trip

Graph.add, basic terms

SM-0 (optional dev pin)

0.2.0

Fields, namespaces, merge, remove/set

bind, remove, value, vocabs

SM-1 (dependency gate)

0.3.0

Literals, blanks, lists, skolemize

term, collection, resource

SM-2

0.4.0

All document formats, base URI, SHACL

parse, serialize

SM-3

0.4.1

Real-world ergonomics (multi-class load, Wikidata typing, XSD dates)

property typing, load_models, mapping validation

0.5.0

Named graphs

Dataset, quads, get_context

SM-4 (if needed)

0.6.0

SPARQL passthrough + remote store

query, UPDATE, SERVICE, stores

0.7.0

CBD, isomorphism, RDFS, safe merge

graph algorithms

0.8.0

Persistent stores, scale

Store open/close, plugins

0.9.0

Matrix audit, API freeze (rdflib)

plugin passthrough

SM-5 prep

0.10.0

pyoxigraph engine

Store, disk store

SM-7

0.11.0

rdflib/SHACL removed

API rename (format_kwargs, base_iri)

0.11.0

pyoxigraph surface + rdflib removal

bulk_load, backup, query results, LangString.direction

RDF 1.2 Triple field values deferred

0.12.0

SparqlModel 0.13 mapping parity (additive)

MultiLangString, TypedLiteral, OntologyRegistry, BackPopulates

No migration file (see CHANGELOG)

1.0.0

Stable, documented, governed

oxigraph matrix frozen

SM-5 pin triplemodel