From 29a6af6d46795cd81fa5f8a409409a5215c7b08e Mon Sep 17 00:00:00 2001 From: Jason Kirtland Date: Sat, 27 Sep 2008 01:37:26 +0000 Subject: [PATCH] Added query_cls= override to scoped_session's query_property --- CHANGES | 5 ++++- lib/sqlalchemy/orm/scoping.py | 19 ++++++++++++++++--- test/engine/reconnect.py | 6 +++--- test/orm/memusage.py | 2 +- test/orm/scoping.py | 9 ++++++++- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 5fb8861cb0..abd018871c 100644 --- a/CHANGES +++ b/CHANGES @@ -21,7 +21,10 @@ CHANGES upon reentrant mapper compile() calls, something that occurs when using declarative constructs inside of ForeignKey objects. - + + - ScopedSession.query_property now accepts a query_cls factory, + overriding the session's configured query_cls. + - sql - column.in_(someselect) can now be used as a columns-clause expression without the subquery diff --git a/lib/sqlalchemy/orm/scoping.py b/lib/sqlalchemy/orm/scoping.py index 422b362633..5dd17a2898 100644 --- a/lib/sqlalchemy/orm/scoping.py +++ b/lib/sqlalchemy/orm/scoping.py @@ -77,7 +77,7 @@ class ScopedSession(object): self.session_factory.configure(**kwargs) - def query_property(self): + def query_property(self, query_cls=None): """return a class property which produces a `Query` object against the class when called. @@ -90,13 +90,26 @@ class ScopedSession(object): # after mappers are defined result = MyClass.query.filter(MyClass.name=='foo').all() - """ + Produces instances of the session's configured query class by + default. To override and use a custom implementation, provide + a ``query_cls`` callable. The callable will be invoked with + the class's mapper as a positional argument and a session + keyword argument. + + There is no limit to the number of query properties placed on + a class. + """ class query(object): def __get__(s, instance, owner): mapper = class_mapper(owner, raiseerror=False) if mapper: - return self.registry().query(mapper) + if query_cls: + # custom query class + return query_cls(mapper, session=self.registry()) + else: + # session's configured query class + return self.registry().query(mapper) else: return None return query() diff --git a/test/engine/reconnect.py b/test/engine/reconnect.py index d50267a1f2..f08dbcdd54 100644 --- a/test/engine/reconnect.py +++ b/test/engine/reconnect.py @@ -46,7 +46,7 @@ class MockCursor(object): pass db, dbapi = None, None -class MockReconnectTest(TestBase): +class MockReconnectTest(object): def setUp(self): global db, dbapi dbapi = MockDBAPI() @@ -175,7 +175,7 @@ class MockReconnectTest(TestBase): assert len(dbapi.connections) == 1 engine = None -class RealReconnectTest(TestBase): +class RealReconnectTest(object): def setUp(self): global engine engine = engines.reconnecting_engine() @@ -281,7 +281,7 @@ class RealReconnectTest(TestBase): self.assertEquals(conn.execute(select([1])).scalar(), 1) assert not conn.invalidated -class RecycleTest(TestBase): +class RecycleTest(object): def test_basic(self): for threadlocal in (False, True): engine = engines.reconnecting_engine(options={'pool_recycle':1, 'pool_threadlocal':threadlocal}) diff --git a/test/orm/memusage.py b/test/orm/memusage.py index 6348f22371..06e2c14238 100644 --- a/test/orm/memusage.py +++ b/test/orm/memusage.py @@ -54,7 +54,7 @@ class EnsureZeroed(_base.ORMTest): _sessions.clear() _mapper_registry.clear() -class MemUsageTest(EnsureZeroed): +class MemUsageTest(object): # ensure a pure growing test trips the assertion @testing.fails_if(lambda:True) diff --git a/test/orm/scoping.py b/test/orm/scoping.py index cdc0c16b41..32e0dedb0e 100644 --- a/test/orm/scoping.py +++ b/test/orm/scoping.py @@ -2,7 +2,7 @@ import testenv; testenv.configure_for_tests() from testlib import sa, testing from sqlalchemy.orm import scoped_session from testlib.sa import Table, Column, Integer, String, ForeignKey -from testlib.sa.orm import mapper, relation +from testlib.sa.orm import mapper, relation, query from testlib.testing import eq_ from orm import _base @@ -38,10 +38,14 @@ class ScopedSessionTest(_base.MappedTest): def test_basic(self): Session = scoped_session(sa.orm.sessionmaker()) + class CustomQuery(query.Query): + pass + class SomeObject(_base.ComparableEntity): query = Session.query_property() class SomeOtherObject(_base.ComparableEntity): query = Session.query_property() + custom_query = Session.query_property(query_cls=CustomQuery) mapper(SomeObject, table1, properties={ 'options':relation(SomeOtherObject)}) @@ -62,6 +66,9 @@ class ScopedSessionTest(_base.MappedTest): eq_(SomeOtherObject(someid=1), SomeOtherObject.query.filter( SomeOtherObject.someid == sso.someid).one()) + assert isinstance(SomeOtherObject.query, query.Query) + assert not isinstance(SomeOtherObject.query, CustomQuery) + assert isinstance(SomeOtherObject.custom_query, query.Query) class ScopedMapperTest(_ScopedTest): -- 2.47.3