[Sqlalchemy-tickets] Issue #4185: AssociationProxy is not properly initialized when created by a de
Brought to you by:
zzzeek
From: Eric A. (Omni) <iss...@bi...> - 2018-02-09 19:11:30
|
New issue 4185: AssociationProxy is not properly initialized when created by a declared_attr of a mixin class https://bitbucket.org/zzzeek/sqlalchemy/issues/4185/associationproxy-is-not-properly Eric Atkin (Omni): After upgrading from 1.1.14 to 1.2.2, my models broke. A simplified representation is included below that demonstrates the issue. If the Parent.children association proxy is not accessed before any subclasses are defined, it's owning_class attribute will be None. This caused the following traceback, but I'm sure it would be the root cause of many more issues throughout the library: ``` Traceback (most recent call last): File "{...}/.venv/lib/python3.6/site-packages/pyramid_mako/__init__.py", line 148, in __call__ result = template.render_unicode(**system) File "{...}/.venv/lib/python3.6/site-packages/mako/template.py", line 471, in render_unicode as_unicode=True) File "{...}/.venv/lib/python3.6/site-packages/mako/runtime.py", line 838, in _render **_kwargs_for_callable(callable_, data)) File "{...}/.venv/lib/python3.6/site-packages/mako/runtime.py", line 873, in _render_context _exec_template(inherit, lclcontext, args=args, kwargs=kwargs) File "{...}/.venv/lib/python3.6/site-packages/mako/runtime.py", line 899, in _exec_template callable_(context, *args, **kwargs) File "{...}/dispatch/templates/base/base.mako", line 297, in render_body <%block name="content"> File "{...}/dispatch/templates/base/detail_carriage.mako", line 710, in render_content % if editable or _context.child_invoice_meta: File "{...}/sqlalchemy_auth/block_base.py", line 86, in __getattribute__ return super().__getattribute__(name) File "{...}/.venv/lib/python3.6/site-packages/sqlalchemy/ext/associationproxy.py", line 263, in __get__ if self.scalar: File "{...}/.venv/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 767, in __get__ obj.__dict__[self.__name__] = result = self.fget(obj) File "{...}/.venv/lib/python3.6/site-packages/sqlalchemy/ext/associationproxy.py", line 233, in scalar scalar = not self._get_property().uselist File "{...}/.venv/lib/python3.6/site-packages/sqlalchemy/ext/associationproxy.py", line 215, in _get_property return (orm.class_mapper(self.owning_class). File "{...}/.venv/lib/python3.6/site-packages/sqlalchemy/orm/base.py", line 426, in class_mapper raise exc.UnmappedClassError(class_) UnmappedClassError: Class 'builtins.NoneType' is not mapped ``` ``` #!python from sqlalchemy import Column, ForeignKey, Integer, Text from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.declarative import declared_attr, declarative_base from sqlalchemy.orm import backref, relationship from sqlalchemy.orm.collections import attribute_mapped_collection Declarative_Base = declarative_base() class Mixin: @declared_attr def children(cls): class Child(Declarative_Base): parent_id = Column(Integer, ForeignKey(f'{cls.__tablename__}.id'), primary_key=True) key = Column(Text, primary_key=True) value = Column(Text, nullable=False) parent = relationship(cls, backref=backref( '_children', cascade='all, delete-orphan', collection_class=attribute_mapped_collection('key') )) __tablename__ = f'{cls.__tablename__}_child' return association_proxy( '_children', 'value', creator=lambda k, v: Child(key=k, value=v), ) class Parent(Mixin, Declarative_Base): id = Column(Integer, primary_key=True) __tablename__ = 'parent' #Parent.children # uncomment this for workaround class SubParent(Parent): id = Column(Integer, ForeignKey(Parent.id), primary_key=True) __tablename__ = 'subparent' Parent.children.owning_class # <class 'NoneType'> ``` This seems to be caused by the fix for https://bitbucket.org/zzzeek/sqlalchemy/issues/4116/accessing-associationproxy-of-aliased in commit https://bitbucket.org/zzzeek/sqlalchemy/commits/f14a58dea4b825beb4baaef44389880927543cc4 I don't know how to fix this, but am able to work around it for now by accessing the proxy attribute prior to the subclass definitions. I hope that by demonstrating it, you would be able to design a change that addresses the original issue and mitigates this side-effect. Thank you, Eric Responsible: zzzeek |