diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-16 17:29:02 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-16 17:29:02 -0400 |
| commit | ce9a702dbd52946487f45b98ef20d1b7783facb6 (patch) | |
| tree | 7273a1982850bf9975509295d766053d4fe822b1 /test | |
| parent | 1dc09bf6ede97ef08b2c8c0886a03b44bba735ff (diff) | |
| download | sqlalchemy-ce9a702dbd52946487f45b98ef20d1b7783facb6.tar.gz | |
- express most of the orm.util functions in terms of the inspection system
- modify inspection system:
1. raise a new exception for any case where the inspection
context can't be returned. this supersedes the "not mapped"
errors.
2. don't configure mappers on a mapper inspection. this allows
the inspectors to be used during mapper config time. instead,
the mapper configures on "with_polymorphic_selectable" now,
which is needed for all queries
- add a bunch of new "is_XYZ" attributes to inspectors
- finish making the name change of "compile" -> "configure", for some reason
this was only done partially
Diffstat (limited to 'test')
| -rw-r--r-- | test/base/test_inspect.py | 15 | ||||
| -rw-r--r-- | test/ext/test_hybrid.py | 6 | ||||
| -rw-r--r-- | test/orm/test_inspect.py | 77 | ||||
| -rw-r--r-- | test/orm/test_mapper.py | 142 |
4 files changed, 166 insertions, 74 deletions
diff --git a/test/base/test_inspect.py b/test/base/test_inspect.py index 1e16fa4aa..c5a60481b 100644 --- a/test/base/test_inspect.py +++ b/test/base/test_inspect.py @@ -1,6 +1,6 @@ """test the inspection registry system.""" -from test.lib.testing import eq_, assert_raises +from test.lib.testing import eq_, assert_raises_message from sqlalchemy import exc, util from sqlalchemy import inspection, inspect from test.lib import fixtures @@ -8,8 +8,7 @@ from test.lib import fixtures class TestFixture(object): pass -class TestEvents(fixtures.TestBase): - """Test class- and instance-level event registration.""" +class TestInspection(fixtures.TestBase): def tearDown(self): for type_ in list(inspection._registrars): @@ -28,6 +27,16 @@ class TestEvents(fixtures.TestBase): insp = inspect(somefoo) assert insp["insp"] is somefoo + def test_no_inspect(self): + class SomeFoo(TestFixture): + pass + + assert_raises_message( + exc.NoInspectionAvailable, + "No inspection system is available for object of type ", + inspect, SomeFoo + ) + def test_class_insp(self): class SomeFoo(TestFixture): pass diff --git a/test/ext/test_hybrid.py b/test/ext/test_hybrid.py index b85d4b0fc..77966e6e5 100644 --- a/test/ext/test_hybrid.py +++ b/test/ext/test_hybrid.py @@ -62,7 +62,7 @@ class PropertyComparatorTest(fixtures.TestBase, AssertsCompiledSQL): "SELECT a.value AS a_value FROM a" ) - def test_alised_query(self): + def test_aliased_query(self): A = self._fixture() sess = Session() self.assert_compile( @@ -214,7 +214,7 @@ class PropertyValueTest(fixtures.TestBase, AssertsCompiledSQL): A = self._fixture(False) a1 = A(_value=5) assert_raises_message( - AttributeError, + AttributeError, "can't set attribute", setattr, a1, 'value', 10 ) @@ -223,7 +223,7 @@ class PropertyValueTest(fixtures.TestBase, AssertsCompiledSQL): A = self._fixture(False) a1 = A(_value=5) assert_raises_message( - AttributeError, + AttributeError, "can't delete attribute", delattr, a1, 'value' ) diff --git a/test/orm/test_inspect.py b/test/orm/test_inspect.py index 70002ee28..128539e68 100644 --- a/test/orm/test_inspect.py +++ b/test/orm/test_inspect.py @@ -1,10 +1,10 @@ """test the inspection registry system.""" -from test.lib.testing import eq_, assert_raises, is_ +from test.lib.testing import eq_, assert_raises_message, is_ from sqlalchemy import exc, util from sqlalchemy import inspect from test.orm import _fixtures -from sqlalchemy.orm import class_mapper, synonym, Session +from sqlalchemy.orm import class_mapper, synonym, Session, aliased from sqlalchemy.orm.attributes import instance_state, NO_VALUE from test.lib import testing @@ -21,11 +21,6 @@ class TestORMInspection(_fixtures.FixtureTest): assert inspect(User) is class_mapper(User) - def test_instance_state(self): - User = self.classes.User - u1 = User() - - assert inspect(u1) is instance_state(u1) def test_column_collection_iterate(self): User = self.classes.User @@ -43,7 +38,7 @@ class TestORMInspection(_fixtures.FixtureTest): User = self.classes.User user_table = self.tables.users insp = inspect(User) - eq_(insp.primary_key, + eq_(insp.primary_key, (user_table.c.id,) ) @@ -53,12 +48,59 @@ class TestORMInspection(_fixtures.FixtureTest): insp = inspect(User) is_(insp.local_table, user_table) - def test_property(self): + def test_mapped_table(self): + User = self.classes.User + user_table = self.tables.users + insp = inspect(User) + is_(insp.mapped_table, user_table) + + def test_mapper_selectable(self): User = self.classes.User user_table = self.tables.users insp = inspect(User) + is_(insp.selectable, user_table) + assert not insp.is_selectable + assert not insp.is_aliased_class + + def test_aliased_class(self): + Address = self.classes.Address + ualias = aliased(Address) + insp = inspect(ualias) + is_(insp.mapper, inspect(Address)) + is_(insp.selectable, ualias._AliasedClass__alias) + assert not insp.is_selectable + assert insp.is_aliased_class + + def test_not_mapped_class(self): + class Foo(object): + pass + + assert_raises_message( + exc.NoInspectionAvailable, + "No inspection system is available for object of type", + inspect, Foo + ) + + def test_not_mapped_instance(self): + class Foo(object): + pass + + assert_raises_message( + exc.NoInspectionAvailable, + "No inspection system is available for object of type", + inspect, Foo() + ) + + def test_property(self): + User = self.classes.User + insp = inspect(User) is_(insp.attr.id, class_mapper(User).get_property('id')) + def test_with_polymorphic(self): + User = self.classes.User + insp = inspect(User) + eq_(insp.with_polymorphic_mappers, [insp]) + def test_col_property(self): User = self.classes.User user_table = self.tables.users @@ -74,7 +116,7 @@ class TestORMInspection(_fixtures.FixtureTest): User = self.classes.User insp = inspect(User) eq_( - set(insp.attr.keys()), + set(insp.attr.keys()), set(['addresses', 'orders', 'id', 'name', 'name_syn']) ) @@ -115,7 +157,7 @@ class TestORMInspection(_fixtures.FixtureTest): User.addresses.property ) eq_( - set(rel.keys()), + set(rel.keys()), set(['orders', 'addresses']) ) @@ -134,6 +176,7 @@ class TestORMInspection(_fixtures.FixtureTest): assert not hasattr(prop, 'columns') assert not hasattr(prop, 'expression') + def test_instance_state(self): User = self.classes.User u1 = User() @@ -228,6 +271,18 @@ class TestORMInspection(_fixtures.FixtureTest): eq_(insp.identity, (u1.id,)) is_(s.query(User).get(insp.identity), u1) + def test_is_instance(self): + User = self.classes.User + u1 = User(name='ed') + insp = inspect(u1) + assert insp.is_instance + + insp = inspect(User) + assert not insp.is_instance + + insp = inspect(aliased(User)) + assert not insp.is_instance + def test_identity_key(self): User = self.classes.User u1 = User(name='ed') diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index 78a1c29a4..89f20362d 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -55,6 +55,8 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): def test_utils(self): users = self.tables.users + addresses = self.tables.addresses + Address = self.classes.Address from sqlalchemy.orm.util import _is_mapped_class, _is_aliased_class @@ -63,7 +65,10 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): @property def y(self): return "somethign else" - m = mapper(Foo, users) + + + m = mapper(Foo, users, properties={"addresses":relationship(Address)}) + mapper(Address, addresses) a1 = aliased(Foo) f = Foo() @@ -71,6 +76,8 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): for fn, arg, ret in [ (_is_mapped_class, Foo.x, False), (_is_mapped_class, Foo.y, False), + (_is_mapped_class, Foo.name, False), + (_is_mapped_class, Foo.addresses, False), (_is_mapped_class, Foo, True), (_is_mapped_class, f, False), (_is_mapped_class, a1, True), @@ -85,7 +92,28 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): ]: assert fn(arg) == ret + def test_entity_descriptor(self): + users = self.tables.users + + from sqlalchemy.orm.util import _entity_descriptor + + class Foo(object): + x = "something" + @property + def y(self): + return "somethign else" + m = mapper(Foo, users) + a1 = aliased(Foo) + + f = Foo() + for arg, key, ret in [ + (m, "x", Foo.x), + (Foo, "x", Foo.x), + (a1, "x", a1.x), + (users, "name", users.c.name) + ]: + assert _entity_descriptor(arg, key) is ret def test_friendly_attribute_str_on_uncompiled_boom(self): User, users = self.classes.User, self.tables.users @@ -96,13 +124,13 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): 'addresses':relationship(boom) }) - # test that QueryableAttribute.__str__() doesn't + # test that QueryableAttribute.__str__() doesn't # cause a compile. eq_(str(User.addresses), "User.addresses") def test_exceptions_sticky(self): """test preservation of mapper compile errors raised during hasattr(), - as well as for redundant mapper compile calls. Test that + as well as for redundant mapper compile calls. Test that repeated calls don't stack up error messages. """ @@ -157,7 +185,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): assert_raises(sa.exc.ArgumentError, mapper, User, s) def test_reconfigure_on_other_mapper(self): - """A configure trigger on an already-configured mapper + """A configure trigger on an already-configured mapper still triggers a check against all mappers.""" users, Address, addresses, User = (self.tables.users, @@ -211,7 +239,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): : addresses.c.user_id}) def test_constructor_exc(self): - """TypeError is raised for illegal constructor args, + """TypeError is raised for illegal constructor args, whether or not explicit __init__ is present [ticket:908].""" users, addresses = self.tables.users, self.tables.addresses @@ -229,7 +257,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): assert_raises(TypeError, Bar, x=5) def test_sort_states_comparisons(self): - """test that _sort_states() doesn't compare + """test that _sort_states() doesn't compare insert_order to state.key, for set of mixed persistent/pending. In particular Python 3 disallows this. @@ -239,7 +267,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): def __init__(self, id): self.id = id m = MetaData() - foo_t = Table('foo', m, + foo_t = Table('foo', m, Column('id', String, primary_key=True) ) m = mapper(Foo, foo_t) @@ -500,7 +528,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): ) def test_column_prop_deannotate(self): - """test that column property deannotates, + """test that column property deannotates, bringing expressions down to the original mapped columns. """ User, users = self.classes.User, self.tables.users @@ -514,7 +542,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): assert User.x.property.columns[0] is not expr assert User.x.property.columns[0].element.left is users.c.name - # a deannotate needs to clone the base, in case + # a deannotate needs to clone the base, in case # the original one referenced annotated elements. assert User.x.property.columns[0].element.right is not expr.right @@ -587,7 +615,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): class AddressUser(User): pass m1 = mapper(User, users, polymorphic_identity='user') - m2 = mapper(AddressUser, addresses, inherits=User, + m2 = mapper(AddressUser, addresses, inherits=User, polymorphic_identity='address') m3 = mapper(AddressUser, addresses, non_primary=True) assert m3._identity_class is m2._identity_class @@ -632,7 +660,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): class Sub(Base): pass mapper(Base, users) - assert_raises_message(sa.exc.InvalidRequestError, + assert_raises_message(sa.exc.InvalidRequestError, "Configure a primary mapper first", mapper, Sub, addresses, non_primary=True ) @@ -660,7 +688,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): pass class Empty(object):pass - empty = mapper(Empty, t, properties={'empty_id' : t.c.id}, + empty = mapper(Empty, t, properties={'empty_id' : t.c.id}, include_properties=[]) p_m = mapper(Person, t, polymorphic_on=t.c.type, include_properties=('id', 'type', 'name')) @@ -698,7 +726,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): want = set(want) eq_(have, want) - assert_props(HasDef, ['h_boss_id', 'h_employee_number', 'h_id', + assert_props(HasDef, ['h_boss_id', 'h_employee_number', 'h_id', 'name', 'h_name', 'h_vendor_id', 'h_type']) assert_props(Person, ['id', 'name', 'type']) assert_instrumented(Person, ['id', 'name', 'type']) @@ -719,7 +747,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): assert_props(Frob, ['f_id', 'f_type', 'f_name', ]) - # putting the discriminator column in exclude_properties, + # putting the discriminator column in exclude_properties, # very weird. As of 0.7.4 this re-maps it. class Foo(Person): pass @@ -835,8 +863,8 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): self.tables.addresses, self.classes.Address) - m = mapper(Address, - addresses.join(email_bounces), + m = mapper(Address, + addresses.join(email_bounces), properties={'id':[addresses.c.id, email_bounces.c.id]} ) configure_mappers() @@ -1285,8 +1313,8 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): eq_(User.uc_name.method2('x'), "method2") assert_raises_message( - AttributeError, - "Neither 'extendedproperty' object nor 'UCComparator' object has an attribute 'nonexistent'", + AttributeError, + "Neither 'extendedproperty' object nor 'UCComparator' object has an attribute 'nonexistent'", getattr, User.uc_name, 'nonexistent') # test compile @@ -1332,8 +1360,8 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): }) assert_raises_message( - AttributeError, - "Neither 'InstrumentedAttribute' object nor 'MyComparator' object has an attribute 'nonexistent'", + AttributeError, + "Neither 'InstrumentedAttribute' object nor 'MyComparator' object has an attribute 'nonexistent'", getattr, User.name, "nonexistent") eq_(str((User.name == 'ed').compile(dialect=sa.engine.default.DefaultDialect())) , "lower(users.name) = lower(:lower_1)") @@ -1458,13 +1486,13 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): }) assert_raises_message( - sa.orm.exc.UnmappedClassError, + sa.orm.exc.UnmappedClassError, "Class 'test.orm._fixtures.Address' is not mapped", sa.orm.configure_mappers) def test_unmapped_not_type_error(self): assert_raises_message( - sa.exc.ArgumentError, + sa.exc.ArgumentError, "Class object expected, got '5'.", class_mapper, 5 ) @@ -1561,8 +1589,8 @@ class DocumentTest(fixtures.TestBase): pass mapper(Foo, t1, properties={ - 'bars':relationship(Bar, - doc="bar relationship", + 'bars':relationship(Bar, + doc="bar relationship", backref=backref('foo',doc='foo relationship') ), 'foober':column_property(t1.c.col3, doc='alternate data col'), @@ -1699,7 +1727,7 @@ class OptionsTest(_fixtures.FixtureTest): self.sql_count_(1, go) def test_eager_degrade(self): - """An eager relationship automatically degrades to a lazy relationship + """An eager relationship automatically degrades to a lazy relationship if eager columns are not available""" Address, addresses, users, User = (self.classes.Address, @@ -1708,7 +1736,7 @@ class OptionsTest(_fixtures.FixtureTest): self.classes.User) mapper(User, users, properties=dict( - addresses = relationship(mapper(Address, addresses), + addresses = relationship(mapper(Address, addresses), lazy='joined', order_by=addresses.c.id))) sess = create_session() @@ -1990,7 +2018,7 @@ class ValidatorTest(_fixtures.FixtureTest): sess.flush() sess.expunge_all() eq_( - sess.query(User).filter_by(name='edward').one(), + sess.query(User).filter_by(name='edward').one(), User(name='edward', addresses=[Address(email_address='foo@bar.com')]) ) @@ -2021,7 +2049,7 @@ class ValidatorTest(_fixtures.FixtureTest): eq_( dict((k, v[0].__name__) for k, v in u_m.validators.items()), - {'name':'validate_name', + {'name':'validate_name', 'addresses':'validate_address'} ) @@ -2058,20 +2086,20 @@ class ValidatorTest(_fixtures.FixtureTest): u1.addresses = [a2, a3] eq_(canary, [ - ('name', 'ed', False), - ('name', 'mary', False), - ('name', 'mary', True), + ('name', 'ed', False), + ('name', 'mary', False), + ('name', 'mary', True), # append a1 - ('addresses', a1, False), + ('addresses', a1, False), # remove a1 - ('addresses', a1, True), + ('addresses', a1, True), # set to [a1, a2] - this is two appends ('addresses', a1, False), ('addresses', a2, False), # set to [a2, a3] - this is a remove of a1, # append of a3. the appends are first. ('addresses', a3, False), - ('addresses', a1, True), - ] + ('addresses', a1, True), + ] ) class ComparatorFactoryTest(_fixtures.FixtureTest, AssertsCompiledSQL): @@ -2129,12 +2157,12 @@ class ComparatorFactoryTest(_fixtures.FixtureTest, AssertsCompiledSQL): comparator_factory=MyFactory) }) self.assert_compile( - User.name == 'ed', + User.name == 'ed', "foobar(users.name) = foobar(:foobar_1)", dialect=default.DefaultDialect()) self.assert_compile( - aliased(User).name == 'ed', + aliased(User).name == 'ed', "foobar(users_1.name) = foobar(:foobar_1)", dialect=default.DefaultDialect()) @@ -2158,7 +2186,7 @@ class ComparatorFactoryTest(_fixtures.FixtureTest, AssertsCompiledSQL): mapper(User, users) mapper(Address, addresses, properties={ - 'user':relationship(User, comparator_factory=MyFactory, + 'user':relationship(User, comparator_factory=MyFactory, backref=backref("addresses", comparator_factory=MyFactory2) ) } @@ -2466,9 +2494,9 @@ class DeferredTest(_fixtures.FixtureTest): order_select = sa.select([ - orders.c.id, - orders.c.user_id, - orders.c.address_id, + orders.c.id, + orders.c.user_id, + orders.c.address_id, orders.c.description, orders.c.isopen]).alias() mapper(Order, order_select, properties={ @@ -2523,7 +2551,7 @@ class SecondaryOptionsTest(fixtures.MappedTest): @classmethod def define_tables(cls, metadata): - Table("base", metadata, + Table("base", metadata, Column('id', Integer, primary_key=True), Column('type', String(50), nullable=False) ) @@ -2556,11 +2584,11 @@ class SecondaryOptionsTest(fixtures.MappedTest): mapper(Base, base, polymorphic_on=base.c.type, properties={ 'related':relationship(Related, uselist=False) }) - mapper(Child1, child1, inherits=Base, - polymorphic_identity='child1', + mapper(Child1, child1, inherits=Base, + polymorphic_identity='child1', properties={ - 'child2':relationship(Child2, - primaryjoin=child1.c.child2id==base.c.id, + 'child2':relationship(Child2, + primaryjoin=child1.c.child2id==base.c.id, foreign_keys=child1.c.child2id) }) mapper(Child2, child2, inherits=Base, polymorphic_identity='child2') @@ -2614,18 +2642,18 @@ class SecondaryOptionsTest(fixtures.MappedTest): eq_( child1s.all(), [ - Child1(id=1, related=Related(id=1)), - Child1(id=2, related=Related(id=2)), + Child1(id=1, related=Related(id=1)), + Child1(id=2, related=Related(id=2)), Child1(id=3, related=Related(id=3)) ] ) self.assert_sql_count(testing.db, go, 1) c1 = child1s[0] - + self.assert_sql_execution( - testing.db, - lambda: c1.child2, + testing.db, + lambda: c1.child2, CompiledSQL( "SELECT child2.id AS child2_id, base.id AS base_id, base.type AS base_type " "FROM base JOIN child2 ON base.id = child2.id " @@ -2651,8 +2679,8 @@ class SecondaryOptionsTest(fixtures.MappedTest): c1 = child1s[0] self.assert_sql_execution( - testing.db, - lambda: c1.child2, + testing.db, + lambda: c1.child2, CompiledSQL( "SELECT child2.id AS child2_id, base.id AS base_id, base.type AS base_type " "FROM base JOIN child2 ON base.id = child2.id WHERE base.id = :param_1", @@ -2685,8 +2713,8 @@ class SecondaryOptionsTest(fixtures.MappedTest): # this *does* joinedload self.assert_sql_execution( - testing.db, - lambda: c1.child2, + testing.db, + lambda: c1.child2, CompiledSQL( "SELECT child2.id AS child2_id, base.id AS base_id, base.type AS base_type, " "related_1.id AS related_1_id FROM base JOIN child2 ON base.id = child2.id " @@ -3027,8 +3055,8 @@ class RequirementsTest(fixtures.MappedTest): ]) s.commit() eq_( - [(h1.value, h1.id, h2.value, h2.id) - for h1, h2 in + [(h1.value, h1.id, h2.value, h2.id) + for h1, h2 in s.query(H1, H2).join(H1.h2s).order_by(H1.id, H2.id)], [ ('abc', 1, 'abc', 1), |
