]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Implemented sequence check capability for the C
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Nov 2010 16:40:23 +0000 (11:40 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Nov 2010 16:40:23 +0000 (11:40 -0500)
version of RowProxy, as well as 2.7 style
"collections.Sequence" registration for RowProxy.
[ticket:1871]

CHANGES
lib/sqlalchemy/cextension/resultproxy.c
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/test/requires.py
test/aaa_profiling/test_resultset.py
test/engine/test_execute.py

diff --git a/CHANGES b/CHANGES
index 65715de54bc60a08607876a6cab183fbe4783e2c..1b4f7cd348d375f5d369fb6984cf38ef358bb95b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -19,6 +19,12 @@ CHANGES
     is an outer join, thus allowing primary rows without
     a referenced child row to be correctly returned
     in results.  [ticket:1954]
+
+- engine
+  - Implemented sequence check capability for the C 
+    version of RowProxy, as well as 2.7 style 
+    "collections.Sequence" registration for RowProxy.
+    [ticket:1871]
     
 - mysql
   - Fixed error handling for Jython + zxjdbc, such that 
index 7404b9ed20977a0cc86a2d50b7ff4f3241976bfe..73e12734570eb379c9b95fbf286ea93b433dd249 100644 (file)
@@ -326,6 +326,12 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
     }
 }
 
+static PyObject *
+BaseRowProxy_getitem(PyObject *self, Py_ssize_t i)
+{
+    return BaseRowProxy_subscript((BaseRowProxy*)self, PyInt_FromSsize_t(i));
+}
+
 static PyObject *
 BaseRowProxy_getattro(BaseRowProxy *self, PyObject *name)
 {
@@ -506,7 +512,7 @@ static PySequenceMethods BaseRowProxy_as_sequence = {
     (lenfunc)BaseRowProxy_length,   /* sq_length */
     0,                              /* sq_concat */
     0,                              /* sq_repeat */
-    0,                              /* sq_item */
+    (ssizeargfunc)BaseRowProxy_getitem,          /* sq_item */
     0,                              /* sq_slice */
     0,                              /* sq_ass_item */
     0,                              /* sq_ass_slice */
index ef402ceea48691380d850fbd9ab778b3e554a013..10b2b67827e6f6653d0f328d1b68a8222692da69 100644 (file)
@@ -2090,6 +2090,14 @@ class RowProxy(BaseRowProxy):
     def itervalues(self):
         return iter(self)
 
+try:
+    # Register RowProxy with Sequence, 
+    # so sequence protocol is implemented
+    import collections
+    collections.Sequence.register(RowProxy)
+except ImportError:
+    pass
+    
 
 class ResultMetaData(object):
     """Handle cursor.description, applying additional info from an execution
index 14c548f122aeb1aed63923f809fae6ee62833c75..5b68a18e17df62aa7fecad0ac9c1a7f8218bec3f 100644 (file)
@@ -252,6 +252,12 @@ def sane_rowcount(fn):
         skip_if(lambda: not testing.db.dialect.supports_sane_rowcount)
     )
 
+def cextensions(fn):
+    return _chain_decorators_on(
+        fn,
+        skip_if(lambda: not _has_cextensions(), "C extensions not installed")
+    )
+    
 def dbapi_lastrowid(fn):
     return _chain_decorators_on(
         fn,
@@ -279,7 +285,14 @@ def python2(fn):
             "Python version 2.xx is required."
             )
     )
-    
+
+def _has_cextensions():
+    try:
+        from sqlalchemy import cresultproxy, cprocessors
+        return True
+    except ImportError:
+        return False
+        
 def _has_sqlite():
     from sqlalchemy import create_engine
     try:
index d71b8dab844aab1d61359b82b4af7efb9cdcaa54..bd9d3ae50f20b236e5f3ab84a7db348dec11faf1 100644 (file)
@@ -30,13 +30,13 @@ class ResultSetTest(TestBase, AssertsExecutionResults):
         metadata.drop_all()
 
     @profiling.function_call_count(14416, versions={'2.4': 13214,
-                                   '2.6+cextension': 409})
+                                   '2.6+cextension': 409, '2.7+cextension':438})
     def test_string(self):
         [tuple(row) for row in t.select().execute().fetchall()]
 
     # sqlite3 returns native unicode.  so shouldn't be an increase here.
 
     @profiling.function_call_count(14396, versions={'2.4': 13214,
-                                   '2.6+cextension': 409})
+                                   '2.6+cextension': 409, '2.7+cextension':409})
     def test_unicode(self):
         [tuple(row) for row in t2.select().execute().fetchall()]
index ee5953c7494b940f36e6310909b2c168019e39f8..bbec402b20f95537ebca1248dd1706097aafc318 100644 (file)
@@ -289,6 +289,37 @@ class ResultProxyTest(TestBase):
             assert_raises(AssertionError, t.delete().execute)
         finally:
             engine.dialect.execution_ctx_cls = execution_ctx_cls
+
+    def test_rowproxy_is_sequence(self):
+        import collections
+        from sqlalchemy.engine import RowProxy
+
+        row = RowProxy(object(), ['value'], [None], {'key'
+                         : (None, 0), 0: (None, 0)})
+        assert isinstance(row, collections.Sequence)
+    
+    @testing.requires.cextensions
+    def test_row_c_sequence_check(self):
+        import csv
+        import collections
+        from StringIO import StringIO
+        
+        metadata = MetaData()
+        metadata.bind = 'sqlite://'
+        users = Table('users', metadata,
+            Column('id', Integer, primary_key=True),
+            Column('name', String(40)),
+        )
+        users.create()
+
+        users.insert().execute(name='Test')
+        row = users.select().execute().fetchone()
+
+        s = StringIO()
+        writer = csv.writer(s)
+        # csv performs PySequenceCheck call
+        writer.writerow(row)
+        assert s.getvalue().strip() == '1,Test'
         
 class ProxyConnectionTest(TestBase):