summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-03-18 15:07:03 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-03-18 15:08:26 -0400
commitce2f28c37e0a2f2aa3b4a404ee190cdc00b8b918 (patch)
tree29a175c6614985f630a2434532e613d459066f68 /lib/sqlalchemy
parent3fec5028e695ad138aa46a0ae66c55e8bcb653f6 (diff)
downloadsqlalchemy-ce2f28c37e0a2f2aa3b4a404ee190cdc00b8b918.tar.gz
Adjust dataclass rules to account for field w/ default
Fixed issue in new ORM dataclasses functionality where dataclass fields on an abstract base or mixin that contained column or other mapping constructs would not be mapped if they also included a "default" key within the dataclasses.field() object. Fixes: #6093 Change-Id: I628086ceb48ab1dd0702f239cd12be74074f58f1
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/decl_base.py24
1 files changed, 17 insertions, 7 deletions
diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py
index a21af192e..0a73288fd 100644
--- a/lib/sqlalchemy/orm/decl_base.py
+++ b/lib/sqlalchemy/orm/decl_base.py
@@ -15,6 +15,7 @@ from sqlalchemy.orm import instrumentation
from . import clsregistry
from . import exc as orm_exc
from . import mapper as mapperlib
+from .attributes import InstrumentedAttribute
from .attributes import QueryableAttribute
from .base import _is_mapped_class
from .base import InspectionAttr
@@ -366,18 +367,24 @@ class _ClassScanMapperConfig(_MapperConfig):
elif ret is not absent:
return True
+ all_field = all_datacls_fields.get(key, absent)
+
ret = getattr(cls, key, obj)
if ret is obj:
return False
- elif ret is not absent:
- return True
- ret = all_datacls_fields.get(key, absent)
+ # for dataclasses, this could be the
+ # 'default' of the field. so filter more specifically
+ # for an already-mapped InstrumentedAttribute
+ if ret is not absent and isinstance(
+ ret, InstrumentedAttribute
+ ):
+ return True
- if ret is obj:
+ if all_field is obj:
return False
- elif ret is not absent:
+ elif all_field is not absent:
return True
# can't find another attribute
@@ -401,15 +408,18 @@ class _ClassScanMapperConfig(_MapperConfig):
yield name, obj
else:
+ field_names = set()
def local_attributes_for_class():
- for name, obj in vars(cls).items():
- yield name, obj
for field in util.local_dataclass_fields(cls):
if sa_dataclass_metadata_key in field.metadata:
+ field_names.add(field.name)
yield field.name, field.metadata[
sa_dataclass_metadata_key
]
+ for name, obj in vars(cls).items():
+ if name not in field_names:
+ yield name, obj
return local_attributes_for_class