[Zope3-checkins] SVN: Zope3/branches/Zope-3.1/ Merged revisions 38059, 38136 from the trunk:

Dmitry Vasiliev dima at hlabs.spb.ru
Fri Sep 2 03:25:19 EDT 2005


Log message for revision 38234:
  Merged revisions 38059, 38136 from the trunk:
  
  Rev 38059:
      Removed duplicate and unused interface
  
  Rev 38136:
      Fixed issue #445: gadflyDA not full implementation
  

Changed:
  U   Zope3/branches/Zope-3.1/doc/CHANGES.txt
  U   Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py
  U   Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py
  U   Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py
  U   Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_zopecursor.py

-=-
Modified: Zope3/branches/Zope-3.1/doc/CHANGES.txt
===================================================================
--- Zope3/branches/Zope-3.1/doc/CHANGES.txt	2005-09-02 00:40:39 UTC (rev 38233)
+++ Zope3/branches/Zope-3.1/doc/CHANGES.txt	2005-09-02 07:25:19 UTC (rev 38234)
@@ -658,6 +658,8 @@
 
     Bug Fixes
 
+      - Fixed issue #445: gadflyDA not full implementation
+
       - Request factories were not uniformly pluggable.  All are pluggable now
         without having to write a new server.
 

Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py	2005-09-02 00:40:39 UTC (rev 38233)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/__init__.py	2005-09-02 07:25:19 UTC (rev 38234)
@@ -290,21 +290,28 @@
             return self.cursor.execute(operation)
         return self.cursor.execute(operation, parameters)
 
+    def executemany(self, operation, parameters):
+        """Executes an operation, registering the underlying
+        connection with the transaction system.  """
+        operation, parameters = self._prepareOperation(operation, parameters)
+        method = getattr(self.cursor, "executemany", self.cursor.execute)
+        self.connection.registerForTxn()
+        return method(operation, parameters)
+
     def _prepareOperation(self, operation, parameters):
         encoding = self.connection.getTypeInfo().getEncoding()
         if isinstance(operation, unicode):
             operation = operation.encode(encoding)
+        parameters = self._prepareParameters(parameters, encoding)
+        return operation, parameters
 
+    def _prepareParameters(self, parameters, encoding):
         if isinstance(parameters, list):
             for i, v in enumerate(parameters):
                 if isinstance(v, unicode):
                     parameters[i] = v.encode(encoding)
-                elif isinstance(v, tuple):
-                    values = list(v)
-                    for j, v in enumerate(values):
-                        if isinstance(v, unicode):
-                            values[j] = v.encode(encoding)
-                    parameters[i] = tuple(values)
+                else:
+                    parameters[i] = self._prepareParameters(v, encoding)
         elif isinstance(parameters, tuple):
             parameters = list(parameters)
             for i, v in enumerate(parameters):
@@ -315,7 +322,7 @@
             for k, v in parameters.items():
                 if isinstance(v, unicode):
                     parameters[k] = v.encode(encoding)
-        return operation, parameters
+        return parameters
 
     def __getattr__(self, key):
         return getattr(self.cursor, key)

Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py	2005-09-02 00:40:39 UTC (rev 38233)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/interfaces.py	2005-09-02 07:25:19 UTC (rev 38234)
@@ -20,6 +20,7 @@
 from zope.schema import TextLine
 from zope.app.i18n import ZopeMessageIDFactory as _
 
+
 class IDBITypeInfoProvider(Interface):
     """This object can get the Type Info for a particular DBI
     implementation."""
@@ -27,7 +28,6 @@
     def getTypeInfo():
         """Return an IDBITypeInfo object."""
 
-
 class IDBITypeInfo(Interface):
     """Database adapter specific information"""
 
@@ -74,120 +74,6 @@
     def getConverter(type):
         """Return a converter function for field type matching key"""
 
