summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/decl_base.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-07-15 12:25:22 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2022-07-15 12:37:06 -0400
commit0aa56cd729407dff1d96c61432b6f3a2a7124d39 (patch)
tree4cda2e1335d2a942632428cb93810a05d4606f1c /lib/sqlalchemy/orm/decl_base.py
parenta0597341195ba7445ef1e9c69092e3bd29427aec (diff)
downloadsqlalchemy-0aa56cd729407dff1d96c61432b6f3a2a7124d39.tar.gz
make anno-only Mapped[] column available for mixins
Documentation is relying on the recently improved behavior of produce_column_copies() to make sure everything is available on cls for a declared_attr. therefore for anno-only attribute, we also need to generate the mapped_column() up front before scan is called. noticed in pylance, allow @declared_attr to recognize @classmethod also which allows letting typing tools know something is explicitly a classmethod Change-Id: I07ff1a642a75679f685914a33c674807929f4918
Diffstat (limited to 'lib/sqlalchemy/orm/decl_base.py')
-rw-r--r--lib/sqlalchemy/orm/decl_base.py48
1 files changed, 26 insertions, 22 deletions
diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py
index 62251fa2b..108027dd5 100644
--- a/lib/sqlalchemy/orm/decl_base.py
+++ b/lib/sqlalchemy/orm/decl_base.py
@@ -737,6 +737,7 @@ class _ClassScanMapperConfig(_MapperConfig):
locally_collected_columns = self._produce_column_copies(
local_attributes_for_class,
attribute_is_overridden,
+ fixed_table,
)
else:
locally_collected_columns = {}
@@ -828,9 +829,7 @@ class _ClassScanMapperConfig(_MapperConfig):
# acting like that for now.
if isinstance(obj, (Column, MappedColumn)):
- self._collect_annotation(
- name, annotation, is_dataclass_field, True, obj
- )
+ self._collect_annotation(name, annotation, True, obj)
# already copied columns to the mapped class.
continue
elif isinstance(obj, MapperProperty):
@@ -913,23 +912,18 @@ class _ClassScanMapperConfig(_MapperConfig):
self._collect_annotation(
name,
obj._collect_return_annotation(),
- False,
True,
obj,
)
elif _is_mapped_annotation(annotation, cls):
- generated_obj = self._collect_annotation(
- name, annotation, is_dataclass_field, True, obj
- )
- if obj is None:
- if not fixed_table:
- collected_attributes[name] = (
- generated_obj
- if generated_obj is not None
- else MappedColumn()
- )
- else:
- collected_attributes[name] = obj
+ # Mapped annotation without any object.
+ # product_column_copies should have handled this.
+ # if future support for other MapperProperty,
+ # then test if this name is already handled and
+ # otherwise proceed to generate.
+ if not fixed_table:
+ assert name in collected_attributes
+ continue
else:
# here, the attribute is some other kind of
# property that we assume is not part of the
@@ -953,12 +947,10 @@ class _ClassScanMapperConfig(_MapperConfig):
obj = obj.fget()
collected_attributes[name] = obj
- self._collect_annotation(
- name, annotation, True, False, obj
- )
+ self._collect_annotation(name, annotation, False, obj)
else:
generated_obj = self._collect_annotation(
- name, annotation, False, None, obj
+ name, annotation, None, obj
)
if (
obj is None
@@ -1060,7 +1052,6 @@ class _ClassScanMapperConfig(_MapperConfig):
self,
name: str,
raw_annotation: _AnnotationScanType,
- is_dataclass: bool,
expect_mapped: Optional[bool],
attr_value: Any,
) -> Any:
@@ -1128,6 +1119,7 @@ class _ClassScanMapperConfig(_MapperConfig):
[], Iterable[Tuple[str, Any, Any, bool]]
],
attribute_is_overridden: Callable[[str, Any], bool],
+ fixed_table: bool,
) -> Dict[str, Union[Column[Any], MappedColumn[Any]]]:
cls = self.cls
dict_ = self.clsdict_view
@@ -1136,7 +1128,19 @@ class _ClassScanMapperConfig(_MapperConfig):
# copy mixin columns to the mapped class
for name, obj, annotation, is_dataclass in attributes_for_class():
- if isinstance(obj, (Column, MappedColumn)):
+ if (
+ not fixed_table
+ and obj is None
+ and _is_mapped_annotation(annotation, cls)
+ ):
+ obj = self._collect_annotation(name, annotation, True, obj)
+ if obj is None:
+ obj = MappedColumn()
+
+ locally_collected_attributes[name] = obj
+ setattr(cls, name, obj)
+
+ elif isinstance(obj, (Column, MappedColumn)):
if attribute_is_overridden(name, obj):
# if column has been overridden
# (like by the InstrumentedAttribute of the