summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-01-13 17:11:27 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-01-13 17:11:27 +0000
commit3c1a8adc782b9440b3e7e350712cdfa231c56f7f (patch)
treeec54c4be11682f6221fab4a744c83a28bd188e30
parentfccc3774171f1cbf6490363fe9d20d8cc9d78827 (diff)
downloadsqlalchemy-3c1a8adc782b9440b3e7e350712cdfa231c56f7f.tar.gz
NamedTuple is pickleable ! no really with all the protocols too !
-rw-r--r--lib/sqlalchemy/orm/query.py5
-rw-r--r--lib/sqlalchemy/util.py7
-rw-r--r--test/orm/test_pickled.py21
-rw-r--r--test/orm/test_query.py29
4 files changed, 43 insertions, 19 deletions
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index bd9069e3a..fc83f9195 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -1375,8 +1375,7 @@ class Query(object):
elif single_entity:
rows = [process[0](row, None) for row in fetch]
else:
- rows = [util.NamedTuple(labels,
- [proc(row, None) for proc in process])
+ rows = [util.NamedTuple([proc(row, None) for proc in process], labels)
for row in fetch]
if filter:
@@ -1445,7 +1444,7 @@ class Query(object):
attributes.instance_state(newrow[i]),
attributes.instance_dict(newrow[i]),
load=load, _recursive={})
- result.append(util.NamedTuple(row._labels, newrow))
+ result.append(util.NamedTuple(newrow, row._labels))
return iter(result)
finally:
diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py
index f7d696971..c3ae25589 100644
--- a/lib/sqlalchemy/util.py
+++ b/lib/sqlalchemy/util.py
@@ -642,11 +642,12 @@ class NamedTuple(tuple):
"""
- def __new__(cls, labels, vals):
+ def __new__(cls, vals, labels=None):
vals = list(vals)
t = tuple.__new__(cls, vals)
- t.__dict__ = dict(itertools.izip(labels, vals))
- t._labels = labels
+ if labels:
+ t.__dict__ = dict(itertools.izip(labels, vals))
+ t._labels = labels
return t
def keys(self):
diff --git a/test/orm/test_pickled.py b/test/orm/test_pickled.py
index 1fcd1b8a4..0285f4d0b 100644
--- a/test/orm/test_pickled.py
+++ b/test/orm/test_pickled.py
@@ -4,7 +4,7 @@ import sqlalchemy as sa
from sqlalchemy.test import testing
from sqlalchemy import Integer, String, ForeignKey
from sqlalchemy.test.schema import Table, Column
-from sqlalchemy.orm import mapper, relation, create_session, attributes, interfaces
+from sqlalchemy.orm import mapper, relation, create_session, sessionmaker, attributes, interfaces
from test.orm import _base, _fixtures
@@ -131,6 +131,25 @@ class PickleTest(_fixtures.FixtureTest):
eq_(u2, User(name='ed', addresses=[Address(email_address='ed@bar.com')]))
@testing.resolve_artifact_names
+ def test_pickle_protocols(self):
+ mapper(User, users, properties={
+ 'addresses':relation(Address, backref="user")
+ })
+ mapper(Address, addresses)
+
+ sess = sessionmaker()()
+ u1 = User(name='ed')
+ u1.addresses.append(Address(email_address='ed@bar.com'))
+ sess.add(u1)
+ sess.commit()
+
+ u1 = sess.query(User).first()
+ u1.addresses
+ for protocol in -1, 0, 1, 2:
+ u2 = pickle.loads(pickle.dumps(u1, protocol))
+ eq_(u1, u2)
+
+ @testing.resolve_artifact_names
def test_options_with_descriptors(self):
mapper(User, users, properties={
'addresses':relation(Address, backref="user")
diff --git a/test/orm/test_query.py b/test/orm/test_query.py
index bc3b9e26d..ee9f1853b 100644
--- a/test/orm/test_query.py
+++ b/test/orm/test_query.py
@@ -2403,44 +2403,49 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL):
def test_tuple_labeling(self):
sess = create_session()
- for pickled in False, True:
+ # test pickle + all the protocols !
+ for pickled in False, -1, 0, 1, 2:
for row in sess.query(User, Address).join(User.addresses).all():
- if pickled:
- row = util.pickle.loads(util.pickle.dumps(row))
+ if pickled is not False:
+ row = util.pickle.loads(util.pickle.dumps(row, pickled))
eq_(set(row.keys()), set(['User', 'Address']))
eq_(row.User, row[0])
eq_(row.Address, row[1])
for row in sess.query(User.name, User.id.label('foobar')):
- if pickled:
- row = util.pickle.loads(util.pickle.dumps(row))
+ if pickled is not False:
+ row = util.pickle.loads(util.pickle.dumps(row, pickled))
eq_(set(row.keys()), set(['name', 'foobar']))
eq_(row.name, row[0])
eq_(row.foobar, row[1])
for row in sess.query(User).values(User.name, User.id.label('foobar')):
- if pickled:
- row = util.pickle.loads(util.pickle.dumps(row))
+ if pickled is not False:
+ row = util.pickle.loads(util.pickle.dumps(row, pickled))
eq_(set(row.keys()), set(['name', 'foobar']))
eq_(row.name, row[0])
eq_(row.foobar, row[1])
oalias = aliased(Order)
for row in sess.query(User, oalias).join(User.orders).all():
- if pickled:
- row = util.pickle.loads(util.pickle.dumps(row))
+ if pickled is not False:
+ row = util.pickle.loads(util.pickle.dumps(row, pickled))
eq_(set(row.keys()), set(['User']))
eq_(row.User, row[0])
oalias = aliased(Order, name='orders')
for row in sess.query(User, oalias).join(User.orders).all():
- if pickled:
- row = util.pickle.loads(util.pickle.dumps(row))
+ if pickled is not False:
+ row = util.pickle.loads(util.pickle.dumps(row, pickled))
eq_(set(row.keys()), set(['User', 'orders']))
eq_(row.User, row[0])
eq_(row.orders, row[1])
-
+
+ if pickled is not False:
+ ret = sess.query(User, Address).join(User.addresses).all()
+ util.pickle.loads(util.pickle.dumps(ret, pickled))
+
def test_column_queries(self):
sess = create_session()