Skip to main content

pydantic-parsed-env

Parse common collection settings from simple env strings instead of JSON.

If you want ALLOWED_HOSTS=api.local,worker.local (not ALLOWED_HOSTS=["api.local","worker.local"]), this package is for you.

Quickstart

pip install pydantic-parsed-env

Requires Python 3.12+.

Runtime dependency policy:

  • Published runtime dependencies use tested compatibility ranges, not exact pins.
  • Supported runtime dependency ranges are declared in the package metadata.
  • Exact versions for development are managed separately in the lockfile/tooling.
from typing import Annotated

from pydantic import Field
from pydantic_settings import SettingsConfigDict

from pydantic_parsed_env import ParseOptions, Parsed, ParsedEnvSettings


class Settings(ParsedEnvSettings):
    model_config = SettingsConfigDict(env_prefix="APP_")

    hosts: Parsed[list[str]] = Field(default_factory=list[str])
    ports: Annotated[
        dict[str, int],
        ParseOptions(kv_delimiter="="),
    ] = Field(default_factory=dict[str, int])


# export APP_HOSTS="api.local, worker.local"
# export APP_PORTS="http=80,https=443"

settings = Settings()

assert settings.hosts == ["api.local", "worker.local"]
assert settings.ports == {"http": 80, "https": 443}

In the simple case, you can use Parsed[dict[str, int]] and the default kv_delimiter=":". The example uses ParseOptions(kv_delimiter="=") only to show delimiter override.

When to use this

Use this package when you want readable delimiter-based env values for collections.

Use plain pydantic-settings JSON parsing when you need nested objects, nullable collection items, or other complex shapes.

Why

pydantic-settings is excellent, but structured env values commonly use JSON. That can be verbose and brittle in shell scripts, Docker env files, and ops tooling.

pydantic-parsed-env keeps common collection config short and readable:

  • APP_HOSTS=api.local,worker.local
  • APP_FEATURE_FLAGS=true,false,true
  • APP_PORTS=http:80,https:443

Core API

  • ParsedEnvSettings: BaseSettings subclass that wires in the custom env source.
  • Parsed[T]: shorthand for Annotated[T, ParseOptions()].
  • ParseOptions(...): annotation metadata factory for delimiter-based parsing.

ParseOptions(...) metadata alone is not enough. The custom parser is installed via settings_customise_sources, so your settings class must inherit from ParsedEnvSettings.

Supported parsing

ParseOptions(...) applies to:

  • list[T]
  • set[T]
  • tuple[T, ...] and fixed tuples like tuple[str, int]
  • dict[K, V] (uses default kv_delimiter set to :)

Supported element conversion:

  • str, int, float, bool (true / false)
  • Enum / StrEnum
  • Literal[...]

Fields without ParseOptions(...) keep normal pydantic-settings behavior, including JSON parsing for complex values.

Behavior matrix

Field type Example input Parsed result
list[int] "1,2,3" [1, 2, 3]
set[str] "a,a,b" {"a", "b"}
tuple[float, ...] "1.2,3.4" (1.2, 3.4)
tuple[str, int] "host,80" ("host", 80)
dict[str, int] + kv_delimiter=":" "http:80,https:443" {"http": 80, "https": 443}

Empty and malformed input semantics

  • For collection fields, unset and "" map to empty collections:

    • list[T] -> []
    • set[T] -> set()
    • tuple[T, ...] -> ()
    • dict[K, V] -> {}
  • For required fields without defaults, unset values still follow normal pydantic-settings required-field behavior.

  • None is not inferred from empty input by default. If you need nullable collection values, use an explicit sentinel convention.

  • Parsing is strict for malformed segments:

    • "a,,b" is invalid for list[int] and similar non-string item types.
    • "k1:v1,broken,k2:v2" is invalid for dict[K, V].
  • Empty segments are allowed for str items:

    • list[str]: "a,,b" -> ["a", "", "b"]

Dict parsing rules

  • Dict fields require a key-value delimiter, for example ParseOptions(kv_delimiter=":").
  • Each pair must match key<kv_delimiter>value, for example "k:v".
  • Whitespace around keys and values is trimmed before conversion.
  • Duplicate keys use the last value encountered:
    • "a:1,a:2" -> {"a": 2}

Error behavior

At the settings integration layer, parsing errors are raised as pydantic_settings.SettingsError (matching upstream source behavior).

Detailed parser failure context is preserved in SettingsError.__cause__.

Non-goals and limits

  • Complex nested model elements (for example list[MyModel]) are not supported by simple string parsing.
  • Nullable item types inside collections (for example list[int | None] or dict[str, bool | None]) are intentionally out of scope for simple parsing. Use standard JSON-based pydantic-settings parsing for those shapes.
  • Complex item-level unions (including nullable item unions) are not supported for simple parsing.
  • Applying ParseOptions(...) to non-collection fields is a type error.

Development

Default (no Nix required):

uv sync
uv run ruff check .
uv run ruff format .
uv run pyright .
uv run pytest -q

If you use Nix, a dev shell plus formatting/check wiring is already provided:

nix develop
nix fmt
nix flake check

CI runs the same Nix commands (nix fmt and nix flake check) using Determinate Nix + Magic Nix Cache.

Versioning and releases

  • Package versions are derived from Git tags via hatch-vcs.
  • Release tags must use the vX.Y.Z form, for example v0.3.1.
  • The published package version strips the v prefix, so v0.3.1 becomes 0.3.1 on PyPI.
  • This project follows semantic versioning for its public API. While the package is still 0.x, breaking changes may still land in minor releases.

License

Apache-2.0.

Release files for pydantic-parsed-env 0.1.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 pydantic-parsed-env 0.1.0
File Size Uploaded
pydantic_parsed_env-0.1.0.tar.gz 45.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pydantic-parsed-env 0.1.0
File Interpreter ABI Platform
pydantic_parsed_env-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 59.3 kB

Release files / pydantic_parsed_env-0.1.0.tar.gz

Download URL pydantic_parsed_env-0.1.0.tar.gz
Size 45.2 kB
Tags Source
SHA-256 checksum
How to use checksums
1eba464e1a1edeaa39e228a16d0d24de9583d908b0dfd9350b962244ff69671b
BLAKE2b-256 checksum
How to use checksums
6f4c777a842b0aed69f767ec3605e86448ecb4d551f7ca23928f14ee99ef011c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 10, 2026.

Transparency log

Release files / pydantic_parsed_env-0.1.0-py3-none-any.whl

Download URL pydantic_parsed_env-0.1.0-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4148bdd2890d4bec6b4077e529eda07c812b08eeb54c536f5421fad3f74be829
BLAKE2b-256 checksum
How to use checksums
9db54aac8bac72cc02c1f6e1e7eca95903691df70bf106828817e88c07398c00
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release 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