Skip to main content

lunaconf

lunaconf is a small configuration library for evaluations and experiments. It combines Pydantic models with ordered configuration layers from nested CLI assignments, JSON, TOML, environment-backed values, and argument files.

It supports Python 3.11 and newer.

Installation

pip install lunaconf

Define a configuration

from typing import Self

from pydantic import Field

from lunaconf import LunaConf


class Config(LunaConf):
    required: int
    batch_size: int = 8
    model: str = "example/model"
    temperatures: list[float] = Field(default_factory=lambda: [0.0, 0.7])

    @classmethod
    def __lunaconf_default__(cls) -> Self:
        return cls(required=42)

LunaConf subclasses pydantic.BaseModel, so normal Pydantic validation, aliases, validators, nested models, and serialization options remain available. When aliases are defined, lunaconf uses the alias names in its mutable configuration dictionary and CLI paths.

Override __lunaconf_default__ when the model contains required fields or needs application-specific defaults.

Build from command-line layers

from lunaconf import lunaconf_cli

config = lunaconf_cli(Config)

Nested fields and list indices use dot-separated paths. Numeric components address list indices; other non-empty components address dictionary keys, including names such as model-id:

python example.py batch_size=16 temperatures.1=0.5
python example.py 'model=another/model'
python example.py 'endpoint=https://example.test?a=1&b=2'

Values are parsed as JSON when possible. Otherwise they remain strings.

Multiple assignments can be separated with semicolons. A semicolon inside a quoted JSON string remains part of the value:

python example.py 'batch_size=16;model=another/model'
python example.py 'message="first; second";batch_size=16'

Structured configuration sources

Sources are applied in command-line order, so later values override earlier values.

python example.py -J base.json -T machine.toml batch_size=32

Available sources:

  • -j JSON / -J FILE: JSON object or JSON file.
  • -t TOML / -T FILE: TOML document or TOML file.
  • -d DATA / -D FILE: detect JSON first, then TOML.
  • -C FILE: argument file containing commands and source options.
  • positional path=value: nested assignment.

The top level of JSON and TOML input must be an object/table.

List behavior

Structured configuration sources replace lists as a whole while dictionaries merge recursively:

# default values: [1, 2, 3]
config = lunaconf_cli(Config, ["-j", '{"values": [9]}'])
# values == [9]

Use a positional index assignment when only one existing list element should change:

python example.py values.1=9

Argument files

An argument file is parsed with shell-like quoting. Blank lines and comments are ignored.

# config.args
-J "base config.json"
-T machine.toml
message="hello; world # literal"
batch_size=32 # trailing comment

Apply it with:

python example.py -C config.args

Special values

Special values are case-insensitive:

  • <null> becomes None.
  • <del> deletes a dictionary field or list element.
  • <inf>, <-inf>, and <nan> become non-finite floats.
  • <env:NAME> reads an environment variable as a string.
  • <envint:NAME> reads an environment variable and converts it to int.

Missing environment variables and invalid integer conversions raise ValueError.

When serializing, unsupported JSON/TOML values are represented using the same markers. Pydantic JSON mode is used so values such as Path, dates, URLs, and enums are converted to portable values first.

Lower-level API

lunaconf_gendict applies the same ordered source logic to an existing dictionary and can extend an existing argparse.ArgumentParser:

import argparse

from lunaconf import lunaconf_gendict

parser = argparse.ArgumentParser()
parser.add_argument("--dry-run", action="store_true")

raw = {"batch_size": 8}
namespace = lunaconf_gendict(raw, parser=parser)

Printing resolved configuration

lunaconf_cli provides:

  • -p: print JSON and exit.
  • -P: print TOML and exit.
  • -a: include fields whose values equal their defaults.
  • --json-indent N: control JSON indentation.

Development

The repository uses uv, Ruff, strict Pyright, pytest with branch coverage, pre-commit, and GitHub Actions.

uv sync --locked --group dev
uv run pre-commit install
just check

The CI matrix tests Python 3.11 and 3.12. Static analysis targets Python 3.11 syntax and behavior.

Releases

Tags matching v* trigger .github/workflows/release.yml. The workflow:

  1. verifies that the tag matches project.version;
  2. runs formatting, linting, strict type checking, and tests;
  3. removes old build artifacts and runs uv build --no-sources;
  4. smoke-tests both the wheel and source distribution in isolated environments;
  5. publishes with uv publish through PyPI Trusted Publishing.

No long-lived PyPI API token is required. The PyPI project must trust:

  • owner: rijuyuezhu
  • repository: lunaconf
  • workflow: release.yml
  • GitHub environment: pypi

The matching GitHub environment must also be created under Settings → Environments → pypi. Requiring manual approval for that environment is recommended.

Metadata

Release files for lunaconf 0.6.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 lunaconf 0.6.0
File Size Uploaded Provenance
lunaconf-0.6.0.tar.gz 12.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for lunaconf 0.6.0
File Interpreter ABI Platform
lunaconf-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 22.6 kB

Release files / lunaconf-0.6.0.tar.gz

Download URL lunaconf-0.6.0.tar.gz
Size 12.5 kB
Tags Source
SHA-256 checksum
How to use checksums
420f9b6b3b41bb0ea0d9f5f2101db43c3bb926117554cf4114a08e8bef608074
BLAKE2b-256 checksum
How to use checksums
3381a0ac6f39c0e924da3b008c392b82195dd4df6952f3888a893676f032bd24
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","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 / lunaconf-0.6.0-py3-none-any.whl

Download URL lunaconf-0.6.0-py3-none-any.whl
Size 10.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c4c4fcf294f225c1c627f931267229dc70782fdecef8e1292d29657e162e3faa
BLAKE2b-256 checksum
How to use checksums
549c4073f987989a4558c77a3556cfd213a12d74357c2f8c7537e43203f631af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","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}

Security for lunaconf 0.6.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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

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