Type-check code that uses prov¶
prov ships inline type annotations and a py.typed marker, so mypy and pyright check
your calls against them with no stub package. This guide covers the attribute arguments,
attributes and other_attributes, which are where a strict checker most often
objects. It describes prov 3.2.2 and later.
Pass attributes as a dict¶
A dict literal written in the call type-checks, whatever mix of names and values it holds:
import datetime
from prov.model import PROV, PROV_LABEL, PROV_TYPE, ProvDocument
document = ProvDocument()
document.add_namespace("ex", "http://example.org/")
report = document.entity(
"ex:report",
{
PROV_LABEL: "Quarterly report",
PROV_TYPE: PROV["Collection"],
"ex:pages": 12,
"ex:filed": datetime.datetime(2026, 9, 18),
},
)
A dict built before the call type-checks too when its values share one type:
labels = {PROV_LABEL: "Quarterly report"}
document.entity("ex:summary", labels)
Annotate a dict that mixes value types¶
mypy infers a dict that is built before the call, with values of more than one type, as
dict[str, object], and reports the call. Annotate the variable with
AttributeValue, the type of the values an attribute accepts:
from prov.model import AttributeValue
details: dict[str, AttributeValue] = {"ex:pages": 12, "ex:status": "filed"}
document.entity("ex:appendix", details)
Pyright accepts the call without the annotation.
AttributeValue covers str, int, float, bool, datetime.datetime,
Identifier, QualifiedName,
Literal, any ProvRecord, and None. A
record stands for its identifier. A None value is skipped.
Pass attributes as pairs¶
A list, tuple, set or iterator of (name, value) pairs is accepted as well. Use pairs to
give one attribute several values, which a dict cannot hold:
document.entity("ex:filing", [(PROV_TYPE, "ex:Report"), (PROV_TYPE, "ex:Filing")])
The values in pairs are typed Any, so a checker does not examine them.
A value whose static type is Iterable[...] or Collection[...] is reported, although it
works at runtime. Wrap it in list(), or type it as a Sequence, a Set or an
Iterator:
from collections.abc import Iterable
def review_attributes() -> Iterable[tuple[str, str]]:
yield ("ex:reviewer", "ex:alice")
document.entity("ex:review", list(review_attributes()))
Give other values an XSD datatype¶
A checker reports a dict value of any other type, such as decimal.Decimal,
datetime.date or bytes. Those values have no PROV form, and prov cannot serialise
them faithfully. Write the value as a Literal with its XSD
datatype:
from prov.model import XSD, XSD_DECIMAL, Literal
document.entity(
"ex:invoice",
{
"ex:total": Literal("1250.50", XSD_DECIMAL),
"ex:due": Literal("2026-10-31", XSD["date"]),
},
)