Metadata-Version: 2.4
Name: mimey
Version: 0.4.0
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
License-File: LICENSE
Summary: A fast and efficient MIME type and file extension detector implemented in Rust, exposed as a Python package.
Keywords: MIME,file type detection,Rust,Python
Home-Page: https://github.com/4thel00z/mimey
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

<p align="center">
  <img src="https://raw.githubusercontent.com/4thel00z/mimey/master/assets/logo.svg" width="180" alt="mimey logo">
</p>

<h1 align="center">mimey</h1>

<p align="center">
  <strong>Tells you what a file is from its first bytes. Rust underneath.</strong>
</p>

<p align="center">
  <img src="https://img.shields.io/pypi/v/mimey?logo=pypi&logoColor=white&color=2a66e0" alt="PyPI">
  <img src="https://img.shields.io/pypi/pyversions/mimey?logo=python&logoColor=white&color=3776AB" alt="Python versions">
  <img src="https://img.shields.io/badge/built%20with-rust-292420?logo=rust&logoColor=white" alt="Built with Rust">
  <img src="https://img.shields.io/badge/license-MIT-2a66e0" alt="MIT license">
</p>

---

```sh
uv add mimey     # or: pip install mimey
```

```python
>>> import mimey
>>> mimey.detect_mime(b"\x89PNG\r\n\x1a\n")
'image/png'
>>> mimey.detect_type(b"\x89PNG\r\n\x1a\n")
'.png'
```

No filename, no `libmagic`, no shelling out to `file`. It reads the bytes you
hand it and answers. Detection looks at the first 3072 bytes at most, so an
8-byte header and a 1 MB payload cost the same.

Wheels ship for CPython 3.10–3.14 on manylinux, musllinux, macOS and Windows.
Linux additionally gets free-threaded 3.14t and PyPy.

## Register your own types

Registered types are checked before the built-in table, in registration order,
so they can teach `mimey` a format it does not know or override a verdict it
gets wrong.

```python
mimey.register("application/x-nes-rom", ".nes", magic=b"NES\x1a")

rom = open("game.nes", "rb").read()
mimey.detect_mime(rom)   # 'application/x-nes-rom'
```

Pass `offset` when the signature does not start at byte 0:

```python
mimey.register("application/x-offset", ".off", magic=b"HERE", offset=4)
```

Matching stays in Rust. A signature that hits is *faster* than built-in
detection, because it never walks the detection tree.

For anything a fixed signature cannot express, hand it a callable instead:

```python
mimey.register("application/x-even", ".even", matcher=lambda data: len(data) % 2 == 0)
```

The callable gets the same `bytes` you passed in, and its exceptions propagate
to the caller. Every detection re-enters Python once per registered callable, so
prefer `magic` when a signature is enough.

```python
mimey.registered()          # [('application/x-nes-rom', '.nes')]
mimey.clear_registrations()
```

## Performance

Per call, macOS arm64 / CPython 3.12, min-of-7 over 200k calls:

| | ns/call |
|---|--:|
| `detect_mime`, no registrations | **83** |
| one registered signature, no match | 89 |
| one registered signature, **matches** | **37** |
| one registered callable | 128 |

Cost is flat in payload size — the detector sniffs a prefix, so the per-call
number is dominated by the Python↔Rust boundary, not by your data. An empty
registry costs a single relaxed atomic load, so the feature is free when unused.

### Free-threading

The module declares `gil_used = false`, so importing it on a free-threaded
build does not silently switch the GIL back on. Detection holds no shared
state, so it scales:

| threads | ns/call | speedup |
|--:|--:|--:|
| 1 | 75.0 | 1.0× |
| 2 | 38.9 | 1.9× |
| 4 | 19.8 | 3.8× |
| 8 | 14.6 | 5.1× |

CPython 3.14.6t, same machine, 400k calls per thread.

## Typing

The package ships `py.typed` and a stub file, so `mypy` and `pyright` see real
signatures rather than `Any`.

## License

MIT. Built on [mimetype-detector](https://crates.io/crates/mimetype-detector)
and [PyO3](https://pyo3.rs).

