From f244287f46476f3b111a2495ce4207530f4b51d8 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 12 Dec 2013 13:30:16 -0500 Subject: [PATCH] - :func:`.composite` will raise an informative error message when the columns/attribute (names) passed don't resolve to a Column or mapped attribute (such as an erroneous tuple); previously raised an unbound local. [ticket:2889] --- doc/build/changelog/changelog_08.rst | 10 ++++++++++ lib/sqlalchemy/orm/descriptor_props.py | 5 +++++ test/orm/test_composites.py | 20 +++++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst index 2cd9b58554..2e1bdc9ad6 100644 --- a/doc/build/changelog/changelog_08.rst +++ b/doc/build/changelog/changelog_08.rst @@ -11,6 +11,16 @@ .. changelog:: :version: 0.8.5 + .. change:: + :tags: bug, orm + :versions: 0.9.0b2 + :tickets: 2889 + + :func:`.composite` will raise an informative error message when the + columns/attribute (names) passed don't resolve to a Column or mapped + attribute (such as an erroneous tuple); previously raised an unbound + local. + .. change:: :tags: bug, declarative :versions: 0.9.0b2 diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py index 1156a140e9..231e531e43 100644 --- a/lib/sqlalchemy/orm/descriptor_props.py +++ b/lib/sqlalchemy/orm/descriptor_props.py @@ -245,6 +245,11 @@ class CompositeProperty(DescriptorProperty): prop = self.parent._columntoproperty[attr] elif isinstance(attr, attributes.InstrumentedAttribute): prop = attr.property + else: + raise sa_exc.ArgumentError( + "Composite expects Column or Column-bound " + "attributes/attribute names as arguments, got: %r" + % (attr,)) props.append(prop) @property diff --git a/test/orm/test_composites.py b/test/orm/test_composites.py index b4abb2dcee..8946b6908d 100644 --- a/test/orm/test_composites.py +++ b/test/orm/test_composites.py @@ -6,7 +6,7 @@ from sqlalchemy import Integer, String, ForeignKey, \ from sqlalchemy.testing.schema import Table, Column from sqlalchemy.orm import mapper, relationship, \ CompositeProperty, aliased -from sqlalchemy.orm import composite, Session +from sqlalchemy.orm import composite, Session, configure_mappers from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures @@ -739,6 +739,24 @@ class ConfigurationTest(fixtures.MappedTest): }) self._test_roundtrip() + def test_check_prop_type(self): + edge, Edge, Point = (self.tables.edge, + self.classes.Edge, + self.classes.Point) + mapper(Edge, edge, properties={ + 'start': sa.orm.composite(Point, (edge.c.x1,), edge.c.y1), + }) + assert_raises_message( + sa.exc.ArgumentError, + # note that we also are checking that the tuple + # renders here, so the "%" operator in the string needs to + # apply the tuple also + r"Composite expects Column or Column-bound " + "attributes/attribute names as " + "arguments, got: \(Column", + configure_mappers + ) + class ComparatorTest(fixtures.MappedTest, testing.AssertsCompiledSQL): __dialect__ = 'default' -- 2.47.3