declarative syntax does not work with column_mapped_collection
Issue #1174
resolved
Using SA 0.5.0rc1.
I am using a pattern which boils down to this:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import orm
from sqlalchemy import schema
from sqlalchemy import types
from sqlalchemy.orm import collections
BaseObject = declarative_base()
class Foo(BaseObject):
__tablename__ = "foo"
id = schema.Column(types.Integer(), primary_key=True, autoincrement=True)
class Bar(BaseObject):
__tablename__ = "bar"
id = schema.Column(types.Integer(), primary_key=True, autoincrement=True)
foos = orm.relation(Foo, lazy=False,
collection_class=collections.column_mapped_collection(Foo.id))
this results in an error when initializing my models:
File "/local/buildout/eggs/tmpEDqA0a/SQLAlchemy-0.5.0rc1-py2.5.egg/sqlalchemy/orm/collections.py", line 140, in column_mapped_collection
TypeError: '_CompileOnAttr' object is not iterable
Comments (4)
-
Account Deleted -
repo owner heres a patch:
Index: lib/sqlalchemy/orm/properties.py =================================================================== --- lib/sqlalchemy/orm/properties.py (revision 5124) +++ lib/sqlalchemy/orm/properties.py (working copy) @@ -18,7 +18,7 @@ from sqlalchemy.orm import ( attributes, dependency, mapper, object_mapper, strategies, ) -from sqlalchemy.orm.util import CascadeOptions, _class_to_mapper, _orm_annotate +from sqlalchemy.orm.util import CascadeOptions, _class_to_mapper, _orm_annotate, _configurational_column_spec from sqlalchemy.orm.interfaces import ( MANYTOMANY, MANYTOONE, MapperProperty, ONETOMANY, PropComparator, StrategizedProperty, @@ -546,16 +546,12 @@ raise sa_exc.ArgumentError("relation '%s' expects a class or a mapper argument (received: %s)" % (self.key, type(self.argument))) assert isinstance(self.mapper, mapper.Mapper), self.mapper - # accept callables for other attributes which may require deferred initialization - for attr in ('order_by', 'primaryjoin', 'secondaryjoin', 'secondary', '_foreign_keys', 'remote_side'): - if callable(getattr(self, attr)): - setattr(self, attr, getattr(self, attr)()) - - if self.order_by: - self.order_by = [for x in util.to_list(self.order_by)](expression._literal_as_column(x)) - - self._foreign_keys = set(expression._literal_as_column(x) for x in util.to_set(self._foreign_keys)) - self.remote_side = set(expression._literal_as_column(x) for x in util.to_set(self.remote_side)) + self.order_by = _configurational_column_spec(self.order_by, util.to_list) + self.secondary = _configurational_column_spec(self.secondary) + self.primaryjoin = _configurational_column_spec(self.primaryjoin) + self.secondaryjoin = _configurational_column_spec(self.secondaryjoin) + self._foreign_keys = _configurational_column_spec(self._foreign_keys, util.to_set) + self.remote_side = _configurational_column_spec(self.remote_side, util.to_set) if not self.parent.concrete: for inheriting in self.parent.iterate_to_root(): Index: lib/sqlalchemy/orm/util.py =================================================================== --- lib/sqlalchemy/orm/util.py (revision 5124) +++ lib/sqlalchemy/orm/util.py (working copy) @@ -459,6 +459,28 @@ def _state_mapper(state): return state.manager.mapper +def _configurational_column_spec(expr, filter=None): + """Perform argument conversions on a column-based configurational expression.""" + + # interpret callables passed by declarative + if callable(expr): + expr = expr() + + # "False" is our current "use the default" symbol + if expr is False: + return expr + + if expr is None: + ret = None + elif isinstance(expr, (tuple, list, set)): + ret = [for x in expr](_configurational_column_spec(x)) + else: + + ret = expression._literal_as_column(expr) + if filter: + ret = filter(ret) + return ret + def object_mapper(object, raiseerror=True): """Given an object, return the primary Mapper associated with the object instance. Index: lib/sqlalchemy/orm/collections.py =================================================================== --- lib/sqlalchemy/orm/collections.py (revision 5124) +++ lib/sqlalchemy/orm/collections.py (working copy) @@ -105,9 +105,9 @@ import sqlalchemy.exceptions as sa_exc from sqlalchemy import schema +from sqlalchemy.sql import expression import sqlalchemy.util as sautil - __all__ = ['collection_adapter', 'mapped_collection', 'column_mapped_collection', 'attribute_mapped_collection']('collection',) @@ -127,9 +127,12 @@ after a session flush. """ - from sqlalchemy.orm.util import _state_mapper + from sqlalchemy.orm.util import _state_mapper, _configurational_column_spec from sqlalchemy.orm.attributes import instance_state + + mapping_spec = _configurational_column_spec(mapping_spec) + if isinstance(mapping_spec, schema.Column): def keyfunc(value): state = instance_state(value)
-
repo owner - changed status to resolved
I just re-noticed that patch above, for now went with something simpler in 9b360dda29f5dbf260d27f43247b1adc9298c51a. It doesn't yet support string-based arguments.
-
repo owner - removed milestone
Removing milestone: 0.5.0 (automated comment)
- Log in to comment
Relevant irc comments:
as an alternative you can also use attribute_mapped_column("id") here.