Conformance¶
prov implements the W3C PROV Data Model and five
serialisations of it: PROV-JSON, PROV-XML, PROV-O (RDF), PROV-JSONLD and PROV-N. This page
states what the current release conforms to; it was revised for 3.2.3.
The component tables answer two questions: is a PROV-DM concept implemented and how is it
written, and does each format preserve it on a round trip. Every cell that is not a plain
tick points at a numbered caveat. The values table does the same for literals. “Reading
other producers’ output” lists what each reader accepts beyond prov’s own output, with
the reason for each allowance. “Corpus evidence” is the test record behind the PROV-N
claims. Every cell is checked against the source and the shared test suite, not against the
specification text alone; The PROV Data Model gives the background for the six
components.
Reading the tables¶
A round trip is
deserialize(serialize(doc)) == docfor every shared test case. ✓ means it holds; ✓ C1 means it holds except in the case caveat C1 describes; ✗ C2 means the format cannot represent the concept.The PROV-N column shows the keyword
get_provn()writes. Every row round-trips through PROV-N under thedefaultprofile, and understrictwhen written withstrict=True.provenforces no structural constraint at assertion time (#257). Merge-time conformance, PROV-CONSTRAINTS unification, isunified()’s job and is described in Unification and flattening.
Component 1: Entities and Activities¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
JSON-LD |
|---|---|---|---|---|---|---|---|
Entity §5.1.1 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Activity §5.1.2 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Generation §5.1.3 |
|
|
✓ |
✓ |
✓ C1 |
✓ |
|
Usage §5.1.4 |
|
|
✓ |
✓ |
✓ C1 |
✓ |
|
Communication §5.1.5 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Start §5.1.6 |
|
|
✓ |
✓ |
✓ C1 |
✓ |
|
End §5.1.7 |
|
|
✓ |
✓ |
✓ C1 |
✓ |
|
Invalidation §5.1.8 |
|
|
✓ |
✓ |
✓ C1 |
✓ |
The factories are ProvBundle methods. ProvEntity
also has wasGeneratedBy() and wasInvalidatedBy(), and ProvActivity
has used(), wasInformedBy(), wasStartedBy() and wasEndedBy(), as chaining methods
with the record itself as subject.
Component 2: Derivations¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
JSON-LD |
|---|---|---|---|---|---|---|---|
Derivation §5.2.1 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Revision §5.2.2 |
|
|
|
✓ |
✓ |
✓ |
✓ |
Quotation §5.2.3 |
|
|
|
✓ |
✓ |
✓ |
✓ |
Primary Source §5.2.4 |
|
|
|
✓ |
✓ |
✓ |
✓ |
The three subtypes share one class and differ only in prov:type, which is how PROV-N
expresses them: the grammar has no wasRevisionOf keyword.
Component 3: Agents, Responsibility and Influence¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
JSON-LD |
|---|---|---|---|---|---|---|---|
Agent §5.3.1 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Person / Organization / SoftwareAgent §5.3.1 |
|
none, see “Not implemented” |
|
✓ |
✓ |
✓ |
✓ |
Attribution §5.3.2 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Association §5.3.3 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Plan §5.3.3 |
the entity named by |
none |
none; the plan is the association’s third argument |
✓ |
✓ |
✓ |
✓ |
Delegation §5.3.4 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Influence §5.3.5 |
|
|
✓ |
✓ |
✓ |
✓ |
Component 4: Bundles¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
JSON-LD |
|---|---|---|---|---|---|---|---|
Bundle constructor §5.4.1 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Bundle as an entity §5.4.2 |
not implemented, see below |
Only a ProvDocument may contain named bundles. A bundle that
declares a default namespace different from the one its identifier lives in is written with
a prefixed identifier, so the identifier’s IRI survives re-reading.
Component 5: Alternate Entities¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
JSON-LD |
|---|---|---|---|---|---|---|---|
Specialization §5.5.1 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Alternate §5.5.2 |
|
|
✓ |
✓ |
✓ |
✓ |
|
Mention (PROV-Links) |
|
|
✓ |
✓ |
✓ |
✗ C2 |
alternate(a, b) is written as the triple a prov:alternateOf b, PROV-DM’s argument order.
Component 6: Collections¶
Concept (PROV-DM §) |
Model class |
Factory / alias |
PROV-N keyword |
JSON |
XML |
RDF |
JSON-LD |
|---|---|---|---|---|---|---|---|
Collection §5.6 |
|
|
|
✓ |
✓ |
✓ |
✓ |
EmptyCollection §5.6 |
|
none, see “Not implemented” |
|
✓ |
✓ |
✓ |
✓ |
Membership §5.6 |
|
|
✓ |
✓ |
✓ |
✓ |
Values and datatypes (PROV-DM §5.7)¶
The shared attribute corpus exercises every XSD type below in every format, on prov:label,
prov:location, prov:role, prov:type, prov:value and on ordinary attributes.
Value |
Written as |
Round trip |
|---|---|---|
String, with or without an explicit |
a string |
✓ in every format |
Language-tagged string |
the tag as given; tags compare case-insensitively |
✓ C5 C6 |
Boolean |
|
✓ |
Python |
|
✓ |
Integer with an asserted datatype ( |
the asserted datatype, never collapsed to a narrower one |
✓ |
|
as given; compared in value space, so |
✓ |
Python |
|
✓ |
Qualified name as a value |
|
✓ |
|
ISO 8601 text; a naive |
✓ C7 |
|
lexical form and datatype as given; datatypes other than |
✓ |
Caveats¶
C1. Two relations with the same identifier and different
prov:time(PROV-O, permanent). PROV-O names a relation by its identifier, so two asserted relations that share one and differ only in time land on one node. Only that construct is affected; decoding third-party RDF shaped this way raisesprov.model.ProvException. Minting a synthetic IRI and guessing values on decode were both rejected (#217).unified()reports the conflict.C2. No Mention term in PROV-JSONLD (permanent). The submission defines none, so serialising or deserialising a document with a
ProvMentionraisesprov.serializers.provjsonld.ProvJSONLDException(#248).C3. PROV-XML escapes attribute names that are not NCNames. A name may start with a digit or contain
' ( ) , : ; [ ] =; each illegal character is written as_xHHHH_, the OpenXML convention, and reversed on read (#289). A third-party name that already looks like an escape is therefore unescaped.C4. PROV-N local parts. A character
PN_LOCALcannot express, such as a space, is percent-encoded with aProvWarning, and the identifier reads back as the encoded IRI, soex:a bbecomesex:a%20b. A%that starts no escape is written as%25, with the same warning. From 3.2.3 such a name also warns when it is built, and 3.3.0 rejects it (#524). PROV-O rejects an IRI containing a space. A namespace prefix must be a validPN_PREFIX(a letter first, then name characters or., not ending in.);provdoes not validate or rename one that is not.C5. Empty language tag.
Literal("hi", langtag="")survives PROV-XML only, asxml:lang="". PROV-N, PROV-JSON and PROV-JSONLD read it back as a plain string and PROV-O raises. From 3.2.3 an empty tag warns when the literal is built, and 3.3.0 rejects it (#472).C6. Language tag that is not BCP 47. PROV-N writes an underscore separator as a hyphen, so
en_USreads back asen-US; PROV-O raises rdflib’sValueError. PROV-JSON, PROV-XML and PROV-JSONLD pass the tag through unchanged. From 3.2.3 such a tag warns when the literal is built, and 3.3.0 rejects it (#472).C7. Zone offsets that are not whole minutes. Every format writes such an
xsd:dateTimein UTC, because the datatype allows no seconds in an offset. The instant is unchanged and the round trip compares equal; the original offset is not preserved.C8. RDF’s
json-ldsyntax is not PROV-JSONLD.rdf_format="json-ld"is rdflib’s generic JSON-LD writer over the PROV-O graph, with every PROV-O limitation. Useformat="jsonld"for PROV-JSONLD.
Reading other producers’ output¶
A round trip covers prov’s own output. Reading what other tools write is a separate claim.
Each allowance below states its reason; prov does not adopt another implementation’s
departure from the Recommendations without one.
PROV-N profiles¶
Profile |
Accepts |
|---|---|
|
The Recommendation grammar only. Mention is |
|
The grammar plus the bare |
|
As |
No profile accepts the keywords person, organization, softwareAgent, collection,
emptyCollection, plan, wasRevisionOf, wasQuotedFrom or hadPrimarySource. They are
not PROV-N. The grammar expresses subtypes through prov:type, no producer writes them and
ProvToolbox’s reader rejects them; they raise ProvNSyntaxError under strict and
default and are skipped under lenient. The PROV-Dictionary set-of-pairs literal
({("k1", e1), ...}) is not supported.
The reader also accepts a leading byte order mark, a carriage return as a line end, an
all-digit local name as an attribute name or datatype, and a bytearray stream. A prefix
declared twice in one scope and a duplicate bundle identifier are errors.
PROV-XML¶
A reference element with no
prov:refwhose child is itself a reference, the shape ProvToolbox writes for ahadMembermember, is resolved with aProvWarning; the intent is unambiguous. A reference with neitherprov:refnor text raisesProvXMLException.<prov:other>elements and attributes the model cannot represent are skipped with aProvWarning.Names escaped as in C3 are unescaped.
PROV-JSONLD¶
The decoder accepts the submission’s compacted shape only. It is not a JSON-LD processor: no expansion, no remote contexts.
ProvToolbox’s
prov:-prefixed spellings of the type and special terms are accepted.An array-valued
entityon aMembershipstatement, which the submission (section 4.18) allows and ProvToolbox always writes, decodes to onehadMemberper member, each with the statement’s@idand attributes; an empty array raisesProvJSONLDException.Attribute values follow the 2026-10-14 revision of the PROV-JSONLD schema (openprov/prov-jsonld#7). A node reference, such as
{"@id": "ex:shed"}, is a qualified name under any attribute. A bare string is a qualified name undertype,locationandrole, which the context coerces to@id, and a string under any other attribute. A node reference whose IRI no declared namespace compacts becomes anIdentifier. A node reference with a key other than@id, or with an empty@id, raisesProvJSONLDException. Anxsd:QNameorprov:QUALIFIED_NAMEvalue object, the formprovwrites for a qualified name under any other attribute, is also read as a qualified name, although a JSON-LD processor reads it as a typed literal.
PROV-O¶
An attribute predicate under a namespace declared neither in the document nor in the graph gets a minted prefix, with a
ProvWarning.Two relations sharing an identifier raise, as C1 describes.
rdf_formatselects the RDF syntax to read.
prov.read() detects the format from the content and forwards each reader’s own options
(profile for PROV-N; rdf_format, relation_mapper and predicate_mapper for PROV-O;
the json.load hooks for PROV-JSON and PROV-JSONLD). An option a format does not accept
raises TypeError naming the format.
Corpus evidence¶
The PROV-N conformance corpus runs at every test run.
Set |
Profile |
Files |
Result |
|---|---|---|---|
Every example in the PROV-N and PROV-DM Recommendations |
|
127 |
100 parse and round-trip through the writer. 27 are excluded because the Recommendation’s prose presents them as PROV-N but the grammar rejects them: fragments missing a paired argument, bare literals, ellipses, a copy-paste |
ProvToolbox’s hand-written PROV-N test documents |
|
9 |
4 parse. 5 are excluded: bare local names with no default namespace, the PROV-Dictionary set-of-pairs literal, and a bare IRI as a datatype. |
PROV-N that ProvToolbox’s writer produced from the shared test corpus, compared with the PROV-JSON fixture of the same name |
|
388 |
229 equal. 159 differ for reasons in ProvToolbox’s 2023 generator, not in |
The corpus README names every excluded or differing file with its reason.
Not implemented¶
A bundle as a first-class entity of type
prov:Bundle(PROV-DM §5.4.2), so the provenance of a bundle itself cannot be asserted (#261).Factories for the agent subtypes and for
EmptyCollection; add theprov:typethroughother_attributes(#260).PROV-Dictionary (#129).
PROV-CONSTRAINTS validation beyond what
unified()checks (#62).