From: Mike Bayer Date: Mon, 7 Apr 2008 19:49:41 +0000 (+0000) Subject: - removed ancient assertion that mapped selectables require X-Git-Tag: rel_0_5beta1~195 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5080a1740928e593a21321763c2bb91ffed2edb3;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - removed ancient assertion that mapped selectables require "alias names" - the mapper creates its own alias now if none is present. Though in this case you need to use the class, not the mapped selectable, as the source of column attributes - so a warning is still issued. --- diff --git a/CHANGES b/CHANGES index 897b84188a..cf7df2c730 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,12 @@ CHANGES multiple times, with a common column shared between the joins. + - removed ancient assertion that mapped selectables require + "alias names" - the mapper creates its own alias now if + none is present. Though in this case you need to use + the class, not the mapped selectable, as the source of + column attributes - so a warning is still issued. + - sql - Fixed bug with union() when applied to non-Table connected select statements diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 751ea765d4..560c304da2 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -135,13 +135,13 @@ class Mapper(object): raise exceptions.ArgumentError("Invalid setting for with_polymorphic") else: self.with_polymorphic = None - - check_tables = [self.local_table] - if self.with_polymorphic: - check_tables.append(self.with_polymorphic[1]) - for table in check_tables: - if table and isinstance(table, expression._SelectBaseMixin): - raise exceptions.ArgumentError("Mapping against a Select object requires that it has a name. Use an alias to give it a name, i.e. s = select(...).alias('myselect')") + + if isinstance(self.local_table, expression._SelectBaseMixin): + util.warn("mapper %s creating an alias for the given selectable - use Class attributes for queries." % self) + self.local_table = self.local_table.alias() + + if self.with_polymorphic and isinstance(self.with_polymorphic[1], expression._SelectBaseMixin): + self.with_polymorphic[1] = self.with_polymorphic[1].alias() # our 'polymorphic identity', a string name that when located in a result set row # indicates this Mapper should be used to construct the object instance for that row. @@ -485,7 +485,7 @@ class Mapper(object): self._pks_by_table = {} self._cols_by_table = {} - all_cols = util.Set(chain(*[c2 for c2 in [col.proxy_set for col in [c for c in self._columntoproperty]]])) + all_cols = util.Set(chain(*[col.proxy_set for col in self._columntoproperty])) pk_cols = util.Set([c for c in all_cols if c.primary_key]) # identify primary key columns which are also mapped by this mapper. @@ -528,8 +528,8 @@ class Mapper(object): by primary key. """ - params = dict([(primary_key, sql.bindparam(None, type_=primary_key.type)) for primary_key in self.primary_key]) - return sql.and_(*[k==v for (k, v) in params.iteritems()]), params + params = [(primary_key, sql.bindparam(None, type_=primary_key.type)) for primary_key in self.primary_key] + return sql.and_(*[k==v for (k, v) in params]), dict(params) _get_clause = property(util.cache_decorator(_get_clause)) def _equivalent_columns(self): diff --git a/test/orm/mapper.py b/test/orm/mapper.py index d4e8c1465c..b99e1fdda1 100644 --- a/test/orm/mapper.py +++ b/test/orm/mapper.py @@ -31,28 +31,15 @@ class MapperTest(MapperSuperTest): properties={ 'addresses':relation(Address, backref='email_address') }) - try: - class_mapper(Address) - class_mapper(User) - assert False - except exceptions.ArgumentError: - pass + self.assertRaises(exceptions.ArgumentError, compile_mappers) def test_prop_accessor(self): mapper(User, users) - try: - class_mapper(User).properties - assert False - except NotImplementedError, uoe: - assert str(uoe) == "Public collection of MapperProperty objects is provided by the get_property() and iterate_properties accessors." + self.assertRaises(NotImplementedError, getattr, class_mapper(User), 'properties') def test_badcascade(self): mapper(Address, addresses) - try: - mapper(User, users, properties={'addresses':relation(Address, cascade="fake, all, delete-orphan")}) - assert False - except exceptions.ArgumentError, e: - assert str(e) == "Invalid cascade option 'fake'" + self.assertRaises(exceptions.ArgumentError, relation, Address, cascade="fake, all, delete-orphan") def test_columnprefix(self): mapper(User, users, column_prefix='_', properties={ @@ -68,11 +55,7 @@ class MapperTest(MapperSuperTest): def test_no_pks(self): s = select([users.c.user_name]).alias('foo') - try: - mapper(User, s) - assert False - except exceptions.ArgumentError, e: - assert "could not assemble any primary key columns for mapped table 'foo'" in str(e) + self.assertRaises(exceptions.ArgumentError, mapper, User, s) def test_recompile_on_othermapper(self): """test the global '__new_mappers' flag such that a compile @@ -115,16 +98,9 @@ class MapperTest(MapperSuperTest): pass mapper(Foo, users) sess = create_session() - try: - Foo('one', _sa_session=sess) - assert False - except: - assert len(list(sess)) == 0 - try: - Foo('one') - assert False - except TypeError, e: - pass + self.assertRaises(TypeError, Foo, 'one', _sa_session=sess) + assert len(list(sess)) == 0 + self.assertRaises(TypeError, Foo, 'one') @testing.uses_deprecated('SessionContext', 'SessionContextExt') def test_constructorexceptions(self): diff --git a/test/orm/selectable.py b/test/orm/selectable.py index 30771ec2b1..fc5be6f505 100644 --- a/test/orm/selectable.py +++ b/test/orm/selectable.py @@ -20,19 +20,15 @@ class SelectableNoFromsTest(ORMTest): def test_no_tables(self): class Subset(object): pass - selectable = select(["x", "y", "z"]).alias('foo') - try: - mapper(Subset, selectable) - compile_mappers() - assert False - except exceptions.InvalidRequestError, e: - assert str(e) == "Could not find any Table objects in mapped table 'SELECT x, y, z'", str(e) + selectable = select(["x", "y", "z"]) + self.assertRaisesMessage(exceptions.InvalidRequestError, "Could not find any Table objects", mapper, Subset, selectable) + @testing.emits_warning('.*creating an Alias.*') def test_basic(self): class Subset(Base): pass - subset_select = select([common_table.c.id, common_table.c.data]).alias('subset') + subset_select = select([common_table.c.id, common_table.c.data]) subset_mapper = mapper(Subset, subset_select) sess = create_session(bind=testing.db) @@ -42,8 +38,14 @@ class SelectableNoFromsTest(ORMTest): sess.flush() sess.clear() - assert [Subset(data=1)] == sess.query(Subset).all() + self.assertEquals(sess.query(Subset).all(), [Subset(data=1)]) + self.assertEquals(sess.query(Subset).filter(Subset.data==1).one(), Subset(data=1)) + self.assertEquals(sess.query(Subset).filter(Subset.data!=1).first(), None) + + subset_select = class_mapper(Subset).mapped_table + self.assertEquals(sess.query(Subset).filter(subset_select.c.data==1).one(), Subset(data=1)) + # TODO: more tests mapping to selects if __name__ == '__main__':