Easy configs for python projects
Project description
P-Conf
Easy configuration for Python projects. Load TOML, JSON, INI, or YAML from an explicit path, from OS-specific application directories (for example ~/.config/<appname>/config.toml), or directly from a Python dict, then read values with attribute access (cfg.section.key). You can use the built-in singleton, pass Config objects around, or integrate with Pydantic via ConfigSettings.
Where config files are searched
By default, discovery checks:
~/.config/<appname>/.config.toml~/.config/<appname>/config.(toml|json|ini|yaml)<system config directory>/<appname>/.config.toml<system config directory>/<appname>/config.(toml|json|ini|yaml)
YAML requires the optional extra, for example: uv add "pi-conf[yaml]".
Quick start
Example config.toml:
foo = 1
[bar]
a = 2
Single script
from pi_conf import load_config
cfg = load_config(appname="ourappname")
print(cfg.foo) # 1
print(cfg.bar.a) # 2
Application package
Set config once (for example in __init__.py), then import cfg elsewhere:
# __init__.py
from pi_conf import cfg, set_config
set_config("ourappname")
# other_module.py
from ourappname import cfg
print(cfg.foo)
Each load_config(...) call returns a new Config. To replace the shared module-level cfg, use set_config(...).
Explicit sources (recommended for clarity)
load_config(...) supports exactly one explicit source keyword, and these are usually clearer than the legacy positional argument:
load_config(data={"debug": True})
load_config(path="/etc/myapp/config.toml")
load_config(appname="myapp")
load_config(appname="myapp", file="secrets.toml") # not `config.<ext>`
Do not mix these keywords with each other, or with a positional source, in the same call.
Other helpers
AttrDict/Config: nested dicts with attribute access;Configadds optional provenance tracking.Config.load_config(...): merge another config source into an existingConfig; conflicting top-level keys raise by default, or passoverwrite=Trueto replace them.get_nested("a.b.c"): dot-path access, with optional defaults and list indexing (see tests intests/test_nested_get.py).AttrDict.from_str(text, "toml"|"json"|"ini"|"yaml"): parse config from a string.to_env(): export nested config to environment variables (seetests/test_config.py).
Examples
The examples/ directory has runnable scripts:
examples/config_dict_example.py/examples/pydantic_settings_example.py— shareexamples/sample_config.toml(dict vs rootConfigSettingswith a nestedBaseModelfor[database]).examples/pydantic_nested_section_example.py—examples/sample_layered_config.toml: aConfigSettingssubclass whose fields map only to[worker], usingtoml_table_header(other top-level sections in the file are not passed to that model).
From the repo root (Pydantic examples need the pydantic extra):
uv run python examples/config_dict_example.py · uv run python examples/pydantic_settings_example.py · uv run python examples/pydantic_nested_section_example.py
Pydantic (ConfigSettings)
Install with your environment’s equivalent of:
uv sync --extra pydantic
# or ensure pydantic-settings and toml are available for TOML round-trips on Python 3.11+
Use config_file for an explicit path (not pydantic-settings’ toml_file, which is reserved for its built-in TOML source). Class-level model_config = ConfigDict(toml_file=...) is still accepted and is rewritten to config_file at class creation time.
Typical TOML usage is to define a subclass and point it at either an explicit file path or an app name:
from pi_conf import ConfigDict, ConfigSettings
class Settings(ConfigSettings):
host: str
port: int
model_config = ConfigDict(config_file="/etc/myapp/config.toml")
from pi_conf import ConfigDict, ConfigSettings
class Settings(ConfigSettings):
host: str
port: int
model_config = ConfigDict(appname="myapp")
You can also load a regular Pydantic model from config with ConfigSettings.from_config(...).
For nested TOML sections, set toml_table_header. For MongoDB-backed settings, use mongo_uri, mongo_database, mongo_collection, and mongo_query when pymongo is installed. See tests/test_config_settings.py and tests/test_config_settings_mongo.py.
ConfigSettings loads without importing bson unless MongoDB support is used. Updating TOML on disk uses the PyPI toml package (declared with the pydantic dependency group) because the stdlib tomllib is read-only.
Development
- Install the development environment:
uv sync --group dev --all-extras - Run tests:
make testoruv run pytest tests - CI runs on Python 3.9, 3.11, and 3.13 (see
.github/workflows/ci.yml).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pi_conf-1.0.1.tar.gz.
File metadata
- Download URL: pi_conf-1.0.1.tar.gz
- Upload date:
- Size: 59.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7abd0376dd679f55d0cdbba712b5b9d0dd6f6af268d6b04e2c4c4978ed4603d6
|
|
| MD5 |
028a2931280c7ea19a7b0132383148a0
|
|
| BLAKE2b-256 |
7fb33787a895191a056a2d85f72505a02384213307c00b122ee2c6bbc7d73d06
|
File details
Details for the file pi_conf-1.0.1-py3-none-any.whl.
File metadata
- Download URL: pi_conf-1.0.1-py3-none-any.whl
- Upload date:
- Size: 18.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40deb62723c10460c453c00ed1a0d49ec9b6a91f70116daaede704e460b80915
|
|
| MD5 |
246b9756ec22362d7dbbf0ffee8182da
|
|
| BLAKE2b-256 |
256b5ba52069ae332d5c64c983a2778fb92e4f0b07b792b0349dfc6af8d3c25b
|