Re: [Sqlalchemy-tickets] [sqlalchemy] #2900: relationship aliased on subclass causes infinite recur
Brought to you by:
zzzeek
|
From: sqlalchemy <mi...@zz...> - 2014-01-01 21:30:20
|
#2900: relationship aliased on subclass causes infinite recursion
---------------------------+-------------------------------
Reporter: scraper | Owner: zzzeek
Type: defect | Status: new
Priority: highest | Milestone: 0.9.xx
Component: orm | Severity: major - 1-3 hours
Resolution: | Keywords:
Progress State: in queue |
---------------------------+-------------------------------
Comment (by zzzeek):
i think just having decalrative turn them into synonyms is the most
straightforward route, otherwise we really can't be too smart about what's
going on, e.g. in the original case where !FooChild has "parent =
Child.foo" inline:
{{{
#!diff
diff --git a/lib/sqlalchemy/ext/declarative/base.py
b/lib/sqlalchemy/ext/declarative/base.py
index f7668a5..a571d07 100644
--- a/lib/sqlalchemy/ext/declarative/base.py
+++ b/lib/sqlalchemy/ext/declarative/base.py
@@ -6,9 +6,10 @@
"""Internal implementation for declarative."""
from ...schema import Table, Column
-from ...orm import mapper, class_mapper
+from ...orm import mapper, class_mapper, synonym
from ...orm.interfaces import MapperProperty
from ...orm.properties import ColumnProperty, CompositeProperty
+from ...orm.attributes import QueryableAttribute
from ...orm.base import _is_mapped_class
from ... import util, exc
from ...sql import expression
@@ -148,6 +149,15 @@ def _as_declarative(cls, classname, dict_):
if isinstance(value, declarative_props):
value = getattr(cls, k)
+ elif isinstance(value, QueryableAttribute) and \
+ value.class_ is not cls and \
+ value.key != k:
+ # detect a QueryableAttribute that's already mapped being
+ # assigned elsewhere in userland, turn into a synonym()
+ value = synonym(value.key)
+ setattr(cls, k, value)
+
+
if (isinstance(value, tuple) and len(value) == 1 and
isinstance(value[0], (Column, MapperProperty))):
util.warn("Ignoring declarative-like tuple value of attribute
"
@@ -397,6 +407,7 @@ def _add_attribute(cls, key, value):
adds it to the Mapper, adds a column to the mapped Table, etc.
"""
+
if '__mapper__' in cls.__dict__:
if isinstance(value, Column):
_undefer_column_name(key, value)
@@ -413,6 +424,11 @@ def _add_attribute(cls, key, value):
key,
clsregistry._deferred_relationship(cls, value)
)
+ elif isinstance(value, QueryableAttribute) and value.key != key:
+ # detect a QueryableAttribute that's already mapped being
+ # assigned elsewhere in userland, turn into a synonym()
+ value = synonym(value.key)
+ type.__setattr__(cls, key, value)
else:
type.__setattr__(cls, key, value)
else:
}}}
--
Ticket URL: <http://www.sqlalchemy.org/trac/ticket/2900#comment:5>
sqlalchemy <http://www.sqlalchemy.org/>
The Database Toolkit for Python
|