diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-02-18 10:05:12 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-05-20 14:19:02 -0400 |
commit | a463b1109abb60fc85f8356f30c0351a4e2ed71e (patch) | |
tree | de8f96b7bce319fc0f19f56b302202ea3e4e91db /lib/sqlalchemy/orm/relationships.py | |
parent | 9e7bed9df601ead02fd96bf2fc787b23b536d2d6 (diff) | |
download | sqlalchemy-a463b1109abb60fc85f8356f30c0351a4e2ed71e.tar.gz |
implement dataclass_transforms
Implement a new means of creating a mapped dataclass where
instead of applying the `@dataclass` decorator distinctly,
the declarative process itself can create the dataclass.
MapperProperty and MappedColumn objects themselves take
the place of the dataclasses.Field object when constructing
the class.
The overall approach is made possible at the typing level
using pep-681 dataclass transforms [1].
This new approach should be able to completely supersede the
previous "dataclasses" approach of embedding metadata into
Field() objects, which remains a mutually exclusive declarative
setup style (mixing them introduces new issues that are not worth
solving).
[1] https://peps.python.org/pep-0681/#transform-descriptor-types-example
Fixes: #7642
Change-Id: I6ba88a87c5df38270317b4faf085904d91c8a63c
Diffstat (limited to 'lib/sqlalchemy/orm/relationships.py')
-rw-r--r-- | lib/sqlalchemy/orm/relationships.py | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py index 1186f0f54..deaf52147 100644 --- a/lib/sqlalchemy/orm/relationships.py +++ b/lib/sqlalchemy/orm/relationships.py @@ -49,6 +49,7 @@ from .base import class_mapper from .base import LoaderCallableStatus from .base import PassiveFlag from .base import state_str +from .interfaces import _AttributeOptions from .interfaces import _IntrospectsAnnotations from .interfaces import MANYTOMANY from .interfaces import MANYTOONE @@ -56,7 +57,6 @@ from .interfaces import ONETOMANY from .interfaces import PropComparator from .interfaces import RelationshipDirection from .interfaces import StrategizedProperty -from .util import _extract_mapped_subtype from .util import _orm_annotate from .util import _orm_deannotate from .util import CascadeOptions @@ -355,6 +355,7 @@ class Relationship( post_update: bool = False, cascade: str = "save-update, merge", viewonly: bool = False, + attribute_options: Optional[_AttributeOptions] = None, lazy: _LazyLoadArgumentType = "select", passive_deletes: Union[Literal["all"], bool] = False, passive_updates: bool = True, @@ -380,7 +381,7 @@ class Relationship( _local_remote_pairs: Optional[_ColumnPairs] = None, _legacy_inactive_history_style: bool = False, ): - super(Relationship, self).__init__() + super(Relationship, self).__init__(attribute_options=attribute_options) self.uselist = uselist self.argument = argument @@ -1701,18 +1702,19 @@ class Relationship( cls: Type[Any], key: str, annotation: Optional[_AnnotationScanType], + extracted_mapped_annotation: Optional[_AnnotationScanType], is_dataclass_field: bool, ) -> None: - argument = _extract_mapped_subtype( - annotation, - cls, - key, - Relationship, - self.argument is None, - is_dataclass_field, - ) - if argument is None: - return + argument = extracted_mapped_annotation + + if extracted_mapped_annotation is None: + + if self.argument is None: + self._raise_for_required(key, cls) + else: + return + + argument = extracted_mapped_annotation if hasattr(argument, "__origin__"): |