summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/decl_api.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2023-02-10 16:06:23 -0500
committermike bayer <mike_mp@zzzcomputing.com>2023-02-16 00:09:14 +0000
commit18fd19e60d55b35408d94b892e0a2051bcb7ec88 (patch)
treeaf402c777c265c841e46147ad309c17671f0e252 /lib/sqlalchemy/orm/decl_api.py
parent8855656626202e541bd2c95bc023e820a022322f (diff)
downloadsqlalchemy-18fd19e60d55b35408d94b892e0a2051bcb7ec88.tar.gz
add dataclasses callable and apply annotations more strictly
Added new parameter ``dataclasses_callable`` to both the :class:`_orm.MappedAsDataclass` class as well as the :meth:`_orm.registry.mapped_as_dataclass` method which allows an alternative callable to Python ``dataclasses.dataclass`` to be used in order to produce dataclasses. The use case here is to drop in Pydantic's dataclass function instead. Adjustments have been made to the mixin support added for :ticket:`9179` in version 2.0.1 so that the ``__annotations__`` collection of the mixin is rewritten to not include the :class:`_orm.Mapped` container, in the same way as occurs with mapped classes, so that the Pydantic dataclasses constructor is not exposed to unknown types. Fixes: #9266 Change-Id: Ia0fab6f20b93a5cb853799dcf1b70a0386837c14
Diffstat (limited to 'lib/sqlalchemy/orm/decl_api.py')
-rw-r--r--lib/sqlalchemy/orm/decl_api.py14
1 files changed, 13 insertions, 1 deletions
diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py
index d02012b86..f332d2964 100644
--- a/lib/sqlalchemy/orm/decl_api.py
+++ b/lib/sqlalchemy/orm/decl_api.py
@@ -593,6 +593,9 @@ class MappedAsDataclass(metaclass=DCTransformDeclarative):
unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG,
match_args: Union[_NoArg, bool] = _NoArg.NO_ARG,
kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG,
+ dataclass_callable: Union[
+ _NoArg, Callable[..., Type[Any]]
+ ] = _NoArg.NO_ARG,
) -> None:
apply_dc_transforms: _DataclassArguments = {
"init": init,
@@ -602,6 +605,7 @@ class MappedAsDataclass(metaclass=DCTransformDeclarative):
"unsafe_hash": unsafe_hash,
"match_args": match_args,
"kw_only": kw_only,
+ "dataclass_callable": dataclass_callable,
}
current_transforms: _DataclassArguments
@@ -623,8 +627,11 @@ class MappedAsDataclass(metaclass=DCTransformDeclarative):
super().__init_subclass__()
if not _is_mapped_class(cls):
+ new_anno = (
+ _ClassScanMapperConfig._update_annotations_for_non_mapped_class
+ )(cls)
_ClassScanMapperConfig._apply_dataclasses_to_any_class(
- current_transforms, cls
+ current_transforms, cls, new_anno
)
@@ -1569,6 +1576,7 @@ class registry:
unsafe_hash: Union[_NoArg, bool] = ...,
match_args: Union[_NoArg, bool] = ...,
kw_only: Union[_NoArg, bool] = ...,
+ dataclass_callable: Union[_NoArg, Callable[..., Type[Any]]] = ...,
) -> Callable[[Type[_O]], Type[_O]]:
...
@@ -1583,6 +1591,9 @@ class registry:
unsafe_hash: Union[_NoArg, bool] = _NoArg.NO_ARG,
match_args: Union[_NoArg, bool] = _NoArg.NO_ARG,
kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG,
+ dataclass_callable: Union[
+ _NoArg, Callable[..., Type[Any]]
+ ] = _NoArg.NO_ARG,
) -> Union[Type[_O], Callable[[Type[_O]], Type[_O]]]:
"""Class decorator that will apply the Declarative mapping process
to a given class, and additionally convert the class to be a
@@ -1608,6 +1619,7 @@ class registry:
"unsafe_hash": unsafe_hash,
"match_args": match_args,
"kw_only": kw_only,
+ "dataclass_callable": dataclass_callable,
}
_as_declarative(self, cls, cls.__dict__)
return cls