summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-06-20 19:28:29 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-06-20 19:28:29 -0400
commit3dd536ac06808adcf9c10707dbf2ebb6e3842be7 (patch)
treed102291da86021aa4584ef836dbb0471596c3eeb /test
parent40098941007ff3aa1593e834915c4042c1668dc2 (diff)
downloadsqlalchemy-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.py158
-rw-r--r--test/orm/inheritance/_poly_fixtures.py48
-rw-r--r--test/orm/inheritance/test_polymorphic_rel.py184
-rw-r--r--test/orm/test_merge.py6
-rw-r--r--test/orm/test_pickled.py14
-rw-r--r--test/orm/test_query.py90
-rw-r--r--test/orm/test_subquery_relations.py2
-rw-r--r--test/perf/orm2010.py4
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