Skip to main content

Typed, layered configuration for Python evaluations and experiments

Project description

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.

Project details


Download files

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

Source Distribution

lunaconf-0.6.0.tar.gz (12.5 kB view details)

Uploaded Source

Built Distribution

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

lunaconf-0.6.0-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file lunaconf-0.6.0.tar.gz.

File metadata

  • Download URL: lunaconf-0.6.0.tar.gz
  • Upload date:
  • Size: 12.5 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for lunaconf-0.6.0.tar.gz
Algorithm Hash digest
SHA256 420f9b6b3b41bb0ea0d9f5f2101db43c3bb926117554cf4114a08e8bef608074
MD5 3697fbe2be1a600b21231f3a9edbf453
BLAKE2b-256 3381a0ac6f39c0e924da3b008c392b82195dd4df6952f3888a893676f032bd24

See more details on using hashes here.

File details

Details for the file lunaconf-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: lunaconf-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for lunaconf-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c4c4fcf294f225c1c627f931267229dc70782fdecef8e1292d29657e162e3faa
MD5 bc9bb61a4cebe5df2af02e23687d2bd1
BLAKE2b-256 549c4073f987989a4558c77a3556cfd213a12d74357c2f8c7537e43203f631af

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page