/SQLAlchemy-0.7.8/test/ext/test_associationproxy.py
Python | 1369 lines | 1062 code | 290 blank | 17 comment | 51 complexity | bedaf670fede93d244fb797b82068e92 MD5 | raw file
- from test.lib.testing import eq_, assert_raises
- import copy
- import pickle
- from sqlalchemy import *
- from sqlalchemy.orm import *
- from sqlalchemy.orm.collections import collection, attribute_mapped_collection
- from sqlalchemy.ext.associationproxy import *
- from sqlalchemy.ext.associationproxy import _AssociationList
- from test.lib import *
- from test.lib.testing import assert_raises_message
- from test.lib.util import gc_collect
- from sqlalchemy.sql import not_
- from test.lib import fixtures
- class DictCollection(dict):
- @collection.appender
- def append(self, obj):
- self[obj.foo] = obj
- @collection.remover
- def remove(self, obj):
- del self[obj.foo]
- class SetCollection(set):
- pass
- class ListCollection(list):
- pass
- class ObjectCollection(object):
- def __init__(self):
- self.values = list()
- @collection.appender
- def append(self, obj):
- self.values.append(obj)
- @collection.remover
- def remove(self, obj):
- self.values.remove(obj)
- def __iter__(self):
- return iter(self.values)
- class _CollectionOperations(fixtures.TestBase):
- def setup(self):
- collection_class = self.collection_class
- metadata = MetaData(testing.db)
- parents_table = Table('Parent', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('name', String(128)))
- children_table = Table('Children', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('parent_id', Integer,
- ForeignKey('Parent.id')),
- Column('foo', String(128)),
- Column('name', String(128)))
- class Parent(object):
- children = association_proxy('_children', 'name')
- def __init__(self, name):
- self.name = name
- class Child(object):
- if collection_class and issubclass(collection_class, dict):
- def __init__(self, foo, name):
- self.foo = foo
- self.name = name
- else:
- def __init__(self, name):
- self.name = name
- mapper(Parent, parents_table, properties={
- '_children': relationship(Child, lazy='joined',
- collection_class=collection_class)})
- mapper(Child, children_table)
- metadata.create_all()
- self.metadata = metadata
- self.session = create_session()
- self.Parent, self.Child = Parent, Child
- def teardown(self):
- self.metadata.drop_all()
- def roundtrip(self, obj):
- if obj not in self.session:
- self.session.add(obj)
- self.session.flush()
- id, type_ = obj.id, type(obj)
- self.session.expunge_all()
- return self.session.query(type_).get(id)
- def _test_sequence_ops(self):
- Parent, Child = self.Parent, self.Child
- p1 = Parent('P1')
- self.assert_(not p1._children)
- self.assert_(not p1.children)
- ch = Child('regular')
- p1._children.append(ch)
- self.assert_(ch in p1._children)
- self.assert_(len(p1._children) == 1)
- self.assert_(p1.children)
- self.assert_(len(p1.children) == 1)
- self.assert_(ch not in p1.children)
- self.assert_('regular' in p1.children)
- p1.children.append('proxied')
- self.assert_('proxied' in p1.children)
- self.assert_('proxied' not in p1._children)
- self.assert_(len(p1.children) == 2)
- self.assert_(len(p1._children) == 2)
- self.assert_(p1._children[0].name == 'regular')
- self.assert_(p1._children[1].name == 'proxied')
- del p1._children[1]
- self.assert_(len(p1._children) == 1)
- self.assert_(len(p1.children) == 1)
- self.assert_(p1._children[0] == ch)
- del p1.children[0]
- self.assert_(len(p1._children) == 0)
- self.assert_(len(p1.children) == 0)
- p1.children = ['a','b','c']
- self.assert_(len(p1._children) == 3)
- self.assert_(len(p1.children) == 3)
- del ch
- p1 = self.roundtrip(p1)
- self.assert_(len(p1._children) == 3)
- self.assert_(len(p1.children) == 3)
- popped = p1.children.pop()
- self.assert_(len(p1.children) == 2)
- self.assert_(popped not in p1.children)
- p1 = self.roundtrip(p1)
- self.assert_(len(p1.children) == 2)
- self.assert_(popped not in p1.children)
- p1.children[1] = 'changed-in-place'
- self.assert_(p1.children[1] == 'changed-in-place')
- inplace_id = p1._children[1].id
- p1 = self.roundtrip(p1)
- self.assert_(p1.children[1] == 'changed-in-place')
- assert p1._children[1].id == inplace_id
- p1.children.append('changed-in-place')
- self.assert_(p1.children.count('changed-in-place') == 2)
- p1.children.remove('changed-in-place')
- self.assert_(p1.children.count('changed-in-place') == 1)
- p1 = self.roundtrip(p1)
- self.assert_(p1.children.count('changed-in-place') == 1)
- p1._children = []
- self.assert_(len(p1.children) == 0)
- after = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
- p1.children = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
- self.assert_(len(p1.children) == 10)
- self.assert_([c.name for c in p1._children] == after)
- p1.children[2:6] = ['x'] * 4
- after = ['a', 'b', 'x', 'x', 'x', 'x', 'g', 'h', 'i', 'j']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children[2:6] = ['y']
- after = ['a', 'b', 'y', 'g', 'h', 'i', 'j']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children[2:3] = ['z'] * 4
- after = ['a', 'b', 'z', 'z', 'z', 'z', 'g', 'h', 'i', 'j']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children[2::2] = ['O'] * 4
- after = ['a', 'b', 'O', 'z', 'O', 'z', 'O', 'h', 'O', 'j']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- assert_raises(TypeError, set, [p1.children])
- p1.children *= 0
- after = []
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children += ['a', 'b']
- after = ['a', 'b']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children += ['c']
- after = ['a', 'b', 'c']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children *= 1
- after = ['a', 'b', 'c']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children *= 2
- after = ['a', 'b', 'c', 'a', 'b', 'c']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- p1.children = ['a']
- after = ['a']
- self.assert_(p1.children == after)
- self.assert_([c.name for c in p1._children] == after)
- self.assert_((p1.children * 2) == ['a', 'a'])
- self.assert_((2 * p1.children) == ['a', 'a'])
- self.assert_((p1.children * 0) == [])
- self.assert_((0 * p1.children) == [])
- self.assert_((p1.children + ['b']) == ['a', 'b'])
- self.assert_((['b'] + p1.children) == ['b', 'a'])
- try:
- p1.children + 123
- assert False
- except TypeError:
- assert True
- class DefaultTest(_CollectionOperations):
- def __init__(self, *args, **kw):
- super(DefaultTest, self).__init__(*args, **kw)
- self.collection_class = None
- def test_sequence_ops(self):
- self._test_sequence_ops()
- class ListTest(_CollectionOperations):
- def __init__(self, *args, **kw):
- super(ListTest, self).__init__(*args, **kw)
- self.collection_class = list
- def test_sequence_ops(self):
- self._test_sequence_ops()
- class CustomListTest(ListTest):
- def __init__(self, *args, **kw):
- super(CustomListTest, self).__init__(*args, **kw)
- self.collection_class = list
- # No-can-do until ticket #213
- class DictTest(_CollectionOperations):
- pass
- class CustomDictTest(DictTest):
- def __init__(self, *args, **kw):
- super(DictTest, self).__init__(*args, **kw)
- self.collection_class = DictCollection
- def test_mapping_ops(self):
- Parent, Child = self.Parent, self.Child
- p1 = Parent('P1')
- self.assert_(not p1._children)
- self.assert_(not p1.children)
- ch = Child('a', 'regular')
- p1._children.append(ch)
- self.assert_(ch in p1._children.values())
- self.assert_(len(p1._children) == 1)
- self.assert_(p1.children)
- self.assert_(len(p1.children) == 1)
- self.assert_(ch not in p1.children)
- self.assert_('a' in p1.children)
- self.assert_(p1.children['a'] == 'regular')
- self.assert_(p1._children['a'] == ch)
- p1.children['b'] = 'proxied'
- self.assert_('proxied' in p1.children.values())
- self.assert_('b' in p1.children)
- self.assert_('proxied' not in p1._children)
- self.assert_(len(p1.children) == 2)
- self.assert_(len(p1._children) == 2)
- self.assert_(p1._children['a'].name == 'regular')
- self.assert_(p1._children['b'].name == 'proxied')
- del p1._children['b']
- self.assert_(len(p1._children) == 1)
- self.assert_(len(p1.children) == 1)
- self.assert_(p1._children['a'] == ch)
- del p1.children['a']
- self.assert_(len(p1._children) == 0)
- self.assert_(len(p1.children) == 0)
- p1.children = {'d': 'v d', 'e': 'v e', 'f': 'v f'}
- self.assert_(len(p1._children) == 3)
- self.assert_(len(p1.children) == 3)
- self.assert_(set(p1.children) == set(['d','e','f']))
- del ch
- p1 = self.roundtrip(p1)
- self.assert_(len(p1._children) == 3)
- self.assert_(len(p1.children) == 3)
- p1.children['e'] = 'changed-in-place'
- self.assert_(p1.children['e'] == 'changed-in-place')
- inplace_id = p1._children['e'].id
- p1 = self.roundtrip(p1)
- self.assert_(p1.children['e'] == 'changed-in-place')
- self.assert_(p1._children['e'].id == inplace_id)
- p1._children = {}
- self.assert_(len(p1.children) == 0)
- try:
- p1._children = []
- self.assert_(False)
- except TypeError:
- self.assert_(True)
- try:
- p1._children = None
- self.assert_(False)
- except TypeError:
- self.assert_(True)
- assert_raises(TypeError, set, [p1.children])
- class SetTest(_CollectionOperations):
- def __init__(self, *args, **kw):
- super(SetTest, self).__init__(*args, **kw)
- self.collection_class = set
- def test_set_operations(self):
- Parent, Child = self.Parent, self.Child
- p1 = Parent('P1')
- self.assert_(not p1._children)
- self.assert_(not p1.children)
- ch1 = Child('regular')
- p1._children.add(ch1)
- self.assert_(ch1 in p1._children)
- self.assert_(len(p1._children) == 1)
- self.assert_(p1.children)
- self.assert_(len(p1.children) == 1)
- self.assert_(ch1 not in p1.children)
- self.assert_('regular' in p1.children)
- p1.children.add('proxied')
- self.assert_('proxied' in p1.children)
- self.assert_('proxied' not in p1._children)
- self.assert_(len(p1.children) == 2)
- self.assert_(len(p1._children) == 2)
- self.assert_(set([o.name for o in p1._children]) ==
- set(['regular', 'proxied']))
- ch2 = None
- for o in p1._children:
- if o.name == 'proxied':
- ch2 = o
- break
- p1._children.remove(ch2)
- self.assert_(len(p1._children) == 1)
- self.assert_(len(p1.children) == 1)
- self.assert_(p1._children == set([ch1]))
- p1.children.remove('regular')
- self.assert_(len(p1._children) == 0)
- self.assert_(len(p1.children) == 0)
- p1.children = ['a','b','c']
- self.assert_(len(p1._children) == 3)
- self.assert_(len(p1.children) == 3)
- del ch1
- p1 = self.roundtrip(p1)
- self.assert_(len(p1._children) == 3)
- self.assert_(len(p1.children) == 3)
- self.assert_('a' in p1.children)
- self.assert_('b' in p1.children)
- self.assert_('d' not in p1.children)
- self.assert_(p1.children == set(['a','b','c']))
- try:
- p1.children.remove('d')
- self.fail()
- except KeyError:
- pass
- self.assert_(len(p1.children) == 3)
- p1.children.discard('d')
- self.assert_(len(p1.children) == 3)
- p1 = self.roundtrip(p1)
- self.assert_(len(p1.children) == 3)
- popped = p1.children.pop()
- self.assert_(len(p1.children) == 2)
- self.assert_(popped not in p1.children)
- p1 = self.roundtrip(p1)
- self.assert_(len(p1.children) == 2)
- self.assert_(popped not in p1.children)
- p1.children = ['a','b','c']
- p1 = self.roundtrip(p1)
- self.assert_(p1.children == set(['a','b','c']))
- p1.children.discard('b')
- p1 = self.roundtrip(p1)
- self.assert_(p1.children == set(['a', 'c']))
- p1.children.remove('a')
- p1 = self.roundtrip(p1)
- self.assert_(p1.children == set(['c']))
- p1._children = set()
- self.assert_(len(p1.children) == 0)
- try:
- p1._children = []
- self.assert_(False)
- except TypeError:
- self.assert_(True)
- try:
- p1._children = None
- self.assert_(False)
- except TypeError:
- self.assert_(True)
- assert_raises(TypeError, set, [p1.children])
- def test_set_comparisons(self):
- Parent, Child = self.Parent, self.Child
- p1 = Parent('P1')
- p1.children = ['a','b','c']
- control = set(['a','b','c'])
- for other in (set(['a','b','c']), set(['a','b','c','d']),
- set(['a']), set(['a','b']),
- set(['c','d']), set(['e', 'f', 'g']),
- set()):
- eq_(p1.children.union(other),
- control.union(other))
- eq_(p1.children.difference(other),
- control.difference(other))
- eq_((p1.children - other),
- (control - other))
- eq_(p1.children.intersection(other),
- control.intersection(other))
- eq_(p1.children.symmetric_difference(other),
- control.symmetric_difference(other))
- eq_(p1.children.issubset(other),
- control.issubset(other))
- eq_(p1.children.issuperset(other),
- control.issuperset(other))
- self.assert_((p1.children == other) == (control == other))
- self.assert_((p1.children != other) == (control != other))
- self.assert_((p1.children < other) == (control < other))
- self.assert_((p1.children <= other) == (control <= other))
- self.assert_((p1.children > other) == (control > other))
- self.assert_((p1.children >= other) == (control >= other))
- def test_set_mutation(self):
- Parent, Child = self.Parent, self.Child
- # mutations
- for op in ('update', 'intersection_update',
- 'difference_update', 'symmetric_difference_update'):
- for base in (['a', 'b', 'c'], []):
- for other in (set(['a','b','c']), set(['a','b','c','d']),
- set(['a']), set(['a','b']),
- set(['c','d']), set(['e', 'f', 'g']),
- set()):
- p = Parent('p')
- p.children = base[:]
- control = set(base[:])
- getattr(p.children, op)(other)
- getattr(control, op)(other)
- try:
- self.assert_(p.children == control)
- except:
- print 'Test %s.%s(%s):' % (set(base), op, other)
- print 'want', repr(control)
- print 'got', repr(p.children)
- raise
- p = self.roundtrip(p)
- try:
- self.assert_(p.children == control)
- except:
- print 'Test %s.%s(%s):' % (base, op, other)
- print 'want', repr(control)
- print 'got', repr(p.children)
- raise
- # in-place mutations
- for op in ('|=', '-=', '&=', '^='):
- for base in (['a', 'b', 'c'], []):
- for other in (set(['a','b','c']), set(['a','b','c','d']),
- set(['a']), set(['a','b']),
- set(['c','d']), set(['e', 'f', 'g']),
- frozenset(['e', 'f', 'g']),
- set()):
- p = Parent('p')
- p.children = base[:]
- control = set(base[:])
- exec "p.children %s other" % op
- exec "control %s other" % op
- try:
- self.assert_(p.children == control)
- except:
- print 'Test %s %s %s:' % (set(base), op, other)
- print 'want', repr(control)
- print 'got', repr(p.children)
- raise
- p = self.roundtrip(p)
- try:
- self.assert_(p.children == control)
- except:
- print 'Test %s %s %s:' % (base, op, other)
- print 'want', repr(control)
- print 'got', repr(p.children)
- raise
- class CustomSetTest(SetTest):
- def __init__(self, *args, **kw):
- super(CustomSetTest, self).__init__(*args, **kw)
- self.collection_class = SetCollection
- class CustomObjectTest(_CollectionOperations):
- def __init__(self, *args, **kw):
- super(CustomObjectTest, self).__init__(*args, **kw)
- self.collection_class = ObjectCollection
- def test_basic(self):
- Parent, Child = self.Parent, self.Child
- p = Parent('p1')
- self.assert_(len(list(p.children)) == 0)
- p.children.append('child')
- self.assert_(len(list(p.children)) == 1)
- p = self.roundtrip(p)
- self.assert_(len(list(p.children)) == 1)
- # We didn't provide an alternate _AssociationList implementation
- # for our ObjectCollection, so indexing will fail.
- try:
- v = p.children[1]
- self.fail()
- except TypeError:
- pass
- class ProxyFactoryTest(ListTest):
- def setup(self):
- metadata = MetaData(testing.db)
- parents_table = Table('Parent', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('name', String(128)))
- children_table = Table('Children', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('parent_id', Integer,
- ForeignKey('Parent.id')),
- Column('foo', String(128)),
- Column('name', String(128)))
- class CustomProxy(_AssociationList):
- def __init__(
- self,
- lazy_collection,
- creator,
- value_attr,
- parent,
- ):
- getter, setter = parent._default_getset(lazy_collection)
- _AssociationList.__init__(
- self,
- lazy_collection,
- creator,
- getter,
- setter,
- parent,
- )
- class Parent(object):
- children = association_proxy('_children', 'name',
- proxy_factory=CustomProxy,
- proxy_bulk_set=CustomProxy.extend
- )
- def __init__(self, name):
- self.name = name
- class Child(object):
- def __init__(self, name):
- self.name = name
- mapper(Parent, parents_table, properties={
- '_children': relationship(Child, lazy='joined',
- collection_class=list)})
- mapper(Child, children_table)
- metadata.create_all()
- self.metadata = metadata
- self.session = create_session()
- self.Parent, self.Child = Parent, Child
- def test_sequence_ops(self):
- self._test_sequence_ops()
- class ScalarTest(fixtures.TestBase):
- def test_scalar_proxy(self):
- metadata = MetaData(testing.db)
- parents_table = Table('Parent', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('name', String(128)))
- children_table = Table('Children', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('parent_id', Integer,
- ForeignKey('Parent.id')),
- Column('foo', String(128)),
- Column('bar', String(128)),
- Column('baz', String(128)))
- class Parent(object):
- foo = association_proxy('child', 'foo')
- bar = association_proxy('child', 'bar',
- creator=lambda v: Child(bar=v))
- baz = association_proxy('child', 'baz',
- creator=lambda v: Child(baz=v))
- def __init__(self, name):
- self.name = name
- class Child(object):
- def __init__(self, **kw):
- for attr in kw:
- setattr(self, attr, kw[attr])
- mapper(Parent, parents_table, properties={
- 'child': relationship(Child, lazy='joined',
- backref='parent', uselist=False)})
- mapper(Child, children_table)
- metadata.create_all()
- session = create_session()
- def roundtrip(obj):
- if obj not in session:
- session.add(obj)
- session.flush()
- id, type_ = obj.id, type(obj)
- session.expunge_all()
- return session.query(type_).get(id)
- p = Parent('p')
- # No child
- try:
- v = p.foo
- self.fail()
- except:
- pass
- p.child = Child(foo='a', bar='b', baz='c')
- self.assert_(p.foo == 'a')
- self.assert_(p.bar == 'b')
- self.assert_(p.baz == 'c')
- p.bar = 'x'
- self.assert_(p.foo == 'a')
- self.assert_(p.bar == 'x')
- self.assert_(p.baz == 'c')
- p = roundtrip(p)
- self.assert_(p.foo == 'a')
- self.assert_(p.bar == 'x')
- self.assert_(p.baz == 'c')
- p.child = None
- # No child again
- try:
- v = p.foo
- self.fail()
- except:
- pass
- # Bogus creator for this scalar type
- try:
- p.foo = 'zzz'
- self.fail()
- except TypeError:
- pass
- p.bar = 'yyy'
- self.assert_(p.foo is None)
- self.assert_(p.bar == 'yyy')
- self.assert_(p.baz is None)
- del p.child
- p = roundtrip(p)
- self.assert_(p.child is None)
- p.baz = 'xxx'
- self.assert_(p.foo is None)
- self.assert_(p.bar is None)
- self.assert_(p.baz == 'xxx')
- p = roundtrip(p)
- self.assert_(p.foo is None)
- self.assert_(p.bar is None)
- self.assert_(p.baz == 'xxx')
- # Ensure an immediate __set__ works.
- p2 = Parent('p2')
- p2.bar = 'quux'
- class LazyLoadTest(fixtures.TestBase):
- def setup(self):
- metadata = MetaData(testing.db)
- parents_table = Table('Parent', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('name', String(128)))
- children_table = Table('Children', metadata,
- Column('id', Integer, primary_key=True,
- test_needs_autoincrement=True),
- Column('parent_id', Integer,
- ForeignKey('Parent.id')),
- Column('foo', String(128)),
- Column('name', String(128)))
- class Parent(object):
- children = association_proxy('_children', 'name')
- def __init__(self, name):
- self.name = name
- class Child(object):
- def __init__(self, name):
- self.name = name
- mapper(Child, children_table)
- metadata.create_all()
- self.metadata = metadata
- self.session = create_session()
- self.Parent, self.Child = Parent, Child
- self.table = parents_table
- def teardown(self):
- self.metadata.drop_all()
- def roundtrip(self, obj):
- self.session.add(obj)
- self.session.flush()
- id, type_ = obj.id, type(obj)
- self.session.expunge_all()
- return self.session.query(type_).get(id)
- def test_lazy_list(self):
- Parent, Child = self.Parent, self.Child
- mapper(Parent, self.table, properties={
- '_children': relationship(Child, lazy='select',
- collection_class=list)})
- p = Parent('p')
- p.children = ['a','b','c']
- p = self.roundtrip(p)
- # Is there a better way to ensure that the association_proxy
- # didn't convert a lazy load to an eager load? This does work though.
- self.assert_('_children' not in p.__dict__)
- self.assert_(len(p._children) == 3)
- self.assert_('_children' in p.__dict__)
- def test_eager_list(self):
- Parent, Child = self.Parent, self.Child
- mapper(Parent, self.table, properties={
- '_children': relationship(Child, lazy='joined',
- collection_class=list)})
- p = Parent('p')
- p.children = ['a','b','c']
- p = self.roundtrip(p)
- self.assert_('_children' in p.__dict__)
- self.assert_(len(p._children) == 3)
- def test_lazy_scalar(self):
- Parent, Child = self.Parent, self.Child
- mapper(Parent, self.table, properties={
- '_children': relationship(Child, lazy='select', uselist=False)})
- p = Parent('p')
- p.children = 'value'
- p = self.roundtrip(p)
- self.assert_('_children' not in p.__dict__)
- self.assert_(p._children is not None)
- def test_eager_scalar(self):
- Parent, Child = self.Parent, self.Child
- mapper(Parent, self.table, properties={
- '_children': relationship(Child, lazy='joined', uselist=False)})
- p = Parent('p')
- p.children = 'value'
- p = self.roundtrip(p)
- self.assert_('_children' in p.__dict__)
- self.assert_(p._children is not None)
- class Parent(object):
- def __init__(self, name):
- self.name = name
- class Child(object):
- def __init__(self, name):
- self.name = name
- class KVChild(object):
- def __init__(self, name, value):
- self.name = name
- self.value = value
- class ReconstitutionTest(fixtures.TestBase):
- def setup(self):
- metadata = MetaData(testing.db)
- parents = Table('parents', metadata, Column('id', Integer,
- primary_key=True,
- test_needs_autoincrement=True), Column('name',
- String(30)))
- children = Table('children', metadata, Column('id', Integer,
- primary_key=True,
- test_needs_autoincrement=True),
- Column('parent_id', Integer,
- ForeignKey('parents.id')), Column('name',
- String(30)))
- metadata.create_all()
- parents.insert().execute(name='p1')
- self.metadata = metadata
- self.parents = parents
- self.children = children
- Parent.kids = association_proxy('children', 'name')
- def teardown(self):
- self.metadata.drop_all()
- clear_mappers()
- def test_weak_identity_map(self):
- mapper(Parent, self.parents,
- properties=dict(children=relationship(Child)))
- mapper(Child, self.children)
- session = create_session(weak_identity_map=True)
- def add_child(parent_name, child_name):
- parent = \
- session.query(Parent).filter_by(name=parent_name).one()
- parent.kids.append(child_name)
- add_child('p1', 'c1')
- gc_collect()
- add_child('p1', 'c2')
- session.flush()
- p = session.query(Parent).filter_by(name='p1').one()
- assert set(p.kids) == set(['c1', 'c2']), p.kids
- def test_copy(self):
- mapper(Parent, self.parents,
- properties=dict(children=relationship(Child)))
- mapper(Child, self.children)
- p = Parent('p1')
- p.kids.extend(['c1', 'c2'])
- p_copy = copy.copy(p)
- del p
- gc_collect()
- assert set(p_copy.kids) == set(['c1', 'c2']), p.kids
- def test_pickle_list(self):
- mapper(Parent, self.parents,
- properties=dict(children=relationship(Child)))
- mapper(Child, self.children)
- p = Parent('p1')
- p.kids.extend(['c1', 'c2'])
- r1 = pickle.loads(pickle.dumps(p))
- assert r1.kids == ['c1', 'c2']
- r2 = pickle.loads(pickle.dumps(p.kids))
- assert r2 == ['c1', 'c2']
- def test_pickle_set(self):
- mapper(Parent, self.parents,
- properties=dict(children=relationship(Child,
- collection_class=set)))
- mapper(Child, self.children)
- p = Parent('p1')
- p.kids.update(['c1', 'c2'])
- r1 = pickle.loads(pickle.dumps(p))
- assert r1.kids == set(['c1', 'c2'])
- r2 = pickle.loads(pickle.dumps(p.kids))
- assert r2 == set(['c1', 'c2'])
- def test_pickle_dict(self):
- mapper(Parent, self.parents,
- properties=dict(children=relationship(KVChild,
- collection_class=
- collections.mapped_collection(PickleKeyFunc('name')))))
- mapper(KVChild, self.children)
- p = Parent('p1')
- p.kids.update({'c1': 'v1', 'c2': 'v2'})
- assert p.kids == {'c1': 'c1', 'c2': 'c2'}
- r1 = pickle.loads(pickle.dumps(p))
- assert r1.kids == {'c1': 'c1', 'c2': 'c2'}
- r2 = pickle.loads(pickle.dumps(p.kids))
- assert r2 == {'c1': 'c1', 'c2': 'c2'}
- class PickleKeyFunc(object):
- def __init__(self, name):
- self.name = name
- def __call__(self, obj):
- return getattr(obj, self.name)
- class ComparatorTest(fixtures.MappedTest, AssertsCompiledSQL):
- __dialect__ = 'default'
- run_inserts = 'once'
- run_deletes = None
- run_setup_mappers = 'once'
- run_setup_classes = 'once'
- @classmethod
- def define_tables(cls, metadata):
- Table('userkeywords', metadata,
- Column('keyword_id', Integer,ForeignKey('keywords.id'), primary_key=True),
- Column('user_id', Integer, ForeignKey('users.id'))
- )
- Table('users', metadata,
- Column('id', Integer,
- primary_key=True, test_needs_autoincrement=True),
- Column('name', String(64)),
- Column('singular_id', Integer, ForeignKey('singular.id'))
- )
- Table('keywords', metadata,
- Column('id', Integer,
- primary_key=True, test_needs_autoincrement=True),
- Column('keyword', String(64)),
- Column('singular_id', Integer, ForeignKey('singular.id'))
- )
- Table('singular', metadata,
- Column('id', Integer,
- primary_key=True, test_needs_autoincrement=True),
- )
- @classmethod
- def setup_classes(cls):
- class User(cls.Comparable):
- def __init__(self, name):
- self.name = name
- # o2m -> m2o
- # uselist -> nonuselist
- keywords = association_proxy('user_keywords', 'keyword',
- creator=lambda k: UserKeyword(keyword=k))
- # m2o -> o2m
- # nonuselist -> uselist
- singular_keywords = association_proxy('singular', 'keywords')
- class Keyword(cls.Comparable):
- def __init__(self, keyword):
- self.keyword = keyword
- # o2o -> m2o
- # nonuselist -> nonuselist
- user = association_proxy('user_keyword', 'user')
- class UserKeyword(cls.Comparable):
- def __init__(self, user=None, keyword=None):
- self.user = user
- self.keyword = keyword
- class Singular(cls.Comparable):
- def __init__(self, value=None):
- self.value = value
- @classmethod
- def setup_mappers(cls):
- users, Keyword, UserKeyword, singular, \
- userkeywords, User, keywords, Singular = (cls.tables.users,
- cls.classes.Keyword,
- cls.classes.UserKeyword,
- cls.tables.singular,
- cls.tables.userkeywords,
- cls.classes.User,
- cls.tables.keywords,
- cls.classes.Singular)
- mapper(User, users, properties={
- 'singular':relationship(Singular)
- })
- mapper(Keyword, keywords, properties={
- 'user_keyword':relationship(UserKeyword, uselist=False)
- })
- mapper(UserKeyword, userkeywords, properties={
- 'user' : relationship(User, backref='user_keywords'),
- 'keyword' : relationship(Keyword)
- })
- mapper(Singular, singular, properties={
- 'keywords': relationship(Keyword)
- })
- @classmethod
- def insert_data(cls):
- UserKeyword, User, Keyword, Singular = (cls.classes.UserKeyword,
- cls.classes.User,
- cls.classes.Keyword,
- cls.classes.Singular)
- session = sessionmaker()()
- words = (
- 'quick', 'brown',
- 'fox', 'jumped', 'over',
- 'the', 'lazy',
- )
- for ii in range(4):
- user = User('user%d' % ii)
- user.singular = Singular()
- session.add(user)
- for jj in words[ii:ii + 3]:
- k = Keyword(jj)
- user.keywords.append(k)
- user.singular.keywords.append(k)
- orphan = Keyword('orphan')
- orphan.user_keyword = UserKeyword(keyword=orphan, user=None)
- session.add(orphan)
- session.commit()
- cls.u = user
- cls.kw = user.keywords[0]
- cls.session = session
- def _equivalent(self, q_proxy, q_direct):
- eq_(q_proxy.all(), q_direct.all())
- def test_filter_any_kwarg_ul_nul(self):
- UserKeyword, User = self.classes.UserKeyword, self.classes.User
- self._equivalent(self.session.query(User).
- filter(User.keywords.any(keyword='jumped'
- )),
- self.session.query(User).filter(
- User.user_keywords.any(
- UserKeyword.keyword.has(keyword='jumped'
- ))))
- def test_filter_has_kwarg_nul_nul(self):
- UserKeyword, Keyword = self.classes.UserKeyword, self.classes.Keyword
- self._equivalent(self.session.query(Keyword).
- filter(Keyword.user.has(name='user2'
- )),
- self.session.query(Keyword).
- filter(Keyword.user_keyword.has(
- UserKeyword.user.has(name='user2'
- ))))
- def test_filter_has_kwarg_nul_ul(self):
- User, Singular = self.classes.User, self.classes.Singular
- self._equivalent(
- self.session.query(User).\
- filter(User.singular_keywords.any(keyword='jumped')),
- self.session.query(User).\
- filter(
- User.singular.has(
- Singular.keywords.any(keyword='jumped')
- )
- )
- )
- def test_filter_any_criterion_ul_nul(self):
- UserKeyword, User, Keyword = (self.classes.UserKeyword,
- self.classes.User,
- self.classes.Keyword)
- self._equivalent(self.session.query(User).
- filter(User.keywords.any(Keyword.keyword
- == 'jumped')),
- self.session.query(User).
- filter(User.user_keywords.any(
- UserKeyword.keyword.has(Keyword.keyword
- == 'jumped'))))
- def test_filter_has_criterion_nul_nul(self):
- UserKeyword, User, Keyword = (self.classes.UserKeyword,
- self.classes.User,
- self.classes.Keyword)
- self._equivalent(self.session.query(Keyword).
- filter(Keyword.user.has(User.name
- == 'user2')),
- self.session.query(Keyword).
- filter(Keyword.user_keyword.has(
- UserKeyword.user.has(User.name
- == 'user2'))))
- def test_filter_any_criterion_nul_ul(self):
- User, Keyword, Singular = (self.classes.User,
- self.classes.Keyword,
- self.classes.Singular)
- self._equivalent(
- self.session.query(User).\
- filter(User.singular_keywords.any(Keyword.keyword=='jumped')),
- self.session.query(User).\
- filter(
- User.singular.has(
- Singular.keywords.any(Keyword.keyword=='jumped')
- )
- )
- )
- def test_filter_contains_ul_nul(self):
- User = self.classes.User
- self._equivalent(self.session.query(User).
- filter(User.keywords.contains(self.kw)),
- self.session.query(User).
- filter(User.user_keywords.any(keyword=self.kw)))
- def test_filter_contains_nul_ul(self):
- User, Singular = self.classes.User, self.classes.Singular
- self._equivalent(
- self.session.query(User).filter(
- User.singular_keywords.contains(self.kw)
- ),
- self.session.query(User).filter(
- User.singular.has(
- Singular.keywords.contains(self.kw)
- )
- ),
- )
- def test_filter_eq_nul_nul(self):
- Keyword = self.classes.Keyword
- self._equivalent(self.session.query(Keyword).filter(Keyword.user
- == self.u),
- self.session.query(Keyword).
- filter(Keyword.user_keyword.has(user=self.u)))
- def test_filter_ne_nul_nul(self):
- Keyword = self.classes.Keyword
- self._equivalent(self.session.query(Keyword).filter(Keyword.user
- != self.u),
- self.session.query(Keyword).
- filter(not_(Keyword.user_keyword.has(user=self.u))))
- def test_filter_eq_null_nul_nul(self):
- UserKeyword, Keyword = self.classes.UserKeyword, self.classes.Keyword
- self._equivalent(self.session.query(Keyword).filter(Keyword.user
- == None),
- self.session.query(Keyword).
- filter(Keyword.user_keyword.has(UserKeyword.user
- == None)))
- def test_filter_scalar_contains_fails_nul_nul(self):
- Keyword = self.classes.Keyword
- assert_raises(exceptions.InvalidRequestError, lambda : \
- Keyword.user.contains(self.u))
- def test_filter_scalar_any_fails_nul_nul(self):
- Keyword = self.classes.Keyword
- assert_raises(exceptions.InvalidRequestError, lambda : \
- Keyword.user.any(name='user2'))
- def test_filter_collection_has_fails_ul_nul(self):
- User = self.classes.User
- assert_raises(exceptions.InvalidRequestError, lambda : \
- User.keywords.has(keyword='quick'))
- def test_filter_collection_eq_fails_ul_nul(self):
- User = self.classes.User
- assert_raises(exceptions.InvalidRequestError, lambda : \
- User.keywords == self.kw)
- def test_filter_collection_ne_fails_ul_nul(self):
- User = self.classes.User
- assert_raises(exceptions.InvalidRequestError, lambda : \
- User.keywords != self.kw)
- def test_join_separate_attr(self):
- User = self.classes.User
- self.assert_compile(
- self.session.query(User).join(
- User.keywords.local_attr,
- User.keywords.remote_attr),
- "SELECT users.id AS users_id, users.name AS users_name, "
- "users.singular_id AS users_singular_id "
- "FROM users JOIN userkeywords ON users.id = "
- "userkeywords.user_id JOIN keywords ON keywords.id = "
- "userkeywords.keyword_id"
- )
- def test_join_single_attr(self):
- User = self.classes.User
- self.assert_compile(
- self.session.query(User).join(
- *User.keywords.attr),
- "SELECT users.id AS users_id, users.name AS users_name, "
- "users.singular_id AS users_singular_id "
- "FROM users JOIN userkeywords ON users.id = "
- "userkeywords.user_id JOIN keywords ON keywords.id = "
- "userkeywords.keyword_id"
- )
- class DictOfTupleUpdateTest(fixtures.TestBase):
- def setup(self):
- class B(object):
- def __init__(self, key, elem):
- self.key = key
- self.elem = elem
- class A(object):
- elements = association_proxy("orig", "elem", creator=B)
- m = MetaData()
- a = Table('a', m, Column('id', Integer, primary_key=True))
- b = Table('b', m, Column('id', Integer, primary_key=True),
- Column('aid', Integer, ForeignKey('a.id')))
- mapper(A, a, properties={
- 'orig':relationship(B, collection_class=attribute_mapped_collection('key'))
- })
- mapper(B, b)
- self.A = A
- self.B = B
- def test_update_one_elem_dict(self):
- a1 = self.A()
- a1.elements.update({("B", 3): 'elem2'})
- eq_(a1.elements, {("B",3):'elem2'})
- def test_update_multi_elem_dict(self):
- a1 = self.A()
- a1.elements.update({("B", 3): 'elem2', ("C", 4): "elem3"})
- eq_(a1.elements, {("B",3):'elem2', ("C", 4): "elem3"})
- def test_update_one_elem_list(self):
- a1 = self.A()
- a1.elements.update([(("B", 3), 'elem2')])
- eq_(a1.elements, {("B",3):'elem2'})
- def test_update_multi_elem_list(self):
- a1 = self.A()
- a1.elements.update([(("B", 3), 'elem2'), (("C", 4), "elem3")])
- eq_(a1.elements, {("B",3):'elem2', ("C", 4): "elem3"})
- def test_update_one_elem_varg(self):
- a1 = self.A()
- assert_raises_message(
- ValueError,
- "dictionary update sequence requires "
- "2-element tuples",
- a1.elements.update, (("B", 3), 'elem2')
- )
- def test_update_multi_elem_varg(self):
- a1 = self.A()
- assert_raises_message(
- TypeError,
- "update expected at most 1 arguments, got 2",
- a1.elements.update,
- (("B", 3), 'elem2'), (("C", 4), "elem3")
- )