Conformance matrix¶
This page tracks how each PROV-DM concept maps onto prov’s classes and factory methods, and
how well each serializer round-trips it. It is the audit artefact for Phase 3.5 of the
modernisation roadmap (roadmap step
28) and is revisited at every release as behaviour changes; a JSON-LD column is planned for
3.1.0 once the PROV-JSONLD serializer lands. For prose background on PROV-DM’s six components and
how they group in prov.model, see The PROV Data Model; this page is the detailed,
verified-against-source reference underneath that explanation.
Every cell below was checked directly against the current source: model classes against
src/prov/model/records.py, factory methods and camelCase aliases against
src/prov/model/bundle.py, PROV-N keywords against PROV_N_MAP / ADDITIONAL_N_MAP in
src/prov/constants.py, and round-trip status against the shared test matrix
(src/prov/tests/conftest.py::SHARED_TARGETS, test_statements.py, test_attributes.py).
Round-trip column key¶
JSON / XML / RDF — whether the type round-trips (
deserialize(serialize(doc)) == doc) under the sharedfmttest matrix (SHARED_TARGETS = ("model", "json", "xml", "rdf")inconftest.py). ✓ means every shared case for that concept passes cleanly; a caveat cites the tracking issue and says what still fails.PROV-N — PROV-N is output-only:
provhas no PROV-N parser (issue #122, planned for 3.2.0), so there is no PROV-N round trip to test, only the keywordget_provn()emits. Every PROV-N cell below is additionally subject to issue #223 (QualifiedName.provn_representation()does not escape PROV-N metacharacters —',),,,(,:,;,[,],=— in an identifier’s local part), which is a property of identifiers, not of any one record type; it is noted once here rather than on every row.
Two more caveats apply across many rows rather than to one:
#217 (RDF): 14 statement-level test cases assert two relations that share one identifier but differ only in
prov:time; PROV-O has no way to represent that (both times serialize onto the same qualified IRI), so those specific test cases are skipped for therdftarget. This is a limitation of same-identifier/differing-time relations, not of the relation types themselves —generation/usage/start/end/invalidationround-trip cleanly in the general case.#224 (XML): the PROV-XML serializer silently drops any
other_attributesentry whose value is the empty string"", regardless of record type.#225 (RDF): a Python
floatattribute (typedxsd:float) can lose precision through RDF, regardless of record type, because the RDF serializer canonicalisesxsd:floatto a short decimal form.
Component 1 — Entities and Activities¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
|---|---|---|---|---|---|---|
Entity §5.1.1 |
|
|
✓ |
✓ |
✓ |
|
Activity §5.1.2 |
|
|
✓ |
✓ |
✓ |
|
Generation §5.1.3 |
|
|
✓ |
✓ |
✓ (#217 for the 2 same-id/differing-time cases) |
|
Usage §5.1.4 |
|
|
✓ |
✓ |
✓ (#217 for the 2 same-id/differing-time cases) |
|
Communication §5.1.5 |
|
|
✓ |
✓ |
✓ |
|
Start §5.1.6 |
|
|
✓ |
✓ |
✓ (#217 for the 4 same-id/differing-time cases) |
|
End §5.1.7 |
|
|
✓ |
✓ |
✓ (#217 for the 4 same-id/differing-time cases) |
|
Invalidation §5.1.8 |
|
|
✓ |
✓ |
✓ (#217 for the 2 same-id/differing-time cases) |
ProvEntity additionally exposes wasGeneratedBy()/wasInvalidatedBy()
and ProvActivity exposes
used()/wasInformedBy()/wasStartedBy()/wasEndedBy() as self-as-subject chaining
methods (records.py) — the table above lists the ProvBundle factories, which every relation
also has.
Component 2 — Derivations¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
|---|---|---|---|---|---|---|
Derivation §5.2.1 |
|
|
✓ |
✓ |
✓ |
|
Revision §5.2.2 |
|
|
|
✓ |
✓ |
✓ |
Quotation §5.2.3 |
|
|
|
✓ |
✓ |
✓ |
Primary Source §5.2.4 |
|
|
|
✓ |
✓ |
✓ |
Revision, quotation, and primary source are PROV-DM subtypes of derivation, not separate PROV-N
records: prov implements all four with the single ProvDerivation class,
and the three subtype factories call derivation() then add the corresponding prov:type
(confirmed by inspection of bundle.py:1011-1146, and by running get_provn() on a revision()
record — it emits wasDerivedFrom(..., [prov:type='prov:Revision']), not a wasRevisionOf(...)
keyword). ADDITIONAL_N_MAP does carry a wasRevisionOf/wasQuotedFrom/hadPrimarySource
keyword mapping for contexts (such as PROV-XML) that treat these as top-level types; PROV-N
output from this library always uses the base wasDerivedFrom form.
Component 3 — Agents, Responsibility, and Influence¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
|---|---|---|---|---|---|---|
Agent §5.3.1 |
|
|
✓ |
✓ |
✓ |
|
Person / Organization / SoftwareAgent §5.3.1 |
via |
none — see finding below |
|
✓ |
✓ |
✓ |
Attribution §5.3.2 |
|
|
✓ |
✓ |
✓ |
|
Association §5.3.3 |
|
|
✓ |
✓ |
✓ |
|
Plan §5.3.3 |
via |
— |
— (plan is an ordinary entity referenced by the association’s |
✓ |
✓ |
✓ |
Delegation §5.3.4 |
|
|
✓ |
✓ |
✓ (anonymous qualified delegations sharing (delegate, activity): #226) |
|
Influence §5.3.5 |
|
|
✓ |
✓ |
✓ |
Finding: PROV-DM defines Person, Organization, and SoftwareAgent as agent subtypes, and Plan
as an entity subtype used with associations. prov has no dedicated classes or factories for the
agent subtypes — you express them with agent("ag", {PROV_TYPE: "prov:Person"}) — while Plan
needs no special handling at all, since it is just an entity passed as the plan= argument to
association(). This is a documented, intentional design choice
(docs/explanation/prov-dm.md:111-114), not a defect; see finding log for the audit note.
Component 4 — Bundles¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
|---|---|---|---|---|---|---|
Bundle constructor §5.4.1 |
|
|
✓ |
✓ |
✓ |
|
Bundle type §5.4.2 |
not implemented — see finding below |
— |
— |
— |
— |
— |
Finding: PROV-DM §5.4.1 defines bundle containment — a named, nestable set of records —
which prov fully implements via ProvDocument.bundle()/add_bundle(); only a
ProvDocument may contain named bundles (is_document()/is_bundle()
in bundle.py distinguish the two at runtime). §5.4.2 additionally lets a bundle’s identifier
denote a first-class entity of type prov:Bundle, so that provenance-of-provenance (e.g. “who
asserted this bundle”) can itself be expressed in PROV. That second half is not implemented:
the PROV_BUNDLE constant and its PROV_N_MAP["bundle"] keyword exist in constants.py but
are consumed only by dot.py (for node styling) — no serializer or
ProvBundle method ever produces a prov:Bundle-typed entity, and
get_provn()’s bundle <id> ... endBundle output is generated structurally (branching on
is_document()), not through that keyword lookup. There is currently no supported way to
attribute a bundle to an agent as a first-class PROV statement.
Component 5 — Alternate Entities¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
|---|---|---|---|---|---|---|
Specialization §5.5.1 |
|
|
✓ |
✓ |
✓ |
|
Alternate §5.5.2 |
|
|
✓ |
✓ |
✓ |
|
Mention (PROV-LINKS) |
|
|
|
✓ |
✓ |
✓ |
Component 6 — Collections¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
|---|---|---|---|---|---|---|
Collection §5.6 |
|
|
|
✓ |
✓ |
✓ |
EmptyCollection §5.6 |
|
none — see finding below |
|
✓ |
✓ |
✓ |
Membership §5.6 |
|
|
✓ |
✓ |
✓ |
Finding: like collections, EmptyCollection is a real PROV-DM type with a real
ADDITIONAL_N_MAP/PROV_BASE_CLS entry in constants.py, so the round-trip machinery
understands it — but there is no empty_collection() factory or empty= flag on collection()
to set the type for you; you would add prov:type: "prov:EmptyCollection" by hand via
other_attributes.
Additional attributes¶
Five PROV-DM attributes are usable on (almost) any record and are exercised directly by the
shared attribute test matrix (test_attributes.py, ATTRIBUTE_VALUES in
attribute_values.py) and by test_statements.py’s add_label/add_locations/add_types/
add_value helpers:
Attribute |
Constant ( |
Round-trip notes |
|---|---|---|
|
|
✓ JSON/XML/RDF, including language-tagged literals and multiple values on one record. |
|
|
✓ JSON/XML/RDF across the full |
|
|
✓ JSON/XML/RDF; used throughout the qualified-relation tests (association, usage, generation, …). |
|
|
✓ JSON/XML; RDF is clean for a single value but see #77 ( |
|
|
✓ JSON/XML/RDF. |
Any attribute value (regardless of which of the five above it is) is additionally subject to
#224 (XML drops the empty string "") and
#225 (RDF can lose xsd:float precision) —
both are properties of the value’s type, not of the attribute name.
Maintenance¶
This matrix reflects the codebase as of the Phase 3.5 conformance audit (roadmap step 28) and should be revisited at each release as serializers change or issues close. Release 3.1.0 adds a PROV-JSONLD serializer; when that lands, this page gains a JSON-LD column alongside JSON/XML/RDF. See The PROV Data Model for the conceptual background behind each component, and prov.model for the full class/method API reference.