summaryrefslogtreecommitdiff
path: root/test/ext
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2017-10-28 13:28:58 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2017-10-28 13:29:48 -0400
commitfd4289c5829d6498495ac59fe1dccb23b4975281 (patch)
tree23881bd839a6ca99d62748ef910fc1c343c5284c /test/ext
parentf7b957b589207cae98b6feec63be84ee6423c3ca (diff)
downloadsqlalchemy-fd4289c5829d6498495ac59fe1dccb23b4975281.tar.gz
Filter attributes we don't map during a load_scalar_attributes
Fixed bug where a descriptor that is elsewhere a mapped column or relationship within a hierarchy based on :class:`.AbstractConcreteBase` would be referred towards during a refresh operation, causing an error as the attribute is not mapped as a mapper property. A similar issue can arise for other attributes like the "type" column added by :class:`.AbstractConcreteBase` if the class fails to include "concrete=True" in its mapper, however the check here should also prevent that scenario from causing a problem. Change-Id: I407b07a3a3e2c374da19fc86ed44b987d595dcfa Fixes: #4124
Diffstat (limited to 'test/ext')
-rw-r--r--test/ext/declarative/test_inheritance.py53
1 files changed, 53 insertions, 0 deletions
diff --git a/test/ext/declarative/test_inheritance.py b/test/ext/declarative/test_inheritance.py
index e57320cfe..7ced8ec15 100644
--- a/test/ext/declarative/test_inheritance.py
+++ b/test/ext/declarative/test_inheritance.py
@@ -1092,6 +1092,10 @@ class ConcreteInhTest(_RemoveListeners, DeclarativeTestBase):
eq_(sess.query(Manager).all(), [Manager(name='dogbert')])
eq_(sess.query(Boss).all(), [Boss(name='pointy haired')])
+ e1 = sess.query(Engineer).order_by(Engineer.name).first()
+ sess.expire(e1)
+ eq_(e1.name, 'dilbert')
+
def test_explicit(self):
engineers = Table(
'engineers', Base.metadata,
@@ -1213,6 +1217,55 @@ class ConcreteInhTest(_RemoveListeners, DeclarativeTestBase):
self._roundtrip(Employee, Manager, Engineer, Boss)
+ def test_abstract_concrete_extension_descriptor_refresh(self):
+ class Employee(AbstractConcreteBase, Base, fixtures.ComparableEntity):
+ @declared_attr
+ def name(cls):
+ return Column(String(50))
+
+ class Manager(Employee):
+ __tablename__ = 'manager'
+ employee_id = Column(Integer, primary_key=True,
+ test_needs_autoincrement=True)
+ paperwork = Column(String(10))
+ __mapper_args__ = {
+ 'polymorphic_identity': 'manager', 'concrete': True}
+
+ class Engineer(Employee):
+ __tablename__ = 'engineer'
+ employee_id = Column(Integer, primary_key=True,
+ test_needs_autoincrement=True)
+
+ @property
+ def paperwork(self):
+ return "p"
+
+ __mapper_args__ = {
+ 'polymorphic_identity': 'engineer', 'concrete': True}
+
+ Base.metadata.create_all()
+ sess = Session()
+ sess.add(Engineer(name='d'))
+ sess.commit()
+
+ # paperwork is excluded because there's a descritor; so it is
+ # not in the Engineers mapped properties at all, though is inside the
+ # class manager. Maybe it shouldn't be in the class manager either.
+ assert 'paperwork' in Engineer.__mapper__.class_manager
+ assert 'paperwork' not in Engineer.__mapper__.attrs.keys()
+
+ # type currently does get mapped, as a
+ # ConcreteInheritedProperty, which means, "ignore this thing inherited
+ # from the concrete base". if we didn't specify concrete=True, then
+ # this one gets stuck in the error condition also.
+ assert 'type' in Engineer.__mapper__.class_manager
+ assert 'type' in Engineer.__mapper__.attrs.keys()
+
+ e1 = sess.query(Engineer).first()
+ eq_(e1.name, 'd')
+ sess.expire(e1)
+ eq_(e1.name, 'd')
+
def test_concrete_extension(self):
class Employee(ConcreteBase, Base, fixtures.ComparableEntity):
__tablename__ = 'employee'