Metadata-Version: 2.4
Name: pydantic-modelable-mypy
Version: 0.4.0
Summary: A mypy plugin teaching the type-checker about pydantic-modelable runtime model extensions
Author-email: David Pineau <dav.pineau@gmail.com>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://joacchim.github.io/pydantic-modelable/
Project-URL: Source, https://github.com/Joacchim/pydantic-modelable
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Framework :: Pydantic :: 2
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic-modelable
Requires-Dist: mypy>=1.11
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Dynamic: license-file

# pydantic-modelable-mypy

A [mypy](https://mypy-lang.org/) plugin that teaches the type-checker about the
model extensions `pydantic_modelable` performs at runtime.

## Why

`pydantic_modelable` lets a class decorate a *different*, pre-existing model to
add fields, union members or enum values to it. A decorator cannot re-type a
third class in the standard type system, so `mypy --strict` reports the added
fields as unknown attributes. This plugin observes those decorators and injects
the corresponding members into the target model during analysis.

## Usage

Install alongside `pydantic-modelable` and enable the plugin in your mypy
configuration:

```ini
[mypy]
plugins = pydantic_modelable_mypy.plugin
```

## What it covers

- `as_attribute` — the injected field is known for reads and construction.
- `extends_union` — the field is typed as the discriminated union of the base's
  subtypes (reads and construction), including subtypes defined in other
  modules, on full and incremental runs.
- `extends_enum` — the discriminator values injected as enum members are
  resolved by name (`Palette.red`).
- `ModelableForwarder` — decorators applied through a forwarder
  (`@Fwd.as_attribute(...)`) are resolved through the `forwards_to` chain
  (including chained forwarders) to the target `Modelable` and handled as above.

## Limitation (`extends_enum` member names)

Enum member access on an unknown name offers no plugin hook, so injected member
names can only be resolved from subtypes discovered during analysis. This is
reliable on **full (non-incremental) runs** (e.g. CI with `mypy` fresh, or
`--no-incremental`). On **incremental / daemon** runs, subtypes served from
cache are not re-analysed, so member-name access (`Palette.red`) may report an
unknown attribute until a clean run. Everything else `ModelableStrEnum` provides
— iteration, membership, construction, `.value` — works in all modes, as does
all of `as_attribute` and `extends_union`.
