Skip to main content

minimal-magic

minimal-magic does two things:

  1. Type conversion. It turns parsed JSON/YAML/TOML into typed Python — plain dataclasses and TypedDicts, checked field by field. This is msgspec.convert() without the C extension and without the Struct base class: point it at the types you already declared.
  2. File finding. load_candidate() picks and merges the right config files out of a list of candidates — navigating into a section such as [tool.myapp] in a shared pyproject.toml, overriding left to right, and letting individual fields say how they merge.

It deliberately does not do a third thing. Error locations — the filename:line:column on every ParseError you see below — come from the parse-errors package this is built on. If located exceptions are all you want, without typed conversion or file merging, use that package directly; minimal-magic consumes it rather than reimplementing it.

The cost of converting in Python is speed: tens of times slower than msgspec on flat bulk arrays, with lower overhead on config-shaped nested data. The overhead depends on the data shape and the alternate library; see shapes and alternate libraries for the benchmark notes. For a config file read once at startup, that is a few milliseconds you will not notice.

Install

pip install minimal-magic

YAML support needs PyYAML, an optional dependency: pip install minimal-magic[yaml].

Requires Python 3.10+. Reads (or more accurately, converts) JSON, YAML, and TOML. Since TOML is a well-defined superset of INI, we do not plan to support configparser or other INI dialects.

load()

Load a file without a type — returns plain dict/list, same as the underlying parser:

from minimal_magic import load

config = load("config.json")

Load into a dataclass and get type-checked, located errors:

import dataclasses
from minimal_magic import load

@dataclasses.dataclass
class ServerConfig:
    host: str
    port: int
    debug: bool = False

config = load("config.yaml", type=ServerConfig)

If config.yaml has a type mismatch, the error tells you exactly where:

config.yaml:3:7: Expected `int`, got `str`

Reject keys that don't exist on the type:

config = load("config.toml", type=ServerConfig, forbid_unknown_fields=True)
# ParseError: config.toml:5:1: Unexpected field `typo` in `ServerConfig`

load() also accepts data= (pre-read bytes) and format= (override extension detection).

convert()

If you already parsed the file yourself, convert() applies the same type conversion and error-location logic that load(..., type=...) uses:

from minimal_magic import convert

raw = {"host": "localhost", "port": 8080}
config = convert(
    raw,
    data=b'{"host": "localhost", "port": 8080}',
    format="json",
    filename="config.json",
    type=ServerConfig,
)

If you pass the original bytes as data=, convert() can build a source map and report the exact line and column on validation errors. If you omit data=, you still get the filename and JSON pointer path, just without exact line/column locations. When data= is provided, format= is only needed if the filename extension does not make the format detectable.

load_candidate()

Loads and merges multiple config files. Each entry is either a plain path or a Candidate(filename, prefix=...) that navigates to a sub-section before merging. Files are processed left to right; later entries win.

from minimal_magic import load_candidate, Candidate

config = load_candidate([
    "defaults.toml",
    Candidate("pyproject.toml", prefix="tool.myapp"),  # reads [tool.myapp]
    "local.toml",                                       # optional local overrides
], type=AppConfig)

If a candidate's prefix is absent in its file, that candidate contributes nothing — it is not an error. Every listed file is still read, though, so a candidate that does not exist on disk raises FileNotFoundError.

Errors name the candidate that actually supplied the bad value. The merge remembers where every key came from, so a value inherited from defaults.toml and never overridden is reported at its line in defaults.toml, not in whichever file happened to be read last:

defaults.toml:2:8: Expected `int`, got `str`

Two things have no single file to point at. A value built by a field's merge callable exists in none of the files, so it is blamed on the candidate whose value arrived as override — the bytes being validated. An error at a key no candidate supplied, such as a missing required field, falls back to the last candidate.

More documentation

Metadata

Release files for minimal-magic 0.7.1

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

Source distribution (sdist)

Source distribution for minimal-magic 0.7.1
File Size Uploaded
minimal_magic-0.7.1.tar.gz 120.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for minimal-magic 0.7.1
File Interpreter ABI Platform
minimal_magic-0.7.1-py3-none-any.whl Python 3 none any Details

Total release size: 168.6 kB

Release files / minimal_magic-0.7.1.tar.gz

Download URL minimal_magic-0.7.1.tar.gz
Size 120.3 kB
Tags Source
SHA-256 checksum
How to use checksums
e2e5606c660d3c8b94cdbd4d03fde19ebf0dc5226d2033fb0f1d5a8abf6209b5
BLAKE2b-256 checksum
How to use checksums
db6253511f1dd5b4108ced2d8006675284c694a1bc2524ec01a4f9a258bf8a00
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 Sep 17, 2026.

Transparency log

Release files / minimal_magic-0.7.1-py3-none-any.whl

Download URL minimal_magic-0.7.1-py3-none-any.whl
Size 48.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5a489e759879fb57214c282df5f2811374faf7f96a5f5aef3e144d1d34642805
BLAKE2b-256 checksum
How to use checksums
68bbb0130ca02ba608fa12396b9b6f3c79e94af2046476dc6a93f9a66ad41d03
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 Sep 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.7.1 This release

2 release files

0.6.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