Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.7.1 instead.
Reason given by maintainers: Security: upgrade to iirds 0.3.1 or later (see SECURITY.md)

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 remote JSON-LD @context is refused wherever it nests — reading a package never touches the network,
  • 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.0

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

Built distribution (wheel)

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

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

Download URL iirds-0.3.0-py3-none-any.whl
Size 18.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f389adae8806dc80c4b03fc3ede2dfca5484fdf512bfa1e055c3867db910a8b
BLAKE2b-256 checksum
How to use checksums
ea73e1744298ca06d5657b5ffc68ecec31ed083e9a7124fcde2f58578fd837fa
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 25, 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

0.3.2

2 release files

0.3.1

2 release files

This release

0.3.0 This release

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