-
-arraysize = 1 # default constant, symbolic
-
-class ICursor(Interface):
-    """DB API ICursor interface"""
-
-    description = Attribute("""This read-only attribute is a sequence of
-        7-item sequences. Each of these sequences contains information
-        describing one result column: (name, type_code, display_size,
-        internal_size, precision, scale, null_ok). This attribute will be None
-        for operations that do not return rows or if the cursor has not had an
-        operation invoked via the executeZZZ() method yet.
-
-        The type_code can be interpreted by comparing it to the Type Objects
-        specified in the section below. """)
-
-    arraysize = Attribute("""This read/write attribute specifies the number of
-        rows to fetch at a time with fetchmany(). It defaults to 1 meaning to
-        fetch a single row at a time.
-
-        Implementations must observe this value with respect to the
-        fetchmany() method, but are free to interact with the database a
-        single row at a time. It may also be used in the implementation of
-        executemany().
-        """)
-
-    def close():
-        """Close the cursor now (rather than whenever __del__ is called).  The
-        cursor will be unusable from this point forward; an Error (or
-        subclass) exception will be raised if any operation is attempted with
-        the cursor.
-        """
-
-    def execute(operation, parameters=None):
-        """Prepare and execute a database operation (query or
-        command). Parameters may be provided as sequence or mapping and will
-        be bound to variables in the operation. Variables are specified in a
-        database-specific notation (see the module's paramstyle attribute for
-        details). [5]
-
-        A reference to the operation will be retained by the cursor. If the
-        same operation object is passed in again, then the cursor can optimize
-        its behavior. This is most effective for algorithms where the same
-        operation is used, but different parameters are bound to it (many
-        times).
-
-        For maximum efficiency when reusing an operation, it is best to use
-        the setinputsizes() method to specify the parameter types and sizes
-        ahead of time. It is legal for a parameter to not match the predefined
-        information; the implementation should compensate, possibly with a
-        loss of efficiency.
-
-        The parameters may also be specified as list of tuples to e.g. insert
-        multiple rows in a single operation, but this kind of usage is
-        depreciated: executemany() should be used instead.
-
-        Return values are not defined.
-        """
-
-
-    def executemany(operation, seq_of_parameters):
-        """Prepare a database operation (query or command) and then execute it
-        against all parameter sequences or mappings found in the sequence
-        seq_of_parameters.
-
-        Modules are free to implement this method using multiple calls to the
-        execute() method or by using array operations to have the database
-        process the sequence as a whole in one call.
-
-        The same comments as for execute() also apply accordingly to this
-        method.
-
-        Return values are not defined.
-        """
-
-    def fetchone():
-        """Fetch the next row of a query result set, returning a single
-        sequence, or None when no more data is available.
-
-        An Error (or subclass) exception is raised if the previous call to
-        executeZZZ() did not produce any result set or no call was issued yet.
-        """
-
-    def fetchmany(size=arraysize):
-        """Fetch the next set of rows of a query result, returning a sequence
-        of sequences (e.g. a list of tuples). An empty sequence is returned
-        when no more rows are available.
-
-        The number of rows to fetch per call is specified by the parameter. If
-        it is not given, the cursor's arraysize determines the number of rows
-        to be fetched. The method should try to fetch as many rows as
-        indicated by the size parameter. If this is not possible due to the
-        specified number of rows not being available, fewer rows may be
-        returned.
-
-        An Error (or subclass) exception is raised if the previous call to
-        executeZZZ() did not produce any result set or no call was issued yet.
-
-        Note there are performance considerations involved with the size
-        parameter. For optimal performance, it is usually best to use the
-        arraysize attribute. If the size parameter is used, then it is best
-        for it to retain the same value from one fetchmany() call to the next.
-        """
-
-    def fetchall():
-        """Fetch all (remaining) rows of a query result, returning them as a
-        sequence of sequences (e.g. a list of tuples). Note that the cursor's
-        arraysize attribute can affect the performance of this operation.
-
-        An Error (or subclass) exception is raised if the previous call to
-        executeZZZ() did not produce any result set or no call was issued yet.
-        """
-
-
 class IResultSet(Interface):
     """Holds results, and allows iteration."""
 
@@ -207,6 +93,7 @@
     def __str__(self):
         return self.message
 
+arraysize = 1 # default constant, symbolic
 
 class IDBICursor(Interface):
     """DB API ICursor interface"""
@@ -264,7 +151,6 @@
         Return values are not defined.
         """
 
-
     def executemany(operation, seq_of_parameters):
         """Prepare a database operation (query or command) and then execute it
         against all parameter sequences or mappings found in the sequence
@@ -318,12 +204,11 @@
         executeZZZ() did not produce any result set or no call was issued yet.
         """
 
-
 class IDBIConnection(Interface):
     """A DB-API based Interface """
 
     def cursor():
-        """Return a new ICursor Object using the connection.
+        """Return a new IDBICursor Object using the connection.
 
         If the database does not provide a direct cursor concept, the module
         will have to emulate cursors using other means to the extent needed by
@@ -351,7 +236,6 @@
         attempted with the connection. The same applies to all cursor objects
         trying to use the connection.  """
 
-
 class ISQLCommand(Interface):
     """Static SQL commands."""
 
@@ -364,8 +248,6 @@
     def __call__():
         """Execute an sql query and return a result object if appropriate"""
 
-
-
 class IZopeDatabaseAdapter(IDBITypeInfo):
     """Interface for persistent object that returns
     volatile IZopeConnections."""
@@ -413,7 +295,6 @@
     """Database adapters with management functions
     """
 
-
 class IZopeConnection(IDBIConnection, IDBITypeInfoProvider):
 
     # An implementation of this object will be exposed to the
@@ -431,20 +312,19 @@
         manager.
         """
 
-
 class IZopeCursor(IDBICursor):
-    """An ICursor that integrates with Zope's transactions"""
+    """An IDBICursor that integrates with Zope's transactions"""
 
     def execute(operation, parameters=None):
         """Executes an operation, registering the underlying connection with
         the transaction system.
 
-        See ICursor for more detailed execute information.
+        See IDBICursor for more detailed execute information.
         """
 
-    def executemany(operation, seq_of_parameters=None):
+    def executemany(operation, seq_of_parameters):
         """Executes an operation, registering the underlying connection with
         the transaction system.
 
-        See ICursor for more detailed executemany information.
+        See IDBICursor for more detailed executemany information.
         """

Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py	2005-09-02 00:40:39 UTC (rev 38233)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_gadflyadapter.py	2005-09-02 07:25:19 UTC (rev 38234)
@@ -19,9 +19,13 @@
 import tempfile
 from unittest import TestCase, TestSuite, main, makeSuite
 
+from zope.interface.verify import verifyObject
+
 from zope.app.rdb import DatabaseAdapterError
+from zope.app.rdb.interfaces import IZopeConnection, IZopeCursor
 from zope.app.rdb.gadflyda import GadflyAdapter, setGadflyRoot
 
+
 class GadflyTestBase(TestCase):
 
     def setUp(self):
@@ -42,8 +46,7 @@
         return self.tempdir
 
     def _create(self, *args):
-        obj = GadflyAdapter(*args)
-        return obj
+        return GadflyAdapter(*args)
 
 
 class TestGadflyAdapter(GadflyTestBase):
@@ -131,7 +134,14 @@
         conn = a._connection_factory()
         conn.rollback()         # is it really a connection?
 
+    def test__interfaces(self):
+        a = self._create("dbi://demo")
+        connection = a()
+        verifyObject(IZopeConnection, connection)
+        cursor = connection.cursor()
+        verifyObject(IZopeCursor, cursor)
 
+
 def test_suite():
     return TestSuite((
         makeSuite(TestGadflyAdapter),

Modified: Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_zopecursor.py
===================================================================
--- Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_zopecursor.py	2005-09-02 00:40:39 UTC (rev 38233)
+++ Zope3/branches/Zope-3.1/src/zope/app/rdb/tests/test_zopecursor.py	2005-09-02 07:25:19 UTC (rev 38234)
@@ -25,7 +25,11 @@
     def cursor(self):
         return MyCursorStub()
 
+class MyConnectionStub2(ConnectionStub):
+    def cursor(self):
+        return MyCursorStub2()
 
+
 raw       = [['mano',      2,    'buvo batai'],
              ['dingo',     1,    'nerandu'],
              ['as su',     1,    'batuku'],
@@ -44,6 +48,7 @@
     description = ((None, 'string'), (None, 'int'), (None, 'foo'))
 
     def execute(self, query, args=None):
+        self.method = "execute"
         self.query = query
         self.args = args
 
@@ -59,7 +64,14 @@
     def fetchmany(self, size=2):
         return self._raw[:size]
 
+class MyCursorStub2(MyCursorStub):
 
+    def executemany(self, query, args):
+        self.method = "executemany"
+        self.query = query
+        self.args = args
+
+
 class MyTypeInfoStub(TypeInfoStub):
 
     def getConverter(self, type):
@@ -125,6 +137,19 @@
                    'got      %r,\n'
                    'expected %r' % (results, expected))
 
+    def test_cursor_executemany(self):
+        self.cursor.executemany("SELECT", [("A",), ("B",)])
+        self.assertEqual("execute", self.cursor.cursor.method)
+        self.assertEqual("SELECT", self.cursor.cursor.query)
+        self.assertEqual([("A",), ("B",)], self.cursor.cursor.args)
+
+        zc = ZopeConnection(MyConnectionStub2(), self.typeInfo)
+        self.cursor = ZopeCursor(zc.conn.cursor(), zc)
+        self.cursor.executemany("SELECT", [("A",), ("B",)])
+        self.assertEqual("executemany", self.cursor.cursor.method)
+        self.assertEqual("SELECT", self.cursor.cursor.query)
+        self.assertEqual([("A",), ("B",)], self.cursor.cursor.args)
+
     def test_cursor_query_encoding(self):
         self.cursor.execute(u'\u0422\u0435\u0441\u0442')
         self.assertEqual('\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82',
@@ -151,6 +176,15 @@
             [(u'\u0422\u0435\u0441\u0442',)])
         self.assertEqual([('\xd2\xe5\xf1\xf2',)], self.cursor.cursor.args)
 
+        self.cursor.execute("SELECT * FROM table",
+            [[u'\u0422\u0435\u0441\u0442']])
+        self.assertEqual([['\xd2\xe5\xf1\xf2']], self.cursor.cursor.args)
+
+        self.cursor.execute("SELECT * FROM table",
+            [{"value": u'\u0422\u0435\u0441\u0442'}])
+        self.assertEqual([{"value": '\xd2\xe5\xf1\xf2'}],
+            self.cursor.cursor.args)
+
     def test_cursor_dict_args_encoding(self):
         self.typeInfo.setEncoding("windows-1251")
         self.cursor.execute("SELECT * FROM table",



More information about the Zope3-Checkins mailing list