unpackio for Python
unpackio is the Python distribution for the repository's security-focused,
unpack-only Rust 7z, ZIP, RPM, CPIO, Debian-package, and ARJ readers and its
separate LZ4/Zstandard/Unix .Z stream readers. The package imports as
unpackio; its implementation module is unpackio._native.
The binding delegates all parsing, graph validation, decoding, cryptography, CRC verification, limits, and path classification to the stable Rust core. It does not create archives and does not automatically extract archive names to the filesystem.
ZIP and RPM use concrete APIs rather than pretending to be 7z archives:
import io
import unpackio
zip_archive = unpackio.open_zip_path("input.zip", password=b"zip-password")
for entry in zip_archive.entries():
print(entry.index, entry.name, entry.compression_method, entry.encryption)
rpm = unpackio.open_rpm_path("package.rpm")
print(rpm.payload_compression, rpm.header.value(1000))
output = io.BytesIO()
rpm.extract_entry_to(0, output)
Use open_zip_bytes/open_zip_path and
open_rpm_bytes/open_rpm_path. ZIP passwords are bytes and remain scoped
to one ZipArchive; RPM accepts no password. Both formats preserve raw names
as bytes, duplicate order, metadata, and safe-path classification. Neither
API writes a name to disk or returns all decoded payloads as one object.
Format-specific data model
Applications consume the native, format-specific unpackio objects directly:
import io
import unpackio
archive = unpackio.open_zip_path("sample.zip", password=b"infected")
entry = archive.entries()[0]
verified = io.BytesIO()
archive.extract_entry_to(entry.index, verified)
package = unpackio.open_rpm_path("sample.rpm")
print(package.header.as_named_dict().get("name"))
payload = io.BytesIO()
package.extract_entry_to(package.entries()[0].index, payload)
ZipEntry exposes decoded/raw names, comments, extras, sizes, CRC, DOS
timestamp, method, flags, creator/extractor versions, attributes, local-header
offset, encryption kind, and directory metadata.
Passwords are supplied when opening a ZipArchive; trying another password
creates another per-archive session. Even a zero-length encrypted member must
be extracted so its password verifier and authentication data are checked.
RpmArchive.header and .signature_header retain ordered typed tags.
as_named_dict() adds a complete symbolic projection, preserves unknown tags
under numeric keys, returns scalar integers for single-value numeric tags, and
selects the first locale for I18N values. RPM opening validates the complete
supported package, including applicable digests, before member data is
exposed.
These APIs contain no writer, extractall, automatic path use, or runtime
fallback. Callers must apply their own policy before using a metadata name as
a path.
ZipArchive.extract_entries_to and RpmArchive.extract_entries_to use the
same three callbacks as the 7z batch protocol, with ZipEntry or RpmEntry
passed to begin_entry. One work budget and cancellation token cover the
complete call, chunks are bounded, callback exceptions retain their identity,
and finish_entry is the integrity-verified boundary. ZIP verifies
authentication/size/applicable CRC before finalization; RPM has already
verified supported package digests and rechecks applicable CRC-newc member
checksums. A caller should still stage output if callback failure must be
atomic.
RPM typed headers use numeric tags. RpmHeader.entries() retains order and
duplicates; .value(tag) returns the last effective value and .as_dict() is
a convenience projection. OpenPGP blobs are exposed but not authenticated.
The current RPM object retains the bounded decoded CPIO payload, reported by
retained_payload_bytes.
Standalone CPIO, Debian packages, and ARJ likewise use concrete APIs:
import io
import unpackio
cpio = unpackio.open_cpio_path("payload.cpio")
deb = unpackio.open_deb_path("package.deb")
arj = unpackio.open_arj_path("archive.arj")
for entry in cpio.entries():
print(entry.index, entry.format, entry.raw_name, entry.mode)
for entry in deb.entries():
print(entry.index, entry.section, entry.raw_name, entry.kind)
for entry in arj.entries():
print(entry.index, entry.compression_method, entry.raw_name, entry.crc32)
verified = io.BytesIO()
deb.extract_entry_to(0, verified)
Use the corresponding open_cpio_bytes, open_deb_bytes, or
open_arj_bytes function for owned byte input. DebArchive.members() lists
the outer ar members, while entries() lists the indexed control/data tar
entries; extract_member_to exposes an outer member to a caller-selected
writer. CPIO symlink targets are returned as raw bytes by symlink_target.
All three preserve raw names and safe-path classification without applying
paths, modes, ownership, devices, or links.
Their extract_entries_to methods use the same begin/write/finish protocol
with CpioEntry, DebEntry, or ArjEntry. A successful finish_entry is the
integrity boundary for every checksum the format provides: CRC-newc for CPIO,
the already validated tar header for Debian, and member CRC-32 for ARJ. Layouts
without a payload checksum do not gain one. Writer/sink exceptions and
cancellation retain their original Python identity, and chunks remain bounded.
For atomic publication, stage output until the operation succeeds.
The current Debian object retains both bounded decoded tar images. ARJ supports
single-volume methods 0--4 and empty no-data methods 8/9; encrypted entries
remain listable but extraction raises PasswordRequired, while split volumes
and security envelopes are typed unsupported. Standalone CPIO accepts raw
newc, CRC-newc, odc, and historical binary inputs but does not automatically
unwrap a compression stream.
Decoded output is delivered to a Python writer or bounded callback. A writer or callback can observe bytes before a trailing archive CRC is checked, so the operation's successful return is the integrity boundary. Use a temporary destination when output must be published atomically.
Python retains ownership of any 7z password str or ZIP password bytes
passed by the caller and cannot erase that Python object. Every Rust-side
password copy is zeroized and kept only in the corresponding archive session.
Standalone inputs never become synthetic archives. Use open_stream_bytes or
open_stream_path, inspect .info, and select a writer or callback yourself:
import io
import unpackio
stream = unpackio.open_stream_path("payload.zst")
print(stream.info.format, stream.info.uncompressed_size)
output = io.BytesIO()
decoded_bytes = stream.extract_to(output)
The optional format= value accepts lz4, zstd/zstandard, or
z/compress/unix-compress; omit it for magic detection. The binding never
removes an input suffix or opens a derived output path. stream(callback)
sends bounded chunks and preserves Python exceptions or False cancellation.
verify() decodes to a discard sink. There is intentionally no Python method
that returns the complete output as one object.
For LZ4 and Zstandard, successful return means every checksum declared by the
frames was finalized. A writer/callback may have observed earlier unverified
chunks, so atomic publication still requires caller-managed staging. Unix .Z
contains no checksum or declared decoded size; successful return means the LZW
decoder reached a valid EOF under the configured bounds, not that the bytes
are authenticated or protected against clean-boundary truncation.
import unpackio
archive = unpackio.open_path("example.7z")
for entry in archive.entries():
print(entry.index, entry.name, entry.size, entry.crc32)
with open("caller-selected-output.bin", "wb") as output:
verified_bytes = archive.extract_entry_to(0, output)
stream_entry(index, callback) sends the same bounded chunks without first
forming a complete Python output object. Return None or True to continue,
or False to cancel.
extract_entries_to(sink) is the natural-order batch surface for solid
archives. It uses one core work budget and cancellation token for the entire
operation and decodes each solid folder at most once. The sink is structural;
archive names remain metadata and are never opened as filesystem paths:
class Sink:
def begin_entry(self, entry: unpackio.Entry, size: int) -> None:
# Select a destination by entry.index and caller policy, not entry.name.
...
def write_entry(self, index: int, chunk: bytes) -> None:
# Chunks are bounded (currently at most 4 KiB).
...
def finish_entry(self, index: int) -> None:
# This callback is the CRC-verified success boundary for the entry.
...
verified_bytes = archive.extract_entries_to(Sink())
Each sink method returns None or True to continue, or False to cancel.
Python exceptions are re-raised unchanged. begin_entry and write_entry may
be observed before a later member CRC failure; only finish_entry means that
the core verified the applicable member and folder CRCs. A Python exception
raised by finish_entry still makes the overall operation fail. Duplicate
names remain separate index-addressed entries, and empty files receive
begin_entry followed by finish_entry without a write call. Streamless
directories and anti-items intentionally produce no sink event; callers that
need to materialize those records must use archive.entries() metadata and
their own validated policy.
open_volumes accepts a callable or an object with
open_volume(index, expected_name) returning bytes or None; all returned
parts remain subject to the core volume and aggregate-input limits.
Published releases use six optimized cp39-abi3 wheels covering Linux,
macOS, and Windows on x86-64 and ARM64. Each exact wheel must pass this binding
suite on Python 3.12, 3.13, and 3.14 before the separately protected manual
PyPI publication step is available. The wheel adds no Python runtime
dependency or command-line entry point. See the repository RELEASING.md for
the release and Trusted Publisher procedure.
For a local development build:
python -m pip install 'maturin==1.13.3'
maturin develop --manifest-path bindings/python/Cargo.toml
python -m unittest discover -s bindings/python/tests -v
See the repository API.md, SECURITY.md, COMPATIBILITY.md, and
bindings/python/AGENTS.md for the complete contracts and current support
evidence.
Metadata
Release files for unpackio 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| unpackio-0.1.1.tar.gz | 341.4 kB | With provenance | Details for unpackio-0.1.1.tar.gz |
Built distributions (wheels)
Total release size: 6.1 MB
Release files / unpackio-0.1.1.tar.gz
| Download URL | unpackio-0.1.1.tar.gz |
|---|---|
| Size | 341.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f33409bfa0c782845d8ae12c33536005e340d64dd24c682528e42f07c8145eac
|
|
BLAKE2b-256 checksum How to use checksums |
31c1ae2be4573a1cd725d64dc7f2e38b3e2c9e5808170e2125697c25b162139e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 23, 2026.
Transparency logRelease files / unpackio-0.1.1-cp39-abi3-win_arm64.whl
| Download URL | unpackio-0.1.1-cp39-abi3-win_arm64.whl |
|---|---|
| Size | 924.7 kB |
| Tags | CPython 3.9 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
d6fe0b956d69b3737b55f809893a934b3ab0266bd81cb911bc394bd2f8e5045c
|
|
BLAKE2b-256 checksum How to use checksums |
c6d27042446fbdcb3e1db36274d7e6dad9e2a5ad0b4f9968f6ee0ba75c7fb9a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 23, 2026.
Transparency logRelease files / unpackio-0.1.1-cp39-abi3-win_amd64.whl
| Download URL | unpackio-0.1.1-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 969.9 kB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
20b1aa8e0484d6ea6a10d78bd45553b9c888005f20d2d3b109481614425683dd
|
|
BLAKE2b-256 checksum How to use checksums |
56b3d3113a45e844d8b25f03eb3cbddb9f51ca5593773371343aa7109dd61586
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 23, 2026.
Transparency logRelease files / unpackio-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | unpackio-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.0 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
22894777632a132c26c88769a02537d029e9edeb5895ee9f677a04f08e0c2255
|
|
BLAKE2b-256 checksum How to use checksums |
ff5a7b573ffadaf891367ac330f31fb3c22e2d82ee767a1b4fad8a9d9c99e747
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 23, 2026.
Transparency logRelease files / unpackio-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | unpackio-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 985.5 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
0f405d5bb401febfd930f7ac26f3a2a0003248933e1189bbbf32f4a6627a19bd
|
|
BLAKE2b-256 checksum How to use checksums |
edc84f3951dd47116521b46b2c0cd72f43cabbe6393439ed6381df544832e7f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 23, 2026.
Transparency logRelease files / unpackio-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | unpackio-0.1.1-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 921.6 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
b82a798cfb917e898976188f166cdea7e2839ca5456a64ca2da3d90b68b05ee9
|
|
BLAKE2b-256 checksum How to use checksums |
d53de3d7433bb88f7faa7ea989ad99eb91631c00e0225ef2286219d7cef5408c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 23, 2026.
Transparency logRelease files / unpackio-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | unpackio-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 967.0 kB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
817bc22e39b500b2b23e3e08fa13ea8e596f18103dc8ac2d2d88710124e51b59
|
|
BLAKE2b-256 checksum How to use checksums |
9c9d569a9f1c3a81e28f7d9465a8a27bab427d91623bd4fac1e91b89160619e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 23, 2026.
Transparency logSecurity for unpackio 0.1.1
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.
Full provenance
All 7 files in this release have been uploaded with provenance metadata.
Attestation for unpackio-0.1.1.tar.gz
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 Jul 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.