[Sqlalchemy-tickets] Issue #4188: mapper places ConcreteInheritedProperty on top of a hybrid (zzzee
Brought to you by:
zzzeek
From: Michael B. <iss...@bi...> - 2018-02-15 23:06:11
|
New issue 4188: mapper places ConcreteInheritedProperty on top of a hybrid https://bitbucket.org/zzzeek/sqlalchemy/issues/4188/mapper-places-concreteinheritedproperty-on Michael Bayer: ``` #!python from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import AbstractConcreteBase from sqlalchemy.ext.hybrid import hybrid_property Base = declarative_base() class AbstractBase(AbstractConcreteBase, Base): @declared_attr def column1(cls): return Column(Integer) @declared_attr def column2(cls): return Column(Integer) class Concrete1(AbstractBase): __tablename__ = "concrete1" id = Column(Integer, primary_key=True) attribute1 = Column(Integer) __mapper_args__ = { 'polymorphic_identity': 'concrete1', 'concrete': True } class Concrete2(AbstractBase): __tablename__ = "concrete2" id = Column(Integer, primary_key=True) attribute2 = Column(Integer) @hybrid_property def attribute1(self): return self.attribute2 @attribute1.expression def attribute1(cls): return cls.attribute2 __mapper_args__ = { 'polymorphic_identity': 'concrete2', 'concrete': True } print(Concrete2.attribute1.__clause_element__()) c2 = Concrete2(attribute2=5) c2.attribute1 ``` produces: ``` #! concrete2.attribute2 Traceback (most recent call last): File "test.py", line 55, in <module> c2.attribute1 File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/attributes.py", line 298, in __get__ return self.descriptor.__get__(instance, owner) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/descriptor_props.py", line 512, in __get__ warn() File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/descriptor_props.py", line 500, in warn (self.parent, self.key, self.parent)) AttributeError: Concrete Mapper|Concrete2|concrete2 does not implement attribute 'attribute1' at the instance level. Add this property explicitly to Mapper|Concrete2|concrete2. ``` suggestion: ``` #!diff diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index cd9e00b8b..31100d9c8 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1612,7 +1612,7 @@ class Mapper(InspectionAttr): def _adapt_inherited_property(self, key, prop, init): if not self.concrete: self._configure_property(key, prop, init=False, setparent=False) - elif key not in self._props: + elif not isinstance(getattr(self.class_, key, None), InspectionAttr): self._configure_property( key, properties.ConcreteInheritedProperty(), ``` |