diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-06-20 19:28:29 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-06-20 19:28:29 -0400 |
| commit | 3dd536ac06808adcf9c10707dbf2ebb6e3842be7 (patch) | |
| tree | d102291da86021aa4584ef836dbb0471596c3eeb /test | |
| parent | 40098941007ff3aa1593e834915c4042c1668dc2 (diff) | |
| download | sqlalchemy-3dd536ac06808adcf9c10707dbf2ebb6e3842be7.tar.gz | |
- [feature] The of_type() construct on attributes
now accepts aliased() class constructs as well
as with_polymorphic constructs, and works with
query.join(), any(), has(), and also
eager loaders subqueryload(), joinedload(),
contains_eager()
[ticket:2438] [ticket:1106]
- a rewrite of the query path system to use an
object based approach for more succinct usage. the system
has been designed carefully to not add an excessive method overhead.
- [feature] select() features a correlate_except()
method, auto correlates all selectables except those
passed. Is needed here for the updated any()/has()
functionality.
- remove some old cruft from LoaderStrategy, init(),debug_callable()
- use a namedtuple for _extended_entity_info. This method should
become standard within the orm internals
- some tweaks to the memory profile tests, number of runs can
be customized to work around pysqlite's very annoying behavior
- try to simplify PropertyOption._get_paths(), rename to _process_paths(),
returns a single list now. overall works more completely as was needed
for of_type() functionality
Diffstat (limited to 'test')
| -rw-r--r-- | test/aaa_profiling/test_memusage.py | 158 | ||||
| -rw-r--r-- | test/orm/inheritance/_poly_fixtures.py | 48 | ||||
| -rw-r--r-- | test/orm/inheritance/test_polymorphic_rel.py | 184 | ||||
| -rw-r--r-- | test/orm/test_merge.py | 6 | ||||
| -rw-r--r-- | test/orm/test_pickled.py | 14 | ||||
| -rw-r--r-- | test/orm/test_query.py | 90 | ||||
| -rw-r--r-- | test/orm/test_subquery_relations.py | 2 | ||||
| -rw-r--r-- | test/perf/orm2010.py | 4 |
8 files changed, 277 insertions, 229 deletions
diff --git a/test/aaa_profiling/test_memusage.py b/test/aaa_profiling/test_memusage.py index 26e7d193c..04cf82a15 100644 --- a/test/aaa_profiling/test_memusage.py +++ b/test/aaa_profiling/test_memusage.py @@ -1,6 +1,7 @@ from test.lib.testing import eq_ from sqlalchemy.orm import mapper, relationship, create_session, \ - clear_mappers, sessionmaker, class_mapper + clear_mappers, sessionmaker, class_mapper, aliased,\ + Session, subqueryload from sqlalchemy.orm.mapper import _mapper_registry from sqlalchemy.orm.session import _sessions import operator @@ -22,40 +23,44 @@ class A(fixtures.ComparableEntity): pass class B(fixtures.ComparableEntity): pass +class ASub(A): + pass -def profile_memory(func): - # run the test 50 times. if length of gc.get_objects() - # keeps growing, assert false +def profile_memory(times=50): + def decorate(func): + # run the test 50 times. if length of gc.get_objects() + # keeps growing, assert false - def profile(*args): - gc_collect() - samples = [0 for x in range(0, 50)] - for x in range(0, 50): - func(*args) + def profile(*args): gc_collect() - samples[x] = len(gc.get_objects()) - - print "sample gc sizes:", samples + samples = [0 for x in range(0, times)] + for x in range(0, times): + func(*args) + gc_collect() + samples[x] = len(gc.get_objects()) - assert len(_sessions) == 0 + print "sample gc sizes:", samples - for x in samples[-4:]: - if x != samples[-5]: - flatline = False - break - else: - flatline = True + assert len(_sessions) == 0 - # object count is bigger than when it started - if not flatline and samples[-1] > samples[0]: - for x in samples[1:-2]: - # see if a spike bigger than the endpoint exists - if x > samples[-1]: + for x in samples[-4:]: + if x != samples[-5]: + flatline = False break else: - assert False, repr(samples) + " " + repr(flatline) + flatline = True - return profile + # object count is bigger than when it started + if not flatline and samples[-1] > samples[0]: + for x in samples[1:-2]: + # see if a spike bigger than the endpoint exists + if x > samples[-1]: + break + else: + assert False, repr(samples) + " " + repr(flatline) + + return profile + return decorate def assert_no_mappers(): clear_mappers() @@ -78,7 +83,7 @@ class MemUsageTest(EnsureZeroed): pass x = [] - @profile_memory + @profile_memory() def go(): x[-1:] = [Foo(), Foo(), Foo(), Foo(), Foo(), Foo()] go() @@ -107,7 +112,7 @@ class MemUsageTest(EnsureZeroed): m3 = mapper(A, table1, non_primary=True) - @profile_memory + @profile_memory() def go(): sess = create_session() a1 = A(col2="a1") @@ -168,7 +173,7 @@ class MemUsageTest(EnsureZeroed): m3 = mapper(A, table1, non_primary=True) - @profile_memory + @profile_memory() def go(): engine = engines.testing_engine( options={'logging_name':'FOO', @@ -227,7 +232,7 @@ class MemUsageTest(EnsureZeroed): (postgresql.INTERVAL, ), (mysql.VARCHAR, ), ): - @profile_memory + @profile_memory() def go(): type_ = args[0](*args[1:]) bp = type_._cached_bind_processor(eng.dialect) @@ -260,7 +265,7 @@ class MemUsageTest(EnsureZeroed): del session counter = [1] - @profile_memory + @profile_memory() def go(): session = create_session() w1 = session.query(Wide).first() @@ -282,11 +287,6 @@ class MemUsageTest(EnsureZeroed): finally: metadata.drop_all() - @testing.fails_if(lambda : testing.db.dialect.name == 'sqlite' \ - and testing.db.dialect.dbapi.version_info >= (2, - 5), - 'Newer pysqlites generate warnings here too and ' - 'have similar issues.') def test_unicode_warnings(self): metadata = MetaData(testing.db) table1 = Table('mytable', metadata, Column('col1', Integer, @@ -296,8 +296,11 @@ class MemUsageTest(EnsureZeroed): metadata.create_all() i = [1] + # the times here is cranked way up so that we can see + # pysqlite clearing out it's internal buffer and allow + # the test to pass @testing.emits_warning() - @profile_memory + @profile_memory(times=220) def go(): # execute with a non-unicode object. a warning is emitted, @@ -325,7 +328,7 @@ class MemUsageTest(EnsureZeroed): Column('col2', String(30)), Column('col3', Integer, ForeignKey("mytable.col1"))) - @profile_memory + @profile_memory() def go(): m1 = mapper(A, table1, properties={ "bs":relationship(B, order_by=table2.c.col1) @@ -368,6 +371,69 @@ class MemUsageTest(EnsureZeroed): metadata.drop_all() assert_no_mappers() + def test_alias_pathing(self): + metadata = MetaData(testing.db) + + a = Table("a", metadata, + Column('id', Integer, primary_key=True, + test_needs_autoincrement=True), + Column('bid', Integer, ForeignKey('b.id')), + Column('type', String(30)) + ) + + asub = Table("asub", metadata, + Column('id', Integer, ForeignKey('a.id'), + primary_key=True), + Column('data', String(30))) + + b = Table("b", metadata, + Column('id', Integer, primary_key=True, + test_needs_autoincrement=True), + ) + mapper(A, a, polymorphic_identity='a', + polymorphic_on=a.c.type) + mapper(ASub, asub, inherits=A,polymorphic_identity='asub') + m1 = mapper(B, b, properties={ + 'as_':relationship(A) + }) + + metadata.create_all() + sess = Session() + a1 = ASub(data="a1") + a2 = ASub(data="a2") + a3 = ASub(data="a3") + b1 = B(as_=[a1, a2, a3]) + sess.add(b1) + sess.commit() + del sess + + # sqlite has a slow enough growth here + # that we have to run it more times to see the + # "dip" again + @profile_memory(times=120) + def go(): + sess = Session() + sess.query(B).options(subqueryload(B.as_.of_type(ASub))).all() + sess.close() + try: + go() + finally: + metadata.drop_all() + clear_mappers() + + def test_path_registry(self): + metadata = MetaData() + a = Table("a", metadata, + Column('id', Integer, primary_key=True), + ) + m1 = mapper(A, a) + @profile_memory() + def go(): + ma = aliased(A) + m1._sa_path_registry['foo'][ma]['bar'] + go() + clear_mappers() + def test_with_inheritance(self): metadata = MetaData(testing.db) @@ -383,7 +449,7 @@ class MemUsageTest(EnsureZeroed): Column('col3', String(30)), ) - @profile_memory + @profile_memory() def go(): class A(fixtures.ComparableEntity): pass @@ -449,7 +515,7 @@ class MemUsageTest(EnsureZeroed): Column('t2', Integer, ForeignKey('mytable2.col1')), ) - @profile_memory + @profile_memory() def go(): class A(fixtures.ComparableEntity): pass @@ -505,7 +571,7 @@ class MemUsageTest(EnsureZeroed): t = Table('t', m, Column('x', Integer), Column('y', Integer)) m.create_all(e) e.execute(t.insert(), {"x":1, "y":1}) - @profile_memory + @profile_memory() def go(): r = e.execute(t.alias().select()) for row in r: @@ -541,7 +607,7 @@ class MemUsageTest(EnsureZeroed): metadata.create_all() session = sessionmaker() - @profile_memory + @profile_memory() def go(): s = table2.select() sess = session() @@ -557,7 +623,7 @@ class MemUsageTest(EnsureZeroed): def test_type_compile(self): from sqlalchemy.dialects.sqlite.base import dialect as SQLiteDialect cast = sa.cast(column('x'), sa.Integer) - @profile_memory + @profile_memory() def go(): dialect = SQLiteDialect() cast.compile(dialect=dialect) @@ -565,21 +631,21 @@ class MemUsageTest(EnsureZeroed): @testing.requires.cextensions def test_DecimalResultProcessor_init(self): - @profile_memory + @profile_memory() def go(): to_decimal_processor_factory({}, 10) go() @testing.requires.cextensions def test_DecimalResultProcessor_process(self): - @profile_memory + @profile_memory() def go(): to_decimal_processor_factory(decimal.Decimal, 10)(1.2) go() @testing.requires.cextensions def test_UnicodeResultProcessor_init(self): - @profile_memory + @profile_memory() def go(): to_unicode_processor_factory('utf8') go() diff --git a/test/orm/inheritance/_poly_fixtures.py b/test/orm/inheritance/_poly_fixtures.py index 0ee8f47e7..6c502f58d 100644 --- a/test/orm/inheritance/_poly_fixtures.py +++ b/test/orm/inheritance/_poly_fixtures.py @@ -154,6 +154,54 @@ class _PolymorphicFixtureBase(fixtures.MappedTest, AssertsCompiledSQL): cls.c1_employees = [e1, e2, b1, m1] cls.c2_employees = [e3] + def _company_with_emps_machines_fixture(self): + fixture = self._company_with_emps_fixture() + fixture[0].employees[0].machines = [ + Machine(name="IBM ThinkPad"), + Machine(name="IPhone"), + ] + fixture[0].employees[1].machines = [ + Machine(name="Commodore 64") + ] + return fixture + + def _company_with_emps_fixture(self): + return [ + Company( + name="MegaCorp, Inc.", + employees=[ + Engineer( + name="dilbert", + engineer_name="dilbert", + primary_language="java", + status="regular engineer" + ), + Engineer( + name="wally", + engineer_name="wally", + primary_language="c++", + status="regular engineer"), + Boss( + name="pointy haired boss", + golf_swing="fore", + manager_name="pointy", + status="da boss"), + Manager( + name="dogbert", + manager_name="dogbert", + status="regular manager"), + ]), + Company( + name="Elbonia, Inc.", + employees=[ + Engineer( + name="vlad", + engineer_name="vlad", + primary_language="cobol", + status="elbonian engineer") + ]) + ] + def _emps_wo_relationships_fixture(self): return [ Engineer( diff --git a/test/orm/inheritance/test_polymorphic_rel.py b/test/orm/inheritance/test_polymorphic_rel.py index 792bd8109..50593d39c 100644 --- a/test/orm/inheritance/test_polymorphic_rel.py +++ b/test/orm/inheritance/test_polymorphic_rel.py @@ -1,17 +1,14 @@ -from sqlalchemy import Integer, String, ForeignKey, func, desc, and_, or_ -from sqlalchemy.orm import interfaces, relationship, mapper, \ - clear_mappers, create_session, joinedload, joinedload_all, \ - subqueryload, subqueryload_all, polymorphic_union, aliased,\ +from sqlalchemy import func, desc +from sqlalchemy.orm import interfaces, create_session, joinedload, joinedload_all, \ + subqueryload, subqueryload_all, aliased,\ class_mapper from sqlalchemy import exc as sa_exc -from sqlalchemy.engine import default -from test.lib import AssertsCompiledSQL, fixtures, testing -from test.lib.schema import Table, Column +from test.lib import testing from test.lib.testing import assert_raises, eq_ from _poly_fixtures import Company, Person, Engineer, Manager, Boss, \ - Machine, Paperwork, _PolymorphicFixtureBase, _Polymorphic,\ + Machine, Paperwork, _Polymorphic,\ _PolymorphicPolymorphic, _PolymorphicUnions, _PolymorphicJoins,\ _PolymorphicAliasedJoins @@ -323,31 +320,6 @@ class _PolymorphicTestBase(object): .filter(any_).all(), []) - def test_polymorphic_any_four(self): - sess = create_session() - any_ = Company.employees.of_type(Engineer).any( - Engineer.primary_language == 'cobol') - eq_(sess.query(Company).filter(any_).one(), c2) - - def test_polymorphic_any_five(self): - sess = create_session() - calias = aliased(Company) - any_ = calias.employees.of_type(Engineer).any( - Engineer.primary_language == 'cobol') - eq_(sess.query(calias).filter(any_).one(), c2) - - def test_polymorphic_any_six(self): - sess = create_session() - any_ = Company.employees.of_type(Boss).any( - Boss.golf_swing == 'fore') - eq_(sess.query(Company).filter(any_).one(), c1) - - def test_polymorphic_any_seven(self): - sess = create_session() - any_ = Company.employees.of_type(Boss).any( - Manager.manager_name == 'pointy') - eq_(sess.query(Company).filter(any_).one(), c1) - def test_polymorphic_any_eight(self): sess = create_session() any_ = Engineer.machines.any( @@ -360,11 +332,6 @@ class _PolymorphicTestBase(object): Paperwork.description == "review #2") eq_(sess.query(Person).filter(any_).all(), [m1]) - def test_polymorphic_any_ten(self): - sess = create_session() - any_ = Company.employees.of_type(Engineer).any( - and_(Engineer.primary_language == 'cobol')) - eq_(sess.query(Company).filter(any_).one(), c2) def test_join_from_columns_or_subclass_one(self): sess = create_session() @@ -529,17 +496,21 @@ class _PolymorphicTestBase(object): .all(), expected) + # TODO: this fails due to the change + # in _configure_subclass_mapper. however we might not + # need it anymore. def test_polymorphic_option(self): """ Test that polymorphic loading sets state.load_path with its actual mapper on a subclass, and not the superclass mapper. - """ + This only works for non-aliased mappers. + """ paths = [] class MyOption(interfaces.MapperOption): propagate_to_loaders = True def process_query_conditionally(self, query): - paths.append(query._current_path) + paths.append(query._current_path.path) sess = create_session() names = ['dilbert', 'pointy haired boss'] @@ -556,6 +527,17 @@ class _PolymorphicTestBase(object): [(class_mapper(Engineer), 'machines'), (class_mapper(Boss), 'paperwork')]) + def test_subclass_option_pathing(self): + from sqlalchemy.orm import defer + sess = create_session() + names = ['dilbert', 'pointy haired boss'] + dilbert = sess.query(Person).\ + options(defer(Engineer.machines, Machine.name)).\ + filter(Person.name == 'dilbert').first() + m = dilbert.machines[0] + assert 'name' not in m.__dict__ + eq_(m.name, 'IBM ThinkPad') + def test_expire(self): """ Test that individual column refresh doesn't get tripped up by @@ -639,69 +621,42 @@ class _PolymorphicTestBase(object): self._emps_wo_relationships_fixture()) - def test_relationship_to_polymorphic(self): - expected = [ - Company( - name="MegaCorp, Inc.", - employees=[ - Engineer( - name="dilbert", - engineer_name="dilbert", - primary_language="java", - status="regular engineer", - machines=[ - Machine(name="IBM ThinkPad"), - Machine(name="IPhone")]), - Engineer( - name="wally", - engineer_name="wally", - primary_language="c++", - status="regular engineer"), - Boss( - name="pointy haired boss", - golf_swing="fore", - manager_name="pointy", - status="da boss"), - Manager( - name="dogbert", - manager_name="dogbert", - status="regular manager"), - ]), - Company( - name="Elbonia, Inc.", - employees=[ - Engineer( - name="vlad", - engineer_name="vlad", - primary_language="cobol", - status="elbonian engineer") - ]) - ] - + def test_relationship_to_polymorphic_one(self): + expected = self._company_with_emps_machines_fixture() sess = create_session() def go(): # test load Companies with lazy load to 'employees' eq_(sess.query(Company).all(), expected) - count = {'':9, 'Polymorphic':4}.get(self.select_type, 5) + count = {'':10, 'Polymorphic':5}.get(self.select_type, 6) self.assert_sql_count(testing.db, go, count) + def test_relationship_to_polymorphic_two(self): + expected = self._company_with_emps_machines_fixture() sess = create_session() def go(): - # currently, it doesn't matter if we say Company.employees, - # or Company.employees.of_type(Engineer). joinedloader - # doesn't pick up on the "of_type()" as of yet. + # with #2438, of_type() is recognized. This + # overrides the with_polymorphic of the mapper + # and we get a consistent 3 queries now. eq_(sess.query(Company) .options(joinedload_all( Company.employees.of_type(Engineer), Engineer.machines)) .all(), expected) - # in the case of select_type='', the joinedload - # doesn't take in this case; it joinedloads company->people, - # then a load for each of 5 rows, then lazyload of "machines" - count = {'':7, 'Polymorphic':1}.get(self.select_type, 2) + + # in the old case, we would get this + #count = {'':7, 'Polymorphic':1}.get(self.select_type, 2) + + # query one is company->Person/Engineer->Machines + # query two is managers + boss for row #3 + # query three is managers for row #4 + count = 3 self.assert_sql_count(testing.db, go, count) + def test_relationship_to_polymorphic_three(self): + expected = self._company_with_emps_machines_fixture() + sess = create_session() + sess = create_session() def go(): eq_(sess.query(Company) @@ -710,12 +665,20 @@ class _PolymorphicTestBase(object): Engineer.machines)) .all(), expected) - count = { - '':8, - 'Joins':4, - 'Unions':4, - 'Polymorphic':3, - 'AliasedJoins':4}[self.select_type] + + # the old case where subqueryload_all + # didn't work with of_tyoe + #count = { '':8, 'Joins':4, 'Unions':4, 'Polymorphic':3, + # 'AliasedJoins':4}[self.select_type] + + # query one is company->Person/Engineer->Machines + # query two is Person/Engineer subq + # query three is Machines subq + # (however this test can't tell if the Q was a + # lazyload or subqload ...) + # query four is managers + boss for row #3 + # query five is managers for row #4 + count = 5 self.assert_sql_count(testing.db, go, count) def test_joinedload_on_subclass(self): @@ -869,40 +832,6 @@ class _PolymorphicTestBase(object): .filter(Machine.name.ilike("%ibm%")).all(), [e1, e3]) - def test_join_to_subclass_eightteen(self): - sess = create_session() - # here's the new way - eq_(sess.query(Company) - .join(Company.employees.of_type(Engineer)) - .filter(Engineer.primary_language == 'java').all(), - [c1]) - - def test_join_to_subclass_nineteen(self): - sess = create_session() - eq_(sess.query(Company) - .join(Company.employees.of_type(Engineer), 'machines') - .filter(Machine.name.ilike("%thinkpad%")).all(), - [c1]) - - def test_join_to_subclass_count(self): - sess = create_session() - - eq_(sess.query(Company, Engineer) - .join(Company.employees.of_type(Engineer)) - .filter(Engineer.primary_language == 'java').count(), - 1) - - # test [ticket:2093] - eq_(sess.query(Company.company_id, Engineer) - .join(Company.employees.of_type(Engineer)) - .filter(Engineer.primary_language == 'java').count(), - 1) - - eq_(sess.query(Company) - .join(Company.employees.of_type(Engineer)) - .filter(Engineer.primary_language == 'java').count(), - 1) - def test_join_through_polymorphic_nonaliased_one(self): sess = create_session() eq_(sess.query(Company) @@ -1364,6 +1293,5 @@ class PolymorphicUnionsTest(_PolymorphicTestBase, _PolymorphicUnions): class PolymorphicAliasedJoinsTest(_PolymorphicTestBase, _PolymorphicAliasedJoins): pass - class PolymorphicJoinsTest(_PolymorphicTestBase, _PolymorphicJoins): pass diff --git a/test/orm/test_merge.py b/test/orm/test_merge.py index 5885a4bda..951b3ec79 100644 --- a/test/orm/test_merge.py +++ b/test/orm/test_merge.py @@ -1078,7 +1078,7 @@ class MergeTest(_fixtures.FixtureTest): for u in s1_users: ustate = attributes.instance_state(u) - eq_(ustate.load_path, (umapper, )) + eq_(ustate.load_path.path, (umapper, )) eq_(ustate.load_options, set([opt2])) # test 2. present options are replaced by merge options @@ -1086,7 +1086,7 @@ class MergeTest(_fixtures.FixtureTest): s1_users = sess.query(User).options(opt1).all() for u in s1_users: ustate = attributes.instance_state(u) - eq_(ustate.load_path, (umapper, )) + eq_(ustate.load_path.path, (umapper, )) eq_(ustate.load_options, set([opt1])) for u in s2_users: @@ -1094,7 +1094,7 @@ class MergeTest(_fixtures.FixtureTest): for u in s1_users: ustate = attributes.instance_state(u) - eq_(ustate.load_path, (umapper, )) + eq_(ustate.load_path.path, (umapper, )) eq_(ustate.load_options, set([opt2])) diff --git a/test/orm/test_pickled.py b/test/orm/test_pickled.py index f2d292832..bb5bca984 100644 --- a/test/orm/test_pickled.py +++ b/test/orm/test_pickled.py @@ -108,6 +108,8 @@ class PickleTest(fixtures.MappedTest): eq_(str(u1), "User(name='ed')") def test_serialize_path(self): + from sqlalchemy.orm.util import PathRegistry + users, addresses = (self.tables.users, self.tables.addresses) @@ -117,24 +119,24 @@ class PickleTest(fixtures.MappedTest): amapper = mapper(Address, addresses) # this is a "relationship" path with mapper, key, mapper, key - p1 = (umapper, 'addresses', amapper, 'email_address') + p1 = PathRegistry.coerce((umapper, 'addresses', amapper, 'email_address')) eq_( - interfaces.deserialize_path(interfaces.serialize_path(p1)), + PathRegistry.deserialize(p1.serialize()), p1 ) # this is a "mapper" path with mapper, key, mapper, no key # at the end. - p2 = (umapper, 'addresses', amapper, ) + p2 = PathRegistry.coerce((umapper, 'addresses', amapper, )) eq_( - interfaces.deserialize_path(interfaces.serialize_path(p2)), + PathRegistry.deserialize(p2.serialize()), p2 ) # test a blank path - p3 = () + p3 = PathRegistry.root eq_( - interfaces.deserialize_path(interfaces.serialize_path(p3)), + PathRegistry.deserialize(p3.serialize()), p3 ) diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 9073f1056..fcda72a8a 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -9,7 +9,8 @@ from sqlalchemy.sql import expression from sqlalchemy.engine import default from sqlalchemy.orm import attributes, mapper, relationship, backref, \ configure_mappers, create_session, synonym, Session, class_mapper, \ - aliased, column_property, joinedload_all, joinedload, Query + aliased, column_property, joinedload_all, joinedload, Query,\ + util as orm_util from test.lib.assertsql import CompiledSQL from test.lib.testing import eq_ from test.lib.schema import Table, Column @@ -2119,7 +2120,7 @@ class ExecutionOptionsTest(QueryTest): class OptionsTest(QueryTest): - """Test the _get_paths() method of PropertyOption.""" + """Test the _process_paths() method of PropertyOption.""" def _option_fixture(self, *arg): from sqlalchemy.orm import interfaces @@ -2136,11 +2137,15 @@ class OptionsTest(QueryTest): r.append(item) return tuple(r) - def _assert_path_result(self, opt, q, paths, mappers): + def _make_path_registry(self, path): + return orm_util.PathRegistry.coerce(self._make_path(path)) + + def _assert_path_result(self, opt, q, paths): + q._attributes = q._attributes.copy() + assert_paths = opt._process_paths(q, False) eq_( - opt._get_paths(q, False), - ([self._make_path(p) for p in paths], - [class_mapper(c) for c in mappers]) + [p.path for p in assert_paths], + [self._make_path(p) for p in paths] ) def test_get_path_one_level_string(self): @@ -2150,7 +2155,7 @@ class OptionsTest(QueryTest): q = sess.query(User) opt = self._option_fixture("addresses") - self._assert_path_result(opt, q, [(User, 'addresses')], [User]) + self._assert_path_result(opt, q, [(User, 'addresses')]) def test_get_path_one_level_attribute(self): User = self.classes.User @@ -2159,7 +2164,7 @@ class OptionsTest(QueryTest): q = sess.query(User) opt = self._option_fixture(User.addresses) - self._assert_path_result(opt, q, [(User, 'addresses')], [User]) + self._assert_path_result(opt, q, [(User, 'addresses')]) def test_path_on_entity_but_doesnt_match_currentpath(self): User, Address = self.classes.User, self.classes.Address @@ -2170,8 +2175,10 @@ class OptionsTest(QueryTest): sess = Session() q = sess.query(User) opt = self._option_fixture('email_address', 'id') - q = sess.query(Address)._with_current_path([class_mapper(User), 'addresses']) - self._assert_path_result(opt, q, [], []) + q = sess.query(Address)._with_current_path( + orm_util.PathRegistry.coerce([class_mapper(User), 'addresses']) + ) + self._assert_path_result(opt, q, []) def test_get_path_one_level_with_unrelated(self): Order = self.classes.Order @@ -2179,7 +2186,7 @@ class OptionsTest(QueryTest): sess = Session() q = sess.query(Order) opt = self._option_fixture("addresses") - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) def test_path_multilevel_string(self): Item, User, Order = (self.classes.Item, @@ -2194,8 +2201,7 @@ class OptionsTest(QueryTest): (User, 'orders'), (User, 'orders', Order, 'items'), (User, 'orders', Order, 'items', Item, 'keywords') - ], - [User, Order, Item]) + ]) def test_path_multilevel_attribute(self): Item, User, Order = (self.classes.Item, @@ -2210,8 +2216,7 @@ class OptionsTest(QueryTest): (User, 'orders'), (User, 'orders', Order, 'items'), (User, 'orders', Order, 'items', Item, 'keywords') - ], - [User, Order, Item]) + ]) def test_with_current_matching_string(self): Item, User, Order = (self.classes.Item, @@ -2220,13 +2225,13 @@ class OptionsTest(QueryTest): sess = Session() q = sess.query(Item)._with_current_path( - self._make_path([User, 'orders', Order, 'items']) + self._make_path_registry([User, 'orders', Order, 'items']) ) opt = self._option_fixture("orders.items.keywords") self._assert_path_result(opt, q, [ (Item, 'keywords') - ], [Item]) + ]) def test_with_current_matching_attribute(self): Item, User, Order = (self.classes.Item, @@ -2235,13 +2240,13 @@ class OptionsTest(QueryTest): sess = Session() q = sess.query(Item)._with_current_path( - self._make_path([User, 'orders', Order, 'items']) + self._make_path_registry([User, 'orders', Order, 'items']) ) opt = self._option_fixture(User.orders, Order.items, Item.keywords) self._assert_path_result(opt, q, [ (Item, 'keywords') - ], [Item]) + ]) def test_with_current_nonmatching_string(self): Item, User, Order = (self.classes.Item, @@ -2250,14 +2255,14 @@ class OptionsTest(QueryTest): sess = Session() q = sess.query(Item)._with_current_path( - self._make_path([User, 'orders', Order, 'items']) + self._make_path_registry([User, 'orders', Order, 'items']) ) opt = self._option_fixture("keywords") - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) opt = self._option_fixture("items.keywords") - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) def test_with_current_nonmatching_attribute(self): Item, User, Order = (self.classes.Item, @@ -2266,14 +2271,14 @@ class OptionsTest(QueryTest): sess = Session() q = sess.query(Item)._with_current_path( - self._make_path([User, 'orders', Order, 'items']) + self._make_path_registry([User, 'orders', Order, 'items']) ) opt = self._option_fixture(Item.keywords) - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) opt = self._option_fixture(Order.items, Item.keywords) - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) def test_from_base_to_subclass_attr(self): Dingaling, Address = self.classes.Dingaling, self.classes.Address @@ -2288,7 +2293,7 @@ class OptionsTest(QueryTest): q = sess.query(Address) opt = self._option_fixture(SubAddr.flub) - self._assert_path_result(opt, q, [(Address, 'flub')], [SubAddr]) + self._assert_path_result(opt, q, [(Address, 'flub')]) def test_from_subclass_to_subclass_attr(self): Dingaling, Address = self.classes.Dingaling, self.classes.Address @@ -2303,7 +2308,7 @@ class OptionsTest(QueryTest): q = sess.query(SubAddr) opt = self._option_fixture(SubAddr.flub) - self._assert_path_result(opt, q, [(SubAddr, 'flub')], [SubAddr]) + self._assert_path_result(opt, q, [(SubAddr, 'flub')]) def test_from_base_to_base_attr_via_subclass(self): Dingaling, Address = self.classes.Dingaling, self.classes.Address @@ -2318,7 +2323,7 @@ class OptionsTest(QueryTest): q = sess.query(Address) opt = self._option_fixture(SubAddr.user) - self._assert_path_result(opt, q, [(Address, 'user')], [Address]) + self._assert_path_result(opt, q, [(Address, 'user')]) def test_of_type(self): User, Address = self.classes.User, self.classes.Address @@ -2334,7 +2339,7 @@ class OptionsTest(QueryTest): self._assert_path_result(opt, q, [ (User, 'addresses'), (User, 'addresses', SubAddr, 'user') - ], [User, Address]) + ]) def test_of_type_plus_level(self): Dingaling, User, Address = (self.classes.Dingaling, @@ -2354,7 +2359,7 @@ class OptionsTest(QueryTest): self._assert_path_result(opt, q, [ (User, 'addresses'), (User, 'addresses', SubAddr, 'flub') - ], [User, SubAddr]) + ]) def test_aliased_single(self): User = self.classes.User @@ -2363,7 +2368,7 @@ class OptionsTest(QueryTest): ualias = aliased(User) q = sess.query(ualias) opt = self._option_fixture(ualias.addresses) - self._assert_path_result(opt, q, [(ualias, 'addresses')], [User]) + self._assert_path_result(opt, q, [(ualias, 'addresses')]) def test_with_current_aliased_single(self): User, Address = self.classes.User, self.classes.Address @@ -2371,10 +2376,10 @@ class OptionsTest(QueryTest): sess = Session() ualias = aliased(User) q = sess.query(ualias)._with_current_path( - self._make_path([Address, 'user']) + self._make_path_registry([Address, 'user']) ) opt = self._option_fixture(Address.user, ualias.addresses) - self._assert_path_result(opt, q, [(ualias, 'addresses')], [User]) + self._assert_path_result(opt, q, [(ualias, 'addresses')]) def test_with_current_aliased_single_nonmatching_option(self): User, Address = self.classes.User, self.classes.Address @@ -2382,22 +2387,21 @@ class OptionsTest(QueryTest): sess = Session() ualias = aliased(User) q = sess.query(User)._with_current_path( - self._make_path([Address, 'user']) + self._make_path_registry([Address, 'user']) ) opt = self._option_fixture(Address.user, ualias.addresses) - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) - @testing.fails_if(lambda: True, "Broken feature") def test_with_current_aliased_single_nonmatching_entity(self): User, Address = self.classes.User, self.classes.Address sess = Session() ualias = aliased(User) q = sess.query(ualias)._with_current_path( - self._make_path([Address, 'user']) + self._make_path_registry([Address, 'user']) ) opt = self._option_fixture(Address.user, User.addresses) - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) def test_multi_entity_opt_on_second(self): Item = self.classes.Item @@ -2405,7 +2409,7 @@ class OptionsTest(QueryTest): opt = self._option_fixture(Order.items) sess = Session() q = sess.query(Item, Order) - self._assert_path_result(opt, q, [(Order, "items")], [Order]) + self._assert_path_result(opt, q, [(Order, "items")]) def test_multi_entity_opt_on_string(self): Item = self.classes.Item @@ -2413,7 +2417,7 @@ class OptionsTest(QueryTest): opt = self._option_fixture("items") sess = Session() q = sess.query(Item, Order) - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) def test_multi_entity_no_mapped_entities(self): Item = self.classes.Item @@ -2421,7 +2425,7 @@ class OptionsTest(QueryTest): opt = self._option_fixture("items") sess = Session() q = sess.query(Item.id, Order.id) - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) def test_path_exhausted(self): User = self.classes.User @@ -2430,9 +2434,9 @@ class OptionsTest(QueryTest): opt = self._option_fixture(User.orders) sess = Session() q = sess.query(Item)._with_current_path( - self._make_path([User, 'orders', Order, 'items']) + self._make_path_registry([User, 'orders', Order, 'items']) ) - self._assert_path_result(opt, q, [], []) + self._assert_path_result(opt, q, []) class OptionsNoPropTest(_fixtures.FixtureTest): """test the error messages emitted when using property diff --git a/test/orm/test_subquery_relations.py b/test/orm/test_subquery_relations.py index 90df17609..53c50634e 100644 --- a/test/orm/test_subquery_relations.py +++ b/test/orm/test_subquery_relations.py @@ -358,8 +358,6 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL): ("subqueryload", "subqueryload", "subqueryload", 4), ("subqueryload", "subqueryload", "joinedload", 3), ] -# _pathing_runs = [("subqueryload", "subqueryload", "joinedload", 3)] -# _pathing_runs = [("subqueryload", "subqueryload", "subqueryload", 4)] def test_options_pathing(self): self._do_options_test(self._pathing_runs) diff --git a/test/perf/orm2010.py b/test/perf/orm2010.py index d24376cc9..23bad9c69 100644 --- a/test/perf/orm2010.py +++ b/test/perf/orm2010.py @@ -159,7 +159,9 @@ print 'Total executemany calls: %d' \ % counts_by_methname.get("<method 'executemany' of 'sqlite3.Cursor' " "objects>", 0) -os.system("runsnake %s" % filename) +#stats.sort_stats('time', 'calls') +#stats.print_stats() +#os.system("runsnake %s" % filename) # SQLA Version: 0.7b1 # Total calls 4956750 |
