Skip to main content

PydanDict

CI PyPI Python versions License

Pydantic models with dictionary semantics.

PydanDict is a Python library whose primary base class, DictModel, is both a genuine Pydantic BaseModel and a Python mutable mapping. It is designed to let existing mapping-oriented code consume models directly, and to let package authors keep internal records valid as they change.

Status: 0.2.0 prepared for release; Phase 0.2 passed independent review. Version 0.1.0 was published to PyPI on 2026-09-13 from the immutable v0.1.0 tag. The checkout in src/pydandict contains the unreleased Phase 0.2 changes with metadata version 0.2.0; that version is not yet published. See the passed review, the Phase 0.2 evidence for current qualification results and the Phase 0.1 findings for historical evidence. The original prototype guide remains reproducible.

The plan prioritizes a dependable dependency: atomic failure behavior, protected nested values, complete public typing, tested ecosystem compatibility, measured costs, and verified distribution artifacts. Start with the roadmap, implementation work packages, and quality bar. Qualification uses automated consumer projects and maintainer checks; no external trials or participants are required.

Install the released package with python -m pip install pydandict. For a local source checkout, install the package and development tools with python -m pip install -e ".[dev]".

Migrating from 0.1.0

Version 0.2.0 intentionally narrows the alpha annotation contract:

Previous field annotation Supported 0.2.0 annotation
list[T] collections.abc.MutableSequence[T]
dict[K, V] collections.abc.MutableMapping[K, V]
set[T] collections.abc.MutableSet[T]

This applies recursively to nested and union annotations and typed-extra values. The outer __pydantic_extra__: dict[str, V] metadata declaration remains valid. Ordinary list/dict/set inputs and serialized shapes remain supported. Generic models require explicit specialization, such as Box[int] or Box[MutableSequence[int]]. See the complete migration and support envelope.

One model, two ways to work

from collections.abc import Mapping, MutableMapping

from pydantic import BaseModel, Field, ValidationError
from pydandict import DictModel


class User(DictModel):
    name: str
    age: int = Field(ge=0)


user = User(name="Eddie", age=40)
assert user.name == user["name"] == "Eddie"

user["age"] = 41
assert user.age == 41

try:
    user["age"] = -1
except ValidationError:
    assert user.age == 41  # Failed mutations leave the model unchanged.

assert isinstance(user, BaseModel)
assert isinstance(user, Mapping)
assert isinstance(user, MutableMapping)
assert list(user) == ["name", "age"]
assert dict(user) == {"name": "Eddie", "age": 41}

Attribute and mapping access address the same model state. Pydantic supplies validation, field definitions, serializers, and JSON Schema. PydanDict supplies mapping behavior and a transaction boundary around supported mutations.

For existing Python systems

An API written against Mapping[str, object] should need no PydanDict-specific branch, adapter, or model_dump() call:

from collections.abc import Mapping


def describe(record: Mapping[str, object]) -> str:
    return ", ".join(f"{key}={value}" for key, value in record.items())


description = describe(user)

The target includes [], get, containment, key iteration, live mapping views, dict(model), and keyword unpacking. It does not include isinstance(model, dict) or compatibility with APIs that insist on a concrete built-in dictionary. dict(model) is a shallow mapping copy; model_dump() is the serialization API.

For package internals

from pydantic import Field
from pydandict import DictModel


class RetryConfig(DictModel):
    timeout: float = Field(default=30.0, gt=0)
    retries: int = Field(default=3, ge=0)


config = RetryConfig()
config.update(timeout=60.0, retries=5)  # One validation transaction.
assert config.timeout == config["timeout"] == 60.0

Successful writes must satisfy the complete model contract. Failed writes must preserve values and model metadata. Required fields cannot disappear; the deletion policy protects all declared fields, with an explicit reset operation for defaults. Extras follow a documented Pydantic configuration policy.

Continuous validation is a release requirement, including nested mutations. It cannot be delivered merely by enabling validate_assignment. The design requires ownership and mutation guards for supported mutable values, validation of affected parent constraints, and rejection of values that cannot be protected. The Phase 0.2 implementation requires mutable ABC field annotations and rejects unprotectable values before commit. See mutation semantics and nested ownership.

A Pydantic model for FastAPI

The tested integration uses ordinary model annotations:

from fastapi import FastAPI

app = FastAPI()


@app.post("/users", response_model=User)
def create_user(user: User) -> User:
    user.update(age=user.age + 1)
    return user

Request parsing, response serialization, and OpenAPI use Pydantic in the pinned integration tests. See the compatibility contract.

Scope and typing

V1 centers on schema-defined DictModel records. It excludes a public TypedMap, replacement TypedDict, generalized collection framework, persistence, reactivity, and a new validation engine. Internal guards needed to protect model fields are part of validation, not separate collection products.

Pyright support is a first-class requirement: attributes retain their declared types, while generic mapping reads return object and require narrowing. Automatic per-key inference such as user["age"] -> int is not promised by the base class. See the typing strategy.

Read the plan

Document Purpose
Package source Installable DictModel implementation
Phase 0.2 implementation contract Bounded architecture, public contract, acceptance criteria and verification plan
Prototype guide Reproducible evidence commands and runnable example
Prototype findings Demonstrated solutions, evidence and remaining limitations
Documentation index Reading paths and requirement traceability
Product and scope Audiences, use cases, success criteria
Architecture BaseModel integration and transactional state
API specification Mapping surface, names, return values, errors
Mutation semantics Invariants, atomicity, deletion, defaults, extras
Nested values Ownership, escaped references, parent validation
Typing Pyright, protocols, limitations, typing checks
Compatibility Pydantic, serialization, schema, FastAPI
Interoperability What existing consumers can and cannot assume
Competition Alternatives and focused positioning
Testing Acceptance cases and release gates
Roadmap Sequenced implementation and release policy
Implementation work packages Priorities, dependencies, first increments and stop criteria
Quality bar Measurable gates, automated consumer journeys and maintenance standards
Release automation Tag-gated checks, artifact build, and PyPI Trusted Publishing
Security and performance Trust boundary, costs, benchmarks
Decision log Established requirements and proposed choices
Upstream evidence Sources and reproducible baseline observations

Contributing

Start with CONTRIBUTING.md. Design contributions should identify the invariant they preserve and the acceptance test that will prove it. The next step for 0.2.0 is the tag-gated release process.

The package is distributed under the MIT license. Use the private GitHub channel described in security reporting and the changelog.

Metadata

Release files for pydandict 0.2.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 pydandict 0.2.0
File Size Uploaded
pydandict-0.2.0.tar.gz 45.8 kB Details

Built distribution (wheel)

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

Total release size: 71.2 kB

Release files / pydandict-0.2.0.tar.gz

Download URL pydandict-0.2.0.tar.gz
Size 45.8 kB
Tags Source
SHA-256 checksum
How to use checksums
cbb3402c5e95444a73a0768d4fca856f54f4adc8877ed3b0727d17b806da81c3
BLAKE2b-256 checksum
How to use checksums
ebe29ae31dd9e8e3dc69f415ed10f6fd286a0ad682bd7e0276d52515418f9f0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 14, 2026.

Transparency log

Release files / pydandict-0.2.0-py3-none-any.whl

Download URL pydandict-0.2.0-py3-none-any.whl
Size 25.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c5cad6a392d0430f01f43264828e230a85e702007cde5ff1fb7c7e6381435646
BLAKE2b-256 checksum
How to use checksums
e4473bbde48eecd391a6d07e536ff606c3ba431a4a7b6aaac64123d00f43b4ae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

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