class JsonPatchFor(_RegistryBoundPatchRoot, Generic[TargetT, RegistryT]):
"""
Factory for creating typed JSON Patch models bound to a registry declaration.
`JsonPatchFor[Target]` produces a patch model using `StandardRegistry`.
`JsonPatchFor[Target, Registry]` produces a patch model using an explicit
registry. `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.
Arguments:
target: The target BaseModel instance.
Returns:
The patched BaseModel instance.
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.
Arguments:
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.
Returns:
The patched JSON document.
Raises:
PatchValidationError: If the input is not a valid `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.
Returns:
The patched model or JSON document, depending on specialization.
Raises:
TypeError: Model variant expects a Pydantic BaseModel instance.
PatchValidationError: If the input is not a valid `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):
params = (params, StandardRegistry)
if len(params) != 2:
raise TypeError(
"JsonPatchFor expects JsonPatchFor[Target] or 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