diff options
Diffstat (limited to 'test/orm/test_inspect.py')
-rw-r--r-- | test/orm/test_inspect.py | 370 |
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) -""" |