Skip to main content

magical_py

Native Python bindings for magical_rs, a zero-dependency Rust library that identifies files by their magic bytes.

This is not a drop-in replacement for python-magic, and it is not trying to be one. python-magic returns a string like "image/png" and leaves you to parse it. This returns a typed value that carries its media type and conventional extension with it.

Install

Not released to PyPI yet. From a checkout of this repository:

pip install ./bindings/python

Once published this becomes pip install magical-py, and there is a binary wheel for every platform we publish for. One abi3 wheel covers CPython 3.8 and later, so you will not have to build from source.

FileKind covers all 114 formats the Rust crate detects, and the enum is declared in Python rather than generated, so it is a real enum.Enum and your editor completes FileKind. with every member and its docstring.

Use

from magical_py import FileKind, detect

kind = detect("photo.jpg")

kind is FileKind.Jpg      # True, a real enum member your editor can complete
kind.value                 # 'jpg', a stable id for serialising
kind.mime                  # 'image/jpeg'
kind.extension             # 'jpg'
kind.description           # 'JPEG'

For data you already have in memory:

from magical_py import detect_bytes

detect_bytes(header)       # FileKind.Png | None

Both return None when nothing matches, and raise the usual OSError subclasses when a file cannot be read:

try:
    kind = detect(path)
except FileNotFoundError:
    kind = None

What it looks like

Each member carries its display name as its __doc__, which is the attribute the REPL and help() read. Python 3.9 and later render it for all 114 members; Python 3.8 omits it from help(), so on 3.8 read __doc__ directly as below.

>>> FileKind.Png.__doc__
'PNG'
>>> FileKind.ISO.__doc__
'ISO 9660'
>>> FileKind.PkgZip.description
'Zip / JAR / APK'

Things worth knowing

Detection reads magic bytes only. The file name is never consulted, so a .jpg that actually contains PNG data is reported as FileKind.Png. That is the behaviour you want from a detection library, and it is also why the extension is advisory rather than something to switch on.

Some media types are None. FileKind.mime and FileKind.extension return None when no media type is registered or verified for that format. None means "there isn't one", never "we guessed". A wrong media type would be a documentation bug of the same kind as a wrong magic byte, and this project does not ship those.

detect reads 36,870 bytes. ISO 9660 stores its magic at offset 36,865, so detecting it means reading that far into the file. detect does that for you; magical_py.bytes_read() reports the figure if you are reading headers yourself. Do not hardcode 2048 and assume you are done.

Some signatures are only two bytes. 9 formats match on nothing but a two-byte prefix: Arj, Bitmap, Gzip, MP3, MSDOS, Pcx, Pickle, SerializedJavaData and Zlib. Those are the values the formats themselves specify, so a file beginning with those bytes is reported as that format even if it is not really one. Each one is listed with its bytes in the magical_rs README.

Two rules look at more than a fixed pattern. FileKind.ScriptExecute requires a / later on the first line, so a bare #! does not count; FileKind.WEBP requires the full RIFF....WEBP layout. The shebang rule exists because #!AMR is the literal magic of AMR audio: without the / check, the script rule claimed those files and they became undetectable.

Type checking

The package ships a py.typed marker and stubs for the compiled module, and it is checked with pyright in strict mode. pythonVersion is pinned to 3.8 so the checker enforces the same floor as the wheel.

from magical_py import FileKind

# Narrowed to FileKind after the None check.
kind: FileKind | None = detect("photo.jpg")
if kind is not None:
    reveal_type(kind)     # FileKind
    reveal_type(kind.mime)  # str | None

Development

Managed with uv.

uv sync                # create the venv and install maturin, pytest, pyright
uv run maturin develop # build the extension into the venv
uv run pytest          # run the tests
uv run pyright         # type check in strict mode
uv build               # build the wheel and the sdist

python/magical_py/_kinds.py is generated. Edit the metadata table in gen_kinds.ps1 and re-run it; tests/test_drift.py fails if the enum and the Rust detection table disagree.

License

MIT, the same as magical_rs.

Metadata

Release files for magical-py 0.1.0

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

Source distribution (sdist)

Source distribution for magical-py 0.1.0
File Size Uploaded
magical_py-0.1.0.tar.gz 69.8 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for magical-py 0.1.0
File
magical_py-0.1.0-cp38-abi3-win_amd64.whl CPython 3.8 abi3 Windows x86-64 Details
magical_py-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.8 abi3 Linux glibc 2.17+ x86-64 Details
magical_py-0.1.0-cp38-abi3-macosx_11_0_arm64.whl CPython 3.8 abi3 macOS 11.0+ ARM64 Details
magical_py-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl CPython 3.8 abi3 macOS 10.12+ x86-64 Details

Total release size: 3.2 MB

Release files / magical_py-0.1.0.tar.gz

Download URL magical_py-0.1.0.tar.gz
Size 69.8 kB
Tags Source
SHA-256 checksum
How to use checksums
550ff0def0aab6026a512f6a42180c534a6ae8ca81de577808db50d1f3f71a8d
BLAKE2b-256 checksum
How to use checksums
e0829e79413259f6c0a2a63847d7e6242531a379f0632b60874a8a7db68dbecf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / magical_py-0.1.0-cp38-abi3-win_amd64.whl

Download URL magical_py-0.1.0-cp38-abi3-win_amd64.whl
Size 187.9 kB
Tags CPython 3.8 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
604f3a49dca667d11cedfa32b8c83458e33e48a2fe1eced1dbd6044daf214c8f
BLAKE2b-256 checksum
How to use checksums
4ebd79a6755b9442faa19be250862c18f57f37b349ce959cc0f4c9cf5552a532
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / magical_py-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL magical_py-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.2 MB
Tags CPython 3.8 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
ba50027074db8d87b4fd25ff4f977181d8c0ade7438c77a6a3707648084eee1d
BLAKE2b-256 checksum
How to use checksums
aa98c6e0d433ffa5e1b87edebf9a75b7fa2c4bdab105e0e274bf9ace835aabc4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / magical_py-0.1.0-cp38-abi3-macosx_11_0_arm64.whl

Download URL magical_py-0.1.0-cp38-abi3-macosx_11_0_arm64.whl
Size 348.1 kB
Tags CPython 3.8 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e5dddc53e6311b978902bc19f995e61fd8596412ae869b320d4eb44332303cd0
BLAKE2b-256 checksum
How to use checksums
33bde52a560257e27e82539c374fb125af070b36c4f7b3ef728dc62c42bf2fd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / magical_py-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl

Download URL magical_py-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl
Size 325.5 kB
Tags CPython 3.8 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
8112f31c7751fc9bbda0b39d6b611c8cd8bdaad02815999e975126648694b5f0
BLAKE2b-256 checksum
How to use checksums
fdaa8fad39c16859cb6af0a9a7275641cd0bd350ddc88d16f2ba20085437aff1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.5.0

5 release files

0.4.0

5 release files

0.3.0

5 release files

0.2.0

5 release files

0.1.1

5 release files

This release

0.1.0 This release

5 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