Skip to main content

from notifig import CommaSeparatedfrom dataclasses import Field

Notifig

A highly declarative, strictly typed, reactive config

Notifig is a configuration library built on Pydantic, and strongly rooted on these principles:

Declaration is behavior - The shape of a config field derives its usage.

Validation, serialization, value choices, CLI flags, all follow from writing the field itself. For example, this statement creates a colors field that only accepts certain values and can be set both with comma-separated values (--color "blue,red"") or explicit lists:

# Color type with restricted values
ColorType = Choice(["red", "green", "blue"]) 
# List that can parse/serialize comma-delimited color names
ColorList = CommaSeparated[ColorType]

# List of colors with CLI flags
colors: Annotated[
    ColorList,
    CliFlags(["color", "c"]), # creates --color/-c CLI flags
] = Field(
    default="green",          # default value
    description="...",        # info string for --help and CLI errors
)

# Usage
#   YAML: `colors: green,blue`
#   CLI:  `--colors "blue,red"`
Single source of truth - Settings should be declared once, in a single mutable single register.

A common example is mapping CLI flags to their config value, which usually involves maintaining a parallel dict that references fields by string name and needs to be manually kept in sync with the config itself:

class BadSettings:
    foo: str
    bar: str | None = None
    baz: int  # We added baz, but forgot to add its CLI flag below

# If any field gets renamed or deleted, someone has to remember to change it here.
CLI_FLAGS = {
    "foo": "foo",
    "f": "foo",
    "bar": "bar"
}

# Requires merging the CLI data into config fields 
for flag, value in cli_data.items():
    if (field := CLI_FLAGS[flag]):
        setattr(config, field, value)

With Notifig, the CLI flags live on their respective field declarations. Deleting or altering a field and all its flags only touches one statement, in a single place.

class Settings(Config):
    foo: Annotated[str, CliFlags("foo", "f")] = Field(description="Value of Foo")
    bar: Annotated[str|None, CliFlags("bar")] = Field(
        description="Name of Bar, if any",
        default=None,
    )
    baz: int = Field(description="Amount of Baz")
Distributed awareness - Each part of an application only interacts with its own config section.

An application's structure hierarchy should map to its config structure. Each component declares its own config section with the fields it needs, and does not need to be

Reactive state - Changes in the config should inform anyone interested.

Adding, changing or deleting an entry should able to trigger behavior instead of relying on periodic checks. An observer is a callable or coroutine registered to a path, and it's called whenever it is altered. A simple example where changing a UI's theme causes it to redraw:

class UIConfig(ConfigSection):
    theme: Annotated[Choices(["dark", "light"])] = Field(default="light")

class Settings(Config):
    ui: UIConfig

config = Settings()

# sync observer that logs every change
@config.on_change()
def print_changes(section: ConfigSection, changes: tuple[Change]):
    for change in changes:
        print(f"Change of type {change.__class__.__name__} on {change.path}")

# async observer
@config.on_change("ui.theme")
async def redraw_theme(section: ConfigSection, changes: tuple[Change]):
    await interface.update_theme(section.ui.theme)

Install

pip install notifig

Requires Python ≥ 3.13.

Features

  • Custom annotations - Notifig introduces several custom Pydantic annotations to express behavior from types:
    • CliFlags - adds a shortcut CLI flag for a field
    • Choice - restricts the values a field can take according to a list of options
    • CommaSeparated - allows parsing a list delimited by ,
    • Link - links one field to another through its full path
  • Observers -
  • Static and Dynamic sections
  • Obvious usage - bar = section.foo, section["foo"] = "baz", section.get("foo.bar"), for name, field in section
  • File formats: supports parsing and serializing config files using JSON, YAML and TOML. # TODO: add INI and env.

Built on

Metadata

Release files for notifig 0.1.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 notifig 0.1.1
File Size Uploaded Provenance
notifig-0.1.1.tar.gz 72.0 kB With provenance Details

Built distribution (wheel)

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

Total release size: 126.5 kB

Release files / notifig-0.1.1.tar.gz

Download URL notifig-0.1.1.tar.gz
Size 72.0 kB
Tags Source
SHA-256 checksum
How to use checksums
1b1a89061a9d542441f258faf0f952aca6450a1cf210b3358471a77045114470
BLAKE2b-256 checksum
How to use checksums
57965d34f9c1ee25776f2f533849ece8dbbda1d9fff68d1b1af2796c898eb56c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 22, 2026.

Transparency log

Release files / notifig-0.1.1-py3-none-any.whl

Download URL notifig-0.1.1-py3-none-any.whl
Size 54.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5e8d411008e743a35ed9b1cf021637f041a574e891bfde2235be899a27c7c918
BLAKE2b-256 checksum
How to use checksums
ad52ee8ce99ca9c70653a31181267de033c364092d570d2d7d46a8f3ac1f1f69
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 22, 2026.

Transparency log

Security for notifig 0.1.1

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for notifig-0.1.1.tar.gz

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 Oct 22, 2026.

Transparency log

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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