Skip to main content

iirds

Read and write iiRDS packages in Python.

pip install iirds
import iirds

with iirds.open("machine-docs.iirds") as pkg:
    print(pkg.version, pkg.variant)      # "1.3" "unrestricted"
    graph = pkg.graph                    # rdflib.Graph of the package metadata
    data = pkg.read("content/topic1.xhtml")

iirds.pack("my-package-directory/")     # → my-package-directory.iirds,
                                         #   mimetype first and stored,
                                         #   byte-identical on every run

Deliberately small: open a container, get the metadata as an RDF graph, read files, write a conformant container back. It does not validate — that is iirds-validate's job (185 rules, offline, CI-friendly), and keeping the two apart keeps this library at one dependency (rdflib).

Two things the pack() half gets right that generic ZIP tooling gets wrong: the mimetype entry is first and stored uncompressed, and packing the same directory twice produces byte-identical output (honouring SOURCE_DATE_EPOCH), so "this archive came from that directory" is checkable with a hash instead of taken on trust.

Stewardship

The iirds name on PyPI belongs to the standard's community more than to any one project. Should the iiRDS Consortium want this name for an official SDK, it will be transferred on request — until then it does real work rather than squatting. iirds-sdk is an alias of this package and travels under the same pledge.

This is an unofficial project, not affiliated with or endorsed by the iiRDS Consortium or tekom Deutschland e.V. "iiRDS" is used descriptively, to name the standard these functions read and write.

Queries

Package.instances_of(cls), is_instance(node, cls) and label_of(node) (also module-level, taking any rdflib graph) answer "what is in this package" with section-7 semantics: an instance of a class the package itself declares beneath an iiRDS class is an instance of that class.

from iirds import IIRDS
with iirds.open("docs.iirds") as pkg:
    for topic in pkg.instances_of(IIRDS["Topic"]):
        print(pkg.label_of(topic))

The closure walks only the package's own rdfs:subClassOf declarations — no ontology is bundled, so instances_of(IIRDS["InformationUnit"]) returns only what the package declares beneath it. One rdflib trap worth knowing: Namespace subclasses str, so IIRDS.format is str.format; always use bracket syntax (IIRDS["format"]).

Deliberately not here (so nobody waits for it): per-class conveniences (topics() is instances_of(IIRDS["Topic"]) and 25 siblings would drift), typed_exactly (one rdflib call on the public graph), a bundled ontology, SPARQL wrappers, and anything that returns a verdict.

Files behind renditions

pkg.source_of(node) resolves a Rendition's iirds:source to the entry it names — the helper a naive implementation gets wrong. The core normalisation matches the validator verbatim (leading slashes stripped, ./ and internal ../ collapsed); folding backslashes and refusing a path that escapes the package are the SDK's own added strictness. pkg.open(node) returns a readable stream over that entry (streaming — a two-gigabyte PDF is read, not loaded), raising when the node names nothing or names an absent entry. The stream borrows the package's open ZIP handle, so consume it while the Package is still open rather than after close(). Resolution never judges existence: that split keeps "what does this rendition say" apart from "is this package whole", which is the validator's question.

Writing metadata

write_metadata(graph, destination=None) serialises a graph as metadata.rdf — and self-verifies: the bytes are parsed back through the same guarded reader every consumer uses and compared isomorphically before being handed over, so "the validator can read what the SDK wrote" is enforced at write time. Byte-stable across repeated writes of the same Graph object, and no more: rdflib mints blank-node labels from a process-global counter, so even identically-built graphs serialise apart, and canonicalisation would be a different, heavier promise. Composes with pack(): write the metadata into a directory, pack the directory, open the result.

Untrusted input

A package arrives from a supplier, so open() treats its metadata the way iirds-validate does — same guards, same error strings, shared code:

  • XML entity declarations are refused (a tame one is indistinguishable from the geometric kind until the parser is already inside it),
  • metadata above 64 MiB uncompressed is refused before being read,
  • a JSON-LD @context that names something to fetch is refused wherever it nests — a URL, an @import, a scoped context on a term, and equally a bare name, which the parser would otherwise resolve against whatever directory the tool was run from and read off your disk. Reading a package touches neither the network nor anything outside the container,
  • a byte order mark decides the encoding, as XML says it should.

META-INF/metadata.jsonld is read and merged beside metadata.rdf (isomorphic sources count once — blank nodes double under naive union). pkg.metadata_sources, pkg.metadata_graphs and pkg.parse_errors say what parsed, which document said what, and what was refused. pkg.graph raises only when nothing parsed, because an empty graph is also what a real, sparse package looks like.

API stability

0.x: the surface will grow; what is published is intended not to break. The API is small on purpose — additions are cheap, retractions are not.

Licence

Apache-2.0, © 2026 Wooyong Lee. Contributions need a Signed-off-by line (DCO); see the workflow in .github/.

Release files for iirds 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for iirds 0.3.2
File Size Uploaded
iirds-0.3.2.tar.gz 48.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for iirds 0.3.2
File Interpreter ABI Platform
iirds-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 69.7 kB

Release files / iirds-0.3.2.tar.gz

Download URL iirds-0.3.2.tar.gz
Size 48.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ef7de5893ad724caae611c1bb364916cf59be8f59a2a1210d2380786bb5ad7e4
BLAKE2b-256 checksum
How to use checksums
cfe4a2183379fe36f26497879dd3b50a1525bdc68370c9cec3aba902c0a38868
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release files / iirds-0.3.2-py3-none-any.whl

Download URL iirds-0.3.2-py3-none-any.whl
Size 21.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
83c35ea0e5514e0208d8ab29588e23dc5bc50f3e31d650db48c7562867250d36
BLAKE2b-256 checksum
How to use checksums
e3e6cc09ef3c8a887488a80127e3312db8f424455601341da2a36a684a2d9b39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release history Release notifications | RSS feed

0.7.1

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

This release

0.3.2 This release

2 release files

0.3.1

2 release files

0.3.0

1 release file

0.2.0

1 release file

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page