summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-04-21 10:39:09 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-04-21 10:42:21 -0400
commited3f2c617239668d74ad3d86aeda0ca2030a5933 (patch)
tree2c1d1881c6b2d0d9c74d41362960e575ec0c404a /lib/sqlalchemy
parent368086e9fc49c7a1ca972480e0134d8e7a9f0544 (diff)
downloadsqlalchemy-ed3f2c617239668d74ad3d86aeda0ca2030a5933.tar.gz
Limit dc field logic to only fields that are definitely dc
Fixed regression where recent changes to support Python dataclasses had the inadvertent effect that an ORM mapped class could not successfully override the ``__new__()`` method. In this case the "__new__" method comes out as staticmethod in cls.__dict__ vs. a function in the metaclass dict_, so comparing using identity fails. I was hoping not to have too much "dataclass" hardcoded, the logic here if it were generalized to other attribute declaration systems there would still have a flag that indicates an attribute is part of the "special declaration system". Fixes: #6331 Change-Id: Ia28a44fb57c668fa2fc5cd1ff38fd511f2c747e6
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/decl_base.py16
1 files changed, 9 insertions, 7 deletions
diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py
index 5a5d98a95..b3444f26f 100644
--- a/lib/sqlalchemy/orm/decl_base.py
+++ b/lib/sqlalchemy/orm/decl_base.py
@@ -410,7 +410,7 @@ class _ClassScanMapperConfig(_MapperConfig):
def local_attributes_for_class():
for name, obj in vars(cls).items():
- yield name, obj
+ yield name, obj, False
else:
field_names = set()
@@ -421,10 +421,10 @@ class _ClassScanMapperConfig(_MapperConfig):
field_names.add(field.name)
yield field.name, _as_dc_declaredattr(
field.metadata, sa_dataclass_metadata_key
- )
+ ), True
for name, obj in vars(cls).items():
if name not in field_names:
- yield name, obj
+ yield name, obj, False
return local_attributes_for_class
@@ -455,7 +455,7 @@ class _ClassScanMapperConfig(_MapperConfig):
local_attributes_for_class, attribute_is_overridden
)
- for name, obj in local_attributes_for_class():
+ for name, obj, is_dataclass in local_attributes_for_class():
if name == "__mapper_args__":
check_decl = _check_declared_props_nocascade(
obj, name, cls
@@ -567,15 +567,17 @@ class _ClassScanMapperConfig(_MapperConfig):
# however, check for some more common mistakes
else:
self._warn_for_decl_attributes(base, name, obj)
- elif name not in dict_ or dict_[name] is not obj:
+ elif is_dataclass and (
+ name not in dict_ or dict_[name] is not obj
+ ):
# here, we are definitely looking at the target class
# and not a superclass. this is currently a
# dataclass-only path. if the name is only
# a dataclass field and isn't in local cls.__dict__,
# put the object there.
-
# assert that the dataclass-enabled resolver agrees
# with what we are seeing
+
assert not attribute_is_overridden(name, obj)
if _is_declarative_props(obj):
@@ -607,7 +609,7 @@ class _ClassScanMapperConfig(_MapperConfig):
column_copies = self.column_copies
# copy mixin columns to the mapped class
- for name, obj in attributes_for_class():
+ for name, obj, is_dataclass in attributes_for_class():
if isinstance(obj, Column):
if attribute_is_overridden(name, obj):
# if column has been overridden