summaryrefslogtreecommitdiff
path: root/test/orm/test_inspect.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/orm/test_inspect.py')
-rw-r--r--test/orm/test_inspect.py370
1 files changed, 233 insertions, 137 deletions
diff --git a/test/orm/test_inspect.py b/test/orm/test_inspect.py
index 3c824d849..9973c31c2 100644
--- a/test/orm/test_inspect.py
+++ b/test/orm/test_inspect.py
@@ -1,11 +1,12 @@
"""test the inspection registry system."""
-from test.lib.testing import eq_, assert_raises
+from test.lib.testing import eq_, assert_raises, is_
from sqlalchemy import exc, util
from sqlalchemy import inspect
from test.orm import _fixtures
-from sqlalchemy.orm import class_mapper, synonym
-from sqlalchemy.orm.attributes import instance_state
+from sqlalchemy.orm import class_mapper, synonym, Session
+from sqlalchemy.orm.attributes import instance_state, NO_VALUE
+from test.lib import testing
class TestORMInspection(_fixtures.FixtureTest):
@classmethod
@@ -26,169 +27,264 @@ class TestORMInspection(_fixtures.FixtureTest):
assert inspect(u1) is instance_state(u1)
- def test_synonyms(self):
+ def test_column_collection_iterate(self):
User = self.classes.User
- syn = inspect(User).synonyms
-
- # TODO: some of the synonym debacle in 0.7
- # has led User.name_syn.property to be the
- # ColumnProperty. not sure if we want that
- # implicit jump in there though, perhaps get Query/etc. to
- # call upon "effective_property" or something like that
-
- eq_(inspect(User).synonyms, {
- "name_syn":class_mapper(User).get_property("name_syn")
- })
-
- # TODO: test all these accessors...
-
-"""
-# column collection
->>> b.columns
-[<id column>, <name column>]
-
-# its a ColumnCollection
->>> b.columns.id
-<id column>
-
-# i.e. from mapper
->>> b.primary_key
-(<id column>, )
-
-# i.e. from mapper
->>> b.local_table
-<user table>
-
-# ColumnProperty
->>> b.attr.id.columns
-[<id column>]
-
-# but perhaps we use a collection with some helpers
->>> b.attr.id.columns.first
-<id column>
-
-# and a mapper? its None since this is a column
->>> b.attr.id.mapper
-None
-
-# attr is basically the _props
->>> b.attr.keys()
-['id', 'name', 'name_syn', 'addresses']
-
-# b itself is likely just the mapper
->>> b
-<User mapper>
+ user_table = self.tables.users
+ insp = inspect(User)
+ eq_(
+ list(insp.columns),
+ [user_table.c.id, user_table.c.name]
+ )
+ is_(
+ insp.columns.id, user_table.c.id
+ )
-# get only column attributes
->>> b.column_attrs
-[<id prop>, <name prop>]
+ def test_primary_key(self):
+ User = self.classes.User
+ user_table = self.tables.users
+ insp = inspect(User)
+ eq_(insp.primary_key,
+ (user_table.c.id,)
+ )
-# its a namespace
->>> b.column_attrs.id
-<id prop>
+ def test_local_table(self):
+ User = self.classes.User
+ user_table = self.tables.users
+ insp = inspect(User)
+ is_(insp.local_table, user_table)
-# get only synonyms
->>> b.synonyms
-[<name syn prop>]
+ def test_property(self):
+ User = self.classes.User
+ user_table = self.tables.users
+ insp = inspect(User)
+ is_(insp.attr.id, class_mapper(User).get_property('id'))
-# get only relationships
->>> b.relationships
-[<addresses prop>]
+ def test_col_property(self):
+ User = self.classes.User
+ user_table = self.tables.users
+ insp = inspect(User)
+ id_prop = insp.attr.id
-# its a namespace
->>> b.relationships.addresses
-<addresses prop>
+ eq_(id_prop.columns, [user_table.c.id])
+ is_(id_prop.expression, user_table.c.id)
-# point inspect() at a class level attribute,
-# basically returns ".property"
->>> b = inspect(User.addresses)
->>> b
-<addresses prop>
+ assert not hasattr(id_prop, 'mapper')
-# mapper
->>> b.mapper
-<Address mapper>
+ def test_attr_keys(self):
+ User = self.classes.User
+ insp = inspect(User)
+ eq_(
+ set(insp.attr.keys()),
+ set(['addresses', 'orders', 'id', 'name', 'name_syn'])
+ )
-# None columns collection, just like columnprop has empty mapper
->>> b.columns
-None
+ def test_col_filter(self):
+ User = self.classes.User
+ insp = inspect(User)
+ eq_(
+ list(insp.column_attrs),
+ [insp.get_property('id'), insp.get_property('name')]
+ )
+ eq_(
+ insp.column_attrs.keys(),
+ ['id', 'name']
+ )
+ is_(
+ insp.column_attrs.id,
+ User.id.property
+ )
-# the parent
->>> b.parent
-<User mapper>
+ def test_synonym_filter(self):
+ User = self.classes.User
+ syn = inspect(User).synonyms
-# __clause_element__()
->>> b.expression
-User.id==Address.user_id
+ eq_(
+ list(syn.keys()), ['name_syn']
+ )
+ is_(syn.name_syn, User.name_syn.original_property)
+ eq_(dict(syn), {
+ "name_syn":User.name_syn.original_property
+ })
->>> inspect(User.id).expression
-<id column with ORM annotations>
+ def test_relationship_filter(self):
+ User = self.classes.User
+ rel = inspect(User).relationships
+ eq_(
+ rel.addresses,
+ User.addresses.property
+ )
+ eq_(
+ set(rel.keys()),
+ set(['orders', 'addresses'])
+ )
-# inspect works on instances !
->>> u1 = User(id=3, name='x')
->>> b = inspect(u1)
+ def test_insp_prop(self):
+ User = self.classes.User
+ prop = inspect(User.addresses)
+ is_(prop, User.addresses.property)
-# what's b here ? probably InstanceState
->>> b
-<InstanceState>
+ def test_rel_accessors(self):
+ User = self.classes.User
+ Address = self.classes.Address
+ prop = inspect(User.addresses)
+ is_(prop.parent, class_mapper(User))
+ is_(prop.mapper, class_mapper(Address))
->>> b.attr.keys()
-['id', 'name', 'name_syn', 'addresses']
+ assert not hasattr(prop, 'columns')
+ assert not hasattr(prop, 'expression')
-# this is class level stuff - should this require b.mapper.columns ?
->>> b.columns
-[<id column>, <name column>]
+ def test_instance_state(self):
+ User = self.classes.User
+ u1 = User()
+ insp = inspect(u1)
+ is_(insp, instance_state(u1))
-# does this return '3'? or an object?
->>> b.attr.id
-<magic attribute inspect thing>
+ def test_instance_state_attr(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
-# or does this ?
->>> b.attr.id.value
-3
+ eq_(
+ set(insp.attr.keys()),
+ set(['id', 'name', 'name_syn', 'addresses', 'orders'])
+ )
+ eq_(
+ insp.attr.name.value,
+ 'ed'
+ )
+ eq_(
+ insp.attr.name.loaded_value,
+ 'ed'
+ )
->>> b.attr.id.history
-<history object>
+ def test_instance_state_attr_passive_value_scalar(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
+ # value was not set, NO_VALUE
+ eq_(
+ insp.attr.id.loaded_value,
+ NO_VALUE
+ )
+ # regular accessor sets it
+ eq_(
+ insp.attr.id.value,
+ None
+ )
+ # now the None is there
+ eq_(
+ insp.attr.id.loaded_value,
+ None
+ )
->>> b.attr.id.history.unchanged
-3
+ def test_instance_state_attr_passive_value_collection(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
+ # value was not set, NO_VALUE
+ eq_(
+ insp.attr.addresses.loaded_value,
+ NO_VALUE
+ )
+ # regular accessor sets it
+ eq_(
+ insp.attr.addresses.value,
+ []
+ )
+ # now the None is there
+ eq_(
+ insp.attr.addresses.loaded_value,
+ []
+ )
->>> b.attr.id.history.deleted
-None
+ def test_instance_state_attr_hist(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
+ hist = insp.attr.addresses.history
+ eq_(
+ hist.unchanged, None
+ )
+ u1.addresses
+ hist = insp.attr.addresses.history
+ eq_(
+ hist.unchanged, []
+ )
-# lets assume the object is persistent
->>> s = Session()
->>> s.add(u1)
->>> s.commit()
+ def test_instance_state_ident_transient(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
+ is_(insp.identity, None)
-# big one - the primary key identity ! always
-# works in query.get()
->>> b.identity
-[3]
+ def test_instance_state_ident_persistent(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ s = Session(testing.db)
+ s.add(u1)
+ s.flush()
+ insp = inspect(u1)
+ eq_(insp.identity, (u1.id,))
+ is_(s.query(User).get(insp.identity), u1)
+
+ def test_identity_key(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ s = Session(testing.db)
+ s.add(u1)
+ s.flush()
+ insp = inspect(u1)
+ eq_(
+ insp.identity_key,
+ (User, (11, ))
+ )
-# the mapper level key
->>> b.identity_key
-(User, [3])
+ def test_persistence_states(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
->>> b.persistent
-True
+ eq_(
+ (insp.transient, insp.pending,
+ insp.persistent, insp.detached),
+ (True, False, False, False)
+ )
+ s = Session(testing.db)
+ s.add(u1)
->>> b.transient
-False
+ eq_(
+ (insp.transient, insp.pending,
+ insp.persistent, insp.detached),
+ (False, True, False, False)
+ )
->>> b.deleted
-False
+ s.flush()
+ eq_(
+ (insp.transient, insp.pending,
+ insp.persistent, insp.detached),
+ (False, False, True, False)
+ )
+ s.expunge(u1)
+ eq_(
+ (insp.transient, insp.pending,
+ insp.persistent, insp.detached),
+ (False, False, False, True)
+ )
->>> b.detached
-False
+ def test_session_accessor(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
->>> b.session
-<session>
+ is_(insp.session, None)
+ s = Session()
+ s.add(u1)
+ is_(insp.session, s)
-# the object. this navigates obj()
-# of course, would be nice if it was b.obj...
->>> b.object_
-<User instance u1>
+ def test_object_accessor(self):
+ User = self.classes.User
+ u1 = User(name='ed')
+ insp = inspect(u1)
+ is_(insp.object, u1)
-"""