]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Added a fully descriptive error message for the
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 28 Feb 2011 17:47:04 +0000 (12:47 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 28 Feb 2011 17:47:04 +0000 (12:47 -0500)
case where Column is subclassed and _make_proxy()
fails to make a copy due to TypeError on the
constructor.   The method _constructor should
be implemented in this case.

CHANGES
lib/sqlalchemy/__init__.py
lib/sqlalchemy/schema.py
test/sql/test_metadata.py

diff --git a/CHANGES b/CHANGES
index 25c955ec25b1c498e3c2db9533e0d077c3702462..b6b6b3bf8e9a0a309afd54bc007ca36660fc9137 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,15 @@
 =======
 CHANGES
 =======
+0.7.0b3
+=======
+- sql
+  - Added a fully descriptive error message for the
+    case where Column is subclassed and _make_proxy()
+    fails to make a copy due to TypeError on the
+    constructor.   The method _constructor should
+    be implemented in this case.
+
 0.7.0b2
 ========
 - orm
index a3c0c32388c5b33d7f43d09c20eda74a792d1af1..2b4cfde0fce19d98f49bcb13156110c665191ad0 100644 (file)
@@ -116,6 +116,6 @@ from sqlalchemy.engine import create_engine, engine_from_config
 __all__ = sorted(name for name, obj in locals().items()
                  if not (name.startswith('_') or inspect.ismodule(obj)))
 
-__version__ = '0.7b2'
+__version__ = '0.7b3'
 
 del inspect, sys
index 80d6018b843e4accba1aa17859f5d6f944c9d3c5..223643c804b5b618580600591c691bc3e23483b0 100644 (file)
@@ -904,13 +904,32 @@ class Column(SchemaItem, expression.ColumnClause):
             raise exc.InvalidRequestError("Cannot initialize a sub-selectable"
                     " with this Column object until it's 'name' has "
                     "been assigned.")
-        c = self._constructor(
-            name or self.name, 
-            self.type, 
-            key = name or self.key, 
-            primary_key = self.primary_key, 
-            nullable = self.nullable, 
-            quote=self.quote, _proxies=[self], *fk)
+        try:
+            c = self._constructor(
+                name or self.name, 
+                self.type, 
+                key = name or self.key, 
+                primary_key = self.primary_key, 
+                nullable = self.nullable, 
+                quote=self.quote, _proxies=[self], *fk)
+        except TypeError, e:
+            # Py3K
+            #raise TypeError(
+            #    "Could not create a copy of this %r object.  "
+            #    "Ensure the class includes a _constructor() "
+            #    "attribute or method which accepts the "
+            #    "standard Column constructor arguments, or "
+            #    "references the Column class itself." % self.__class__) from e
+            # Py2K
+            raise TypeError(
+                "Could not create a copy of this %r object.  "
+                "Ensure the class includes a _constructor() "
+                "attribute or method which accepts the "
+                "standard Column constructor arguments, or "
+                "references the Column class itself. "
+                "Original error: %s" % (self.__class__, e))
+            # end Py2K
+
         c.table = selectable
         selectable._columns.add(c)
         if self.primary_key:
index ace3b69d5a3060a84ddfca6795d1d34cff9339b6..4c0abd1f0faf4f28d5eb245f682530d092cb0ff5 100644 (file)
@@ -547,10 +547,10 @@ class ConstraintTest(TestBase):
         assert s1.c.a.references(t1.c.a)
         assert not s1.c.a.references(t1.c.b)
 
-class ColumnDefinitionTest(TestBase):
+class ColumnDefinitionTest(AssertsCompiledSQL, TestBase):
     """Test Column() construction."""
 
-    # flesh this out with explicit coverage...
+    __dialect__ = 'default'
 
     def columns(self):
         return [ Column(Integer),
@@ -598,6 +598,78 @@ class ColumnDefinitionTest(TestBase):
         assert_raises(exc.ArgumentError, Column, 'foo', Integer,
                           type_=Integer())
 
+    def test_custom_subclass_proxy(self):
+        """test proxy generation of a Column subclass, can be compiled."""
+
+        from sqlalchemy.schema import Column
+        from sqlalchemy.ext.compiler import compiles
+        from sqlalchemy.sql import select
+
+        class MyColumn(Column):
+            def _constructor(self, name, type, **kw):
+                kw['name'] = name
+                return MyColumn(type, **kw)
+
+            def __init__(self, type, **kw):
+                Column.__init__(self, type, **kw)
+
+            def my_goofy_thing(self):
+                return "hi"
+
+        @compiles(MyColumn)
+        def goofy(element, compiler, **kw):
+            s = compiler.visit_column(element, **kw)
+            return s + "-"
+
+        id = MyColumn(Integer, primary_key=True)
+        id.name = 'id'
+        name = MyColumn(String)
+        name.name = 'name'
+        t1 = Table('foo', MetaData(),
+            id,
+            name
+        )
+
+        # goofy thing
+        eq_(t1.c.name.my_goofy_thing(), "hi")
+
+        # create proxy
+        s = select([t1.select().alias()])
+
+        # proxy has goofy thing
+        eq_(s.c.name.my_goofy_thing(), "hi")
+
+        # compile works
+        self.assert_compile(
+            select([t1.select().alias()]),
+            "SELECT anon_1.id-, anon_1.name- FROM "
+            "(SELECT foo.id- AS id, foo.name- AS name "
+            "FROM foo) AS anon_1",
+        )
+
+    def test_custom_subclass_proxy_typeerror(self):
+        from sqlalchemy.schema import Column
+        from sqlalchemy.sql import select
+
+        class MyColumn(Column):
+            def __init__(self, type, **kw):
+                Column.__init__(self, type, **kw)
+
+        id = MyColumn(Integer, primary_key=True)
+        id.name = 'id'
+        name = MyColumn(String)
+        name.name = 'name'
+        t1 = Table('foo', MetaData(),
+            id,
+            name
+        )
+        assert_raises_message(
+            TypeError,
+            "Could not create a copy of this <class "
+            "'test.sql.test_metadata.MyColumn'> "
+            "object.  Ensure the class includes a _constructor()",
+            getattr, select([t1.select().alias()]), 'c'
+        )
 
 class ColumnOptionsTest(TestBase):