Module adcp.types.variants

Schema-variant marker for cross-class entity overrides (#710).

When an adopter subclasses an auto-generated response type and assigns a shape-compatible-but-distinct entity class to a parent field, mypy flags the override as a Liskov violation. SchemaVariant[T] marks the override as intentional — at runtime it collapses to T (Pydantic validates against the wrapped type); with :mod:adcp.types.mypy_plugin active it rewrites to Any for override-compat purposes, retiring the # type: ignore[assignment] adopters used to stamp::

class GetMediaBuyDeliveryResponse(LibraryGetMediaBuyDeliveryResponse):
    media_buy_deliveries: SchemaVariant[list[MediaBuyDeliveryData]]

Inside the override the field's mypy type is Any; cast to recover inference::

for d in cast(list[MediaBuyDeliveryData], self.media_buy_deliveries):
    d.local_method()

Don't use SchemaVariant for subclass overrides — those already type-check via Sequence[T] covariance (PR #635) and the marker would obscure that the override is sub-typing, not substitution.

Pyright / Pylance: the bundled mypy plugin doesn't affect pyright. Adopters using Pylance in VSCode will still see the LSP override flagged on SchemaVariant[T] fields even though their mypy CI passes. The runtime contract holds either way; this is purely an editor-warning asymmetry. A pyright-side suppression mechanism is tracked as a follow-up.

Classes

class SchemaVariant
Expand source code
class SchemaVariant(metaclass=_SchemaVariantMeta):
    """Marker for intentional cross-class entity overrides — see module docstring."""

Marker for intentional cross-class entity overrides — see module docstring.