From: Mike Bayer Date: Mon, 6 Aug 2012 02:53:56 +0000 (-0400) Subject: - [bug] An error is emitted when uselist=False X-Git-Tag: rel_0_8_0b1~290 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b5c310c27928cbb1922ee34a978b8ac724c4cc42;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - [bug] An error is emitted when uselist=False is combined with a "dynamic" loader. This is a warning in 0.7.9. --- diff --git a/CHANGES b/CHANGES index f228486b2a..d480f812a9 100644 --- a/CHANGES +++ b/CHANGES @@ -213,6 +213,10 @@ underneath "0.7.xx". or remove operation is received on the now-detached collection. [ticket:2476] + - [bug] An error is emitted when uselist=False + is combined with a "dynamic" loader. + This is a warning in 0.7.9. + - [removed] Deprecated identifiers removed: * allow_null_pks mapper() argument @@ -441,6 +445,10 @@ are also present in 0.8. disabled on subclasses, unless overridden explicitly. + - [bug] A warning is emitted when lazy='dynamic' + is combined with uselist=False. This is an + exception raise in 0.8. + - sql - [bug] Fixed CTE bug whereby positional bound parameters present in the CTEs themselves diff --git a/doc/build/orm/collections.rst b/doc/build/orm/collections.rst index e11fc009ea..822fcd3be6 100644 --- a/doc/build/orm/collections.rst +++ b/doc/build/orm/collections.rst @@ -84,6 +84,12 @@ Note that eager/lazy loading options cannot be used in conjunction dynamic relat The :func:`~.orm.dynamic_loader` function is essentially the same as :func:`~.orm.relationship` with the ``lazy='dynamic'`` argument specified. +.. warning:: + + The "dynamic" loader applies to **collections only**. It is not valid + to use "dynamic" loaders with many-to-one, one-to-one, or uselist=False + relationships. Newer versions of SQLAlchemy emit warnings or exceptions + in these cases. Setting Noload --------------- diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py index 6d532e669b..5985755767 100644 --- a/lib/sqlalchemy/orm/dynamic.py +++ b/lib/sqlalchemy/orm/dynamic.py @@ -11,7 +11,7 @@ basic add/delete mutation. """ -from .. import log, util +from .. import log, util, exc from ..sql import operators from . import ( attributes, object_session, util as orm_util, strategies, @@ -22,7 +22,11 @@ from .query import Query class DynaLoader(strategies.AbstractRelationshipLoader): def init_class_attribute(self, mapper): self.is_class_level = True - + if not self.uselist: + raise exc.InvalidRequestError( + "On relationship %s, 'dynamic' loaders cannot be used with " + "many-to-one/one-to-one relationships and/or " + "uselist=False." % self.parent_property) strategies._register_attribute(self, mapper, useobject=True, diff --git a/test/orm/test_dynamic.py b/test/orm/test_dynamic.py index 07f01822b9..fd8793778a 100644 --- a/test/orm/test_dynamic.py +++ b/test/orm/test_dynamic.py @@ -1,8 +1,8 @@ from test.lib.testing import eq_, ne_ import operator -from sqlalchemy.orm import dynamic_loader, backref +from sqlalchemy.orm import dynamic_loader, backref, configure_mappers from test.lib import testing -from sqlalchemy import Integer, String, ForeignKey, desc, select, func +from sqlalchemy import Integer, String, ForeignKey, desc, select, func, exc from test.lib.schema import Table, Column from sqlalchemy.orm import mapper, relationship, create_session, Query, attributes, exc as orm_exc from sqlalchemy.orm.dynamic import AppenderMixin @@ -62,7 +62,7 @@ class DynamicTest(_fixtures.FixtureTest, AssertsCompiledSQL): self.classes.User) mapper(User, users, properties={ - 'addresses':dynamic_loader(mapper(Address, addresses)) + 'addresses': dynamic_loader(mapper(Address, addresses)) }) sess = create_session() u = sess.query(User).get(8) @@ -73,6 +73,40 @@ class DynamicTest(_fixtures.FixtureTest, AssertsCompiledSQL): email_address='e' ) + def test_no_uselist_false(self): + users, Address, addresses, User = (self.tables.users, + self.classes.Address, + self.tables.addresses, + self.classes.User) + mapper(Address, addresses) + mapper(User, users, properties={ + "addresses": relationship(Address, lazy='dynamic', uselist=False) + }) + assert_raises_message( + exc.InvalidRequestError, + "On relationship User.addresses, 'dynamic' loaders cannot be " + "used with many-to-one/one-to-one relationships and/or " + "uselist=False.", + configure_mappers + ) + + def test_no_m2o(self): + users, Address, addresses, User = (self.tables.users, + self.classes.Address, + self.tables.addresses, + self.classes.User) + mapper(Address, addresses, properties={ + 'user': relationship(User, lazy='dynamic') + }) + mapper(User, users) + assert_raises_message( + exc.InvalidRequestError, + "On relationship Address.user, 'dynamic' loaders cannot be " + "used with many-to-one/one-to-one relationships and/or " + "uselist=False.", + configure_mappers + ) + def test_order_by(self): users, Address, addresses, User = (self.tables.users, self.classes.Address,