Skip to main content

eqxconfig

eqxconfig is a small utility for constructing an Equinox module from TOML without writing a second configuration class. It derives a Pydantic model from the concrete module's annotated __init__ signature, validates the configuration, and calls the unchanged constructor.

TOML
  ↓
dynamically generated Pydantic schema
  ↓
validated constructor arguments
  ↓
Equinox __init__
  ↓
ordinary eqx.Module / JAX PyTree

The package requires Python 3.14 or newer.

Installation

python -m pip install eqxconfig

Usage

import equinox as eqx
import jax

from eqxconfig import ConfigurableModule


class MLP(ConfigurableModule):
    mlp: eqx.nn.MLP

    def __init__(
        self,
        in_size: int,
        out_size: int,
        width_size: int = 128,
        depth: int = 3,
        seed: int = 0,
    ) -> None:
        self.mlp = eqx.nn.MLP(
            in_size=in_size,
            out_size=out_size,
            width_size=width_size,
            depth=depth,
            key=jax.random.key(seed),
        )


model = MLP.from_toml("model.toml")
model_with_overrides = MLP.from_toml(
    "model.toml",
    width_size=512,
    depth=6,
)

model.toml contains constructor arguments at its root:

in_size = 32
out_size = 10
width_size = 256
depth = 4
seed = 42

Precedence is:

__init__ defaults < TOML < explicit from_toml overrides

The final configuration—including constructor defaults, TOML values, and explicit overrides—goes through one Pydantic v2 validation pass. The generated schema preserves annotations and defaults, so Annotated/Field constraints, Literal, unions, enums, constrained types, and nested Pydantic models work normally. Unknown keys are forbidden. Pydantic validation errors, TOML decoding errors, and file access errors retain their standard exception types.

Nested ConfigurableModule fields are derived recursively from their own constructor signatures. Each nested value is built through its ordinary Equinox constructor, so custom __init__ methods, field converters, __post_init__, __check_init__, frozen-module semantics, and PyTree behavior are preserved at every level. This also applies inside optional, list, tuple, and dictionary fields. Passing an already constructed nested module as an override preserves that instance without constructing or checking it again.

The schema is generated lazily once per Equinox subclass. Constructor parameters must be annotated and must be positional-or-keyword or keyword-only. Positional- only parameters, *args, and **kwargs are deliberately rejected with a TypeError. Constructor defaults must be ordinary Python defaults in the signature; defaults embedded in Field(...), private parameter names, and the reserved name model_config are rejected because they cannot preserve a one-to-one constructor schema. Configuration keys match constructor parameter names; Pydantic validation aliases are not supported in v0.1.

Direct construction remains ordinary Python and Equinox:

model = MLP(in_size=32, out_size=10, width_size=512)

Configuration parsing and module construction happen before JAX transformations. Do not call from_toml inside jax.jit; pass the resulting module into compiled functions as a normal Equinox PyTree.

Development

Install the development dependency group with uv:

uv sync --all-groups

Run the individual checks with:

uv run ruff check .
uv run ruff format --check .
uv run pyrefly check
uv run pytest
uv build
uv run twine check dist/*

The repository uses prek for local hooks. From a fresh checkout:

prek install
prek run --all-files

Releases

The package version lives in pyproject.toml. Update it with uv version, merge the change, and push a matching tag such as v0.1.0. The release workflow builds and validates one wheel and one source distribution, attaches those exact files to a GitHub Release, and publishes the same files to PyPI.

PyPI publishing uses Trusted Publishing, not an API token. Before the first release, the repository owner must:

  1. Create a GitHub environment named pypi (and add any desired deployment protection rules).
  2. In the PyPI project's publishing settings, add a GitHub Trusted Publisher for the actual repository owner and repository name, workflow file release.yml, and environment pypi.

No long-lived PyPI credential should be added to GitHub secrets.

Scope

eqxconfig intentionally handles only root-level TOML-to-constructor configuration. It is not a general configuration framework and does not add environment variables, command-line parsing, remote sources, or configuration work inside JAX transformations.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eqxconfig-1.0.3.tar.gz (24.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eqxconfig-1.0.3-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file eqxconfig-1.0.3.tar.gz.

File metadata

  • Download URL: eqxconfig-1.0.3.tar.gz
  • Upload date:
  • Size: 24.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for eqxconfig-1.0.3.tar.gz
Algorithm Hash digest
SHA256 03b8643738c1a3b15f231c1487e5dadb2158ee4d4cf3b48515b1907a94537a0a
MD5 849b5523ff8d45cd8cedf44126325ffc
BLAKE2b-256 f85dd35abf94ec35129aeb9a7d24699eab992722dd3681d4a58c4e265a23d3a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for eqxconfig-1.0.3.tar.gz:

Publisher: release.yml on varchasgopalaswamy/eqxconfig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file eqxconfig-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: eqxconfig-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for eqxconfig-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 3b09855bdbbb3b7d08661804bfc5b9660177dd05bfdcb92837eb121c00d9ff8e
MD5 1a51abf83f4fa120ff05c0416469b79b
BLAKE2b-256 1a669774496d192899269d5f48488b3ad312178b04d20e384d43228657de9b9e

See more details on using hashes here.

Provenance

The following attestation bundles were made for eqxconfig-1.0.3-py3-none-any.whl:

Publisher: release.yml on varchasgopalaswamy/eqxconfig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.0.3 This release

2 files

1.0.2

2 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