class JsonPatchFor(_RegistryBoundPatchRoot, Generic[TargetT, RegistryT]):
"""
Factory for creating typed JSON Patch models bound to a registry declaration.
``JsonPatchFor[Target, Registry]`` produces a patch model.
``Target`` is either a Pydantic model or ``Literal["SchemaName"]`` for JSON documents.
``Registry`` is a union of concrete OperationSchemas (``OpA | OpB | ...``).
"""
if TYPE_CHECKING:
# At runtime, JsonPatchFor[X] returns either a _BasePatchBody or a BasePatchModel, each with their own apply().
# Tell type checkers that JsonPatchFor[X] has an apply() to expose this.
@overload
def apply[TargetModelM: BaseModel](
self: JsonPatchFor[TargetModelM, RegistryT], target: TargetModelM
) -> TargetModelM:
"""
Apply this patch to ``target`` and return the patched Model.
Args:
target: The target BaseModel.
Returns:
patched: The patched BaseModel.
Raises:
PatchValidationError: Patched data fails validation for the target model.
PatchError: Any patch-domain error raised by operations, including conflicts.
``PatchInternalError`` is a ``PatchError`` raised for unexpected failures.
"""
pass
@overload
def apply[TargetNameN: str](
self: JsonPatchFor[TargetNameN, RegistryT],
doc: JSONValue,
*,
inplace: bool = False,
) -> JSONValue:
"""
Apply this patch to ``doc`` and return the patched document.
Args:
doc: The target JSON document.
inplace: Copy policy. ``False`` deep-copies ``doc`` first; ``True``
applies operations against ``doc`` without that copy. This does
not guarantee returned root object identity.
Return:
patched: The patched JSON document.
Raises:
ValidationError: If the input is not a mutable ``JSONValue``.
PatchError: Any patch-domain error raised by operations, including conflicts.
``PatchInternalError`` is a ``PatchError`` raised for unexpected failures.
"""
pass
def apply(self, *args: Any, **kwargs: Any) -> Any:
"""
Apply a JSON Patch document.
Raises:
TypeError: Model variant expects a Pydantic BaseModel instance.
ValidationError: If the input is not a mutable ``JSONValue``.
PatchValidationError: Patched data fails validation for the target model.
PatchError: Any patch-domain error raised by operations, including conflicts.
``PatchInternalError`` is a ``PatchError`` raised for unexpected failures.
"""
pass
@override
def __class_getitem__(cls, params: object) -> type[_RegistryBoundPatchRoot]:
if not isinstance(params, tuple) or len(params) != 2:
raise TypeError(
"JsonPatchFor expects JsonPatchFor[Target, Registry] where "
'Target is a BaseModel subclass or Literal["SchemaName"] and '
"Registry is a union of concrete OperationSchemas. "
f"Got: {params!r}."
)
target, registry = params
registry = _RegistrySpec.from_typeform(registry)
schema_name = _coerce_schema_name(target)
if schema_name is not None:
return cls._create_json_patch_body(schema_name, registry)
if not isclass(target) or not issubclass(target, BaseModel):
raise TypeError(
'JsonPatchFor[...] expects a Pydantic BaseModel subclass or Literal["SchemaName"], '
f"got {target!r}"
)
return cls._create_model_patch_body(target, registry)
@staticmethod
def _create_json_patch_body(
schema_name: str,
registry: _RegistrySpec,
) -> type[_BasePatchBody]:
BodyPatchOperation = TypeAliasType( # type: ignore[misc]
f"{schema_name}PatchOperation",
Annotated[
registry.union_type,
Field(
title=f"{schema_name} Patch Operation",
description=(
f"Discriminated union of patch operations for {schema_name}."
),
),
],
) # NOTE: can't use type keyword because otherwise OpenAPI title binds to "BodyPatchOperation" instead
PatchBody = create_model(
f"{schema_name}PatchRequest",
__base__=_BasePatchBody,
__config__=ConfigDict(
title=f"{schema_name} Patch Request",
json_schema_extra={
"description": f"Array of patch operations for {schema_name}.",
},
),
root=(list[BodyPatchOperation], ...), # type: ignore[valid-type]
)
PatchBody.__registry__ = registry
PatchBody.__doc__ = (
f"Discriminated union of patch operations for {schema_name}."
)
return PatchBody
@staticmethod
def _create_model_patch_body(
model: type[ModelT],
registry: _RegistrySpec,
) -> type[_BasePatchModel[ModelT]]:
ModelPatchOperation = TypeAliasType( # type: ignore[misc]
f"{model.__name__}PatchOperation",
Annotated[
registry.union_type,
Field(
title=f"{model.__name__} Patch Operation",
description=f"Discriminated union of patch operations for {model.__name__}.",
),
],
) # NOTE: can't use type keyword because otherwise OpenAPI title binds to "ModelPatchOperation" instead
PatchModel = create_model(
f"{model.__name__}PatchRequest",
__base__=_BasePatchModel,
__config__=ConfigDict(
title=f"{model.__name__} Patch Request",
json_schema_extra={
"description": (
f"Array of patch operations for {model.__name__}. "
"Applied to model_dump() and re-validated against the model schema."
),
"x-target-model": model.__name__,
},
),
root=(list[ModelPatchOperation], ...), # type: ignore[valid-type]
)
PatchModel.__target_model__ = model
PatchModel.__registry__ = registry
PatchModel.__doc__ = f"Array of patch operations for {model.__name__}."
return PatchModel