[pypy-svn] r69710 - in pypy/trunk/pypy/module/oracle: . test

afa at codespeak.net afa at codespeak.net
Fri Nov 27 19:30:29 CET 2009


Author: afa
Date: Fri Nov 27 19:30:28 2009
New Revision: 69710

Modified:
   pypy/trunk/pypy/module/oracle/config.py
   pypy/trunk/pypy/module/oracle/interp_connect.py
   pypy/trunk/pypy/module/oracle/interp_environ.py
   pypy/trunk/pypy/module/oracle/interp_object.py
   pypy/trunk/pypy/module/oracle/interp_pool.py
   pypy/trunk/pypy/module/oracle/interp_variable.py
   pypy/trunk/pypy/module/oracle/roci.py
   pypy/trunk/pypy/module/oracle/test/test_connect.py
Log:
Now the cx_Oracle module translates, compiles, and works!
Tested on Windows.

Support for ucs4 builds of pypy is likely incomplete.
Likewise, the "full unicode" mode of cx_Oracle is not implemented.
And the cx_Oracle test suite itself is not complete...

The module works well enough for most usages, though.


Modified: pypy/trunk/pypy/module/oracle/config.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/config.py	(original)
+++ pypy/trunk/pypy/module/oracle/config.py	Fri Nov 27 19:30:28 2009
@@ -26,24 +26,28 @@
     class StringBuffer:
         "Fill a char* buffer with data, suitable to pass to Oracle functions"
         def __init__(self):
-            pass
+            self.ptr = lltype.nullptr(roci.oratext.TO)
+            self.size = 0
 
-        def fill(self, space, w_string):
-            if w_string is None or space.is_w(w_string, space.w_None):
+        def fill(self, space, w_value):
+            if w_value is None or space.is_w(w_value, space.w_None):
                 self.clear()
             else:
-                self.ptr = string_w(space, w_string)
-                self.size = len(self.ptr)
+                strvalue = space.str_w(w_value)
+                self.ptr = rffi.str2charp(strvalue)
+                self.size = len(strvalue)
 
-        def fill_with_unicode(self, space, w_unicode):
-            if w_unicode is None or space.is_w(w_unicode, space.w_None):
+        def fill_with_unicode(self, space, w_value):
+            if w_value is None or space.is_w(w_value, space.w_None):
                 self.clear()
             else:
                 # XXX ucs2 only probably
-                unistr = space.unicode_w(w_unicode)
-                self.ptr = rffi.cast(roci.oratext, rffi.unicode2wcharp(unistr))
-                self.size = len(unistr) * 2
+                univalue = space.unicode_w(w_value)
+                self.ptr = rffi.cast(roci.oratext, rffi.unicode2wcharp(univalue))
+                self.size = len(univalue) * 2
 
         def clear(self):
-            self.ptr = None
+            if self.ptr:
+                rffi.free_charp(self.ptr)
+                self.ptr = lltype.nullptr(roci.oratext.TO)
             self.size = 0

Modified: pypy/trunk/pypy/module/oracle/interp_connect.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/interp_connect.py	(original)
+++ pypy/trunk/pypy/module/oracle/interp_connect.py	Fri Nov 27 19:30:28 2009
@@ -21,8 +21,8 @@
         self.environment = None
         self.autocommit = False
 
-        self.sessionHandle = None
-        self.serverHandle = None
+        self.sessionHandle = lltype.nullptr(roci.OCISession.TO)
+        self.serverHandle = lltype.nullptr(roci.OCIServer.TO)
 
         self.w_inputTypeHandler = None
         self.w_outputTypeHandler = None
@@ -41,7 +41,7 @@
                   twophase=False,
                   events=False,
                   w_cclass=Null,
-                  purity=False,
+                  purity=0,
                   w_newpassword=Null):
         self = space.allocate_instance(W_Connection, w_subtype)
         W_Connection.__init__(self)
@@ -83,7 +83,7 @@
                              W_Root,
                              bool, bool, bool,
                              W_Root,
-                             bool,
+                             int,
                              W_Root]
 
     def __del__(self):
@@ -244,7 +244,7 @@
         rather than using the low level interface for connecting."""
 
         proxyCredentials = False
-        authInfo = None
+        authInfo = lltype.nullptr(roci.OCIAuthInfo.TO)
 
         if pool:
             w_dbname = pool.w_name
@@ -261,7 +261,7 @@
         # set up authorization handle, if needed
         if not pool or w_cclass or proxyCredentials:
             # create authorization handle
-            handleptr = lltype.malloc(rffi.CArrayPtr(roci.OCIServer).TO,
+            handleptr = lltype.malloc(rffi.CArrayPtr(roci.OCIAuthInfo).TO,
                                       1, flavor='raw')
             try:
                 status = roci.OCIHandleAlloc(
@@ -287,7 +287,7 @@
                         authInfo,
                         roci.OCI_HTYPE_AUTHINFO,
                         stringBuffer.ptr, stringBuffer.size,
-                        roci.OCI_ATTR_PASSWORD,
+                        roci.OCI_ATTR_USERNAME,
                         self.environment.errorHandle)
                     self.environment.checkForError(
                         status, "Connection_GetConnection(): set user name")
@@ -303,7 +303,7 @@
                         authInfo,
                         roci.OCI_HTYPE_AUTHINFO,
                         stringBuffer.ptr, stringBuffer.size,
-                        roci.OCI_ATTR_USERNAME,
+                        roci.OCI_ATTR_PASSWORD,
                         self.environment.errorHandle)
                     self.environment.checkForError(
                         status, "Connection_GetConnection(): set password")
@@ -334,12 +334,13 @@
             if purity != roci.OCI_ATTR_PURITY_DEFAULT:
                 purityptr = lltype.malloc(rffi.CArrayPtr(roci.ub4).TO,
                                           1, flavor='raw')
-                purityptr[0] = purity
+                purityptr[0] = rffi.cast(roci.ub4, purity)
                 try:
                     status = roci.OCIAttrSet(
                         authInfo,
                         roci.OCI_HTYPE_AUTHINFO,
-                        purityptr, rffi.sizeof(roci.ub4),
+                        rffi.cast(roci.dvoidp, purityptr),
+                        rffi.sizeof(roci.ub4),
                         roci.OCI_ATTR_PURITY,
                         self.environment.errorHandle)
                     self.environment.checkForError(

Modified: pypy/trunk/pypy/module/oracle/interp_environ.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/interp_environ.py	(original)
+++ pypy/trunk/pypy/module/oracle/interp_environ.py	Fri Nov 27 19:30:28 2009
@@ -47,8 +47,8 @@
         raise OperationError(get(self.space).w_DatabaseError,
                              self.space.wrap(error))
 
-    @classmethod
-    def create(cls, space, threaded, events):
+    @staticmethod
+    def create(space, threaded, events):
         "Create a new environment object from scratch"
         mode = roci.OCI_OBJECT
         if threaded:
@@ -80,7 +80,7 @@
             lltype.free(handleptr, flavor='raw')
 
         try:
-            newenv = cls(space, handle)
+            newenv = Environment(space, handle)
         except:
             roci.OCIHandleFree(handle, roci.OCI_HTYPE_ENV)
             raise
@@ -92,7 +92,7 @@
     def clone(self):
         """Clone an existing environment.
         used when acquiring a connection from a session pool, for example."""
-        newenv = type(self)(self.space, self.handle)
+        newenv = Environment(self.space, self.handle)
         newenv.maxBytesPerCharacter = self.maxBytesPerCharacter
         newenv.maxStringBytes = self.maxStringBytes
         return newenv

Modified: pypy/trunk/pypy/module/oracle/interp_object.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/interp_object.py	(original)
+++ pypy/trunk/pypy/module/oracle/interp_object.py	Fri Nov 27 19:30:28 2009
@@ -7,10 +7,11 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 
 from pypy.module.oracle import roci, config, transform
+from pypy.module.oracle.interp_error import get
 
 class W_ObjectType(Wrappable):
     def __init__(self, connection, param):
-        self.tdo = None
+        self.tdo = lltype.nullptr(roci.dvoidp.TO)
         self.environment = connection.environment
         self.isCollection = False
         self.initialize(connection, param)
@@ -153,7 +154,7 @@
                 self.environment.errorHandle)
             self.environment.checkForError(
                 status, "ObjectType_Describe(): get type code")
-            typeCode = typecodeptr[0]
+            typeCode = rffi.cast(lltype.Signed, typecodeptr[0])
         finally:
             lltype.free(typecodeptr, flavor='raw')
 
@@ -206,7 +207,7 @@
                     self.environment.errorHandle)
                 self.environment.checkForError(
                     status, "ObjectType_Describe(): get element type code")
-                self.elementTypeCode = typecodeptr[0]
+                self.elementTypeCode = rffi.cast(lltype.Signed, typecodeptr[0])
             finally:
                 lltype.free(typecodeptr, flavor='raw')
 
@@ -318,7 +319,7 @@
                 connection.environment.errorHandle)
             connection.environment.checkForError(
                 status, "ObjectType_Describe(): get type code")
-            self.typeCode = typecodeptr[0]
+            self.typeCode = rffi.cast(lltype.Signed, typecodeptr[0])
         finally:
             lltype.free(typecodeptr, flavor='raw')
 
@@ -386,7 +387,8 @@
             # determine the proper null indicator
             valueIndicator = valueindicatorptr[0]
             if not valueIndicator:
-                valueIndicator = scalarvalueindicatorptr
+                valueIndicator = rffi.cast(roci.dvoidp,
+                                           scalarvalueindicatorptr)
             value = valueptr[0]
 
             return convertObject(
@@ -413,8 +415,13 @@
 
 def convertObject(space, environment, typeCode,
                   value, indicator, var, subtype):
+
     # null values returned as None
-    if rffi.cast(roci.Ptr(roci.OCIInd), indicator)[0] == roci.OCI_IND_NULL:
+    if (rffi.cast(lltype.Signed,
+                  rffi.cast(roci.Ptr(roci.OCIInd),
+                            indicator)[0])
+        ==
+        rffi.cast(lltype.Signed, roci.OCI_IND_NULL)):
         return space.w_None
 
     if typeCode in (roci.OCI_TYPECODE_CHAR,
@@ -435,10 +442,10 @@
         dateValue = rffi.cast(roci.Ptr(roci.OCIDateTime), value)
         return transform.OracleTimestampToPythonDate(environment, dateValue)
     elif typeCode == roci.OCI_TYPECODE_OBJECT:
-        return space.wrap(W_ExternalObject(var, subType, value, indicator,
+        return space.wrap(W_ExternalObject(var, subtype, value, indicator,
                                            isIndependent=False))
     elif typeCode == roci.OCI_TYPECODE_NAMEDCOLLECTION:
-        return convertCollection(space, environment, value, var, subType)
+        return convertCollection(space, environment, value, var, subtype)
 
     raise OperationError(
         get(space).w_NotSupportedError,

Modified: pypy/trunk/pypy/module/oracle/interp_pool.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/interp_pool.py	(original)
+++ pypy/trunk/pypy/module/oracle/interp_pool.py	Fri Nov 27 19:30:28 2009
@@ -29,18 +29,20 @@
         W_SessionPool.__init__(self)
 
         if w_connectiontype is not None:
-            if not space.is_true(space.issubtype(w_value,
-                                                 interp_connect.W_Connection)):
+            if not space.is_true(space.issubtype(w_connectiontype,
+                                                 get(space).w_Connection)):
                 raise OperationError(
                     interp_error.get(space).w_ProgrammingError,
                     space.wrap(
                         "connectiontype must be a subclass of Connection"))
+            self.w_connectionType = w_connectiontype
+        else:
+            self.w_connectionType = get(space).w_Connection
+
         self.w_username = w_user
         self.w_password = w_password
         self.w_tnsentry = w_dsn
 
-        from pypy.module.oracle.interp_connect import W_Connection
-        self.w_connectionType = w_connectiontype or get(space).w_Connection
         self.minSessions = min
         self.maxSessions = max
         self.sessionIncrement = increment
@@ -173,7 +175,7 @@
 
         # ensure that the connection behaves as closed
         connection.sessionPool = None
-        connection.handle = None
+        connection.handle = lltype.nullptr(roci.OCISvcCtx.TO)
 
 def computedProperty(oci_attr_code, oci_value_type):
     def fget(space, self):
@@ -191,7 +193,7 @@
             return space.wrap(valueptr[0])
         finally:
             lltype.free(valueptr, flavor='raw')
-    return GetSetProperty(fget)
+    return GetSetProperty(fget, cls=W_SessionPool)
 
 W_SessionPool.typedef = TypeDef(
     "SessionPool",

Modified: pypy/trunk/pypy/module/oracle/interp_variable.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/interp_variable.py	(original)
+++ pypy/trunk/pypy/module/oracle/interp_variable.py	Fri Nov 27 19:30:28 2009
@@ -476,32 +476,28 @@
 
     def getValueProc(self, space, pos):
         offset = pos * self.bufferSize
+        dataptr = rffi.ptradd(self.data, offset)
         length = rffi.cast(lltype.Signed, self.actualLength[pos])
 
-        l = []
         i = 0
         if config.WITH_UNICODE:
             if isinstance(self, VT_Binary):
-                while i < length:
-                    l.append(self.data[offset + i])
-                    i += 1
-                return space.wrap(''.join(l))
+                return space.wrap(rffi.charpsize2str(dataptr, length))
             else:
+                l = []
                 while i < length:
-                    l.append(unichr((ord(self.data[offset + i + 1]) << 8) +
-                                    ord(self.data[offset + i])))
+                    l.append(unichr((ord(dataptr[i + 1]) << 8) +
+                                    ord(dataptr[i])))
                     i += 2
                 return space.wrap(u''.join(l))
         else:
             if self.charsetForm == roci.SQLCS_IMPLICIT:
-                while i < length:
-                    l.append(self.data[offset + i])
-                    i += 1
-                return space.wrap(''.join(l))
+                return space.wrap(rffi.charpsize2str(dataptr, length))
             else:
+                l = []
                 while i < length:
-                    l.append(unichr((ord(self.data[offset + i + 1]) << 8) +
-                                    ord(self.data[offset + i])))
+                    l.append(unichr((ord(dataptr[i + 1]) << 8) +
+                                    ord(dataptr[i])))
                     i += 2
                 return space.wrap(u''.join(l))
 
@@ -1007,7 +1003,7 @@
     temporaryLobType = roci.OCI_TEMP_CLOB
 
     def initialize(self, space, cursor):
-        super(W_LobVariable, self).initialize(space, cursor)
+        W_VariableWithDescriptor.initialize(self, space, cursor)
         self.connection = cursor.connection
 
     def ensureTemporary(self, space, pos):
@@ -1060,7 +1056,8 @@
             self.environment.checkForError(
                 status,
                 "LobVar_GetLength()")
-            return int(lengthptr[0]) # XXX test overflow
+            return rffi.cast(lltype.Signed,
+                             lengthptr[0]) # XXX test overflow
         finally:
             lltype.free(lengthptr, flavor='raw')
 
@@ -1099,7 +1096,8 @@
             self.environment.checkForError(
                 status,
                 "LobVar_Read()")
-            amount = int(amountptr[0]) # XXX test overflow
+            amount = rffi.cast(lltype.Signed,
+                               amountptr[0]) # XXX test overflow
             value = rffi.str_from_buffer(raw_buffer, gc_buffer, bufferSize, amount)
             return space.wrap(value)
         finally:
@@ -1115,7 +1113,7 @@
         try:
             # nothing to do if no data to write
             if databuf.size == 0:
-                return
+                return 0
 
             status = roci.OCILobWrite(
                 self.connection.handle,
@@ -1158,11 +1156,17 @@
             space.wrap("BFILEs are read only"))
 
     def read(self, space, pos, offset, amount):
-        self.fileOpen()
+        self.openFile()
         try:
             return W_LobVariable.read(self, space, pos, offset, amount)
         finally:
-            self.fileClose()
+            self.closeFile()
+
+    def openFile(self):
+        pass # XXX
+
+    def closeFile(self):
+        pass # XXX
 
 class VT_Cursor(W_Variable):
     oracleType = roci.SQLT_RSET
@@ -1217,7 +1221,7 @@
     size = rffi.sizeof(roci.dvoidp)
     canBeInArray = False
 
-    objectIndicator = None
+    objectIndicator = lltype.nullptr(rffi.CArrayPtr(roci.dvoidp).TO)
 
     def initialize(self, space, cursor):
         self.connection = cursor.connection
@@ -1260,7 +1264,9 @@
         # look at our own indicator array
         if not self.objectIndicator[pos]:
             return True
-        return (rffi.cast(roci.Ptr(roci.OCIInd), self.objectIndicator[pos])[0]
+        return (rffi.cast(lltype.Signed,
+                          rffi.cast(roci.Ptr(roci.OCIInd),
+                                    self.objectIndicator[pos])[0])
                 ==
                 rffi.cast(lltype.Signed, roci.OCI_IND_NULL))
 

Modified: pypy/trunk/pypy/module/oracle/roci.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/roci.py	(original)
+++ pypy/trunk/pypy/module/oracle/roci.py	Fri Nov 27 19:30:28 2009
@@ -64,7 +64,7 @@
     OCI_SUCCESS OCI_SUCCESS_WITH_INFO OCI_INVALID_HANDLE OCI_NO_DATA
     OCI_HTYPE_ERROR OCI_HTYPE_SVCCTX OCI_HTYPE_SERVER OCI_HTYPE_SESSION
     OCI_HTYPE_STMT OCI_HTYPE_DESCRIBE OCI_HTYPE_BIND OCI_HTYPE_DEFINE
-    OCI_HTYPE_ENV OCI_HTYPE_SPOOL OCI_HTYPE_AUTHINFO
+    OCI_HTYPE_ENV OCI_HTYPE_SPOOL OCI_HTYPE_AUTHINFO OCI_ATTR_CONNECTION_CLASS
     OCI_DTYPE_PARAM OCI_DTYPE_TIMESTAMP OCI_DTYPE_INTERVAL_DS OCI_DTYPE_LOB
     OCI_CRED_RDBMS OCI_CRED_EXT OCI_SPOOL_ATTRVAL_NOWAIT
     OCI_ATTR_SERVER OCI_ATTR_SESSION OCI_ATTR_USERNAME OCI_ATTR_PASSWORD
@@ -99,7 +99,7 @@
     OCI_NLS_MAXBUFSZ OCI_NLS_CS_ORA_TO_IANA OCI_UTF16ID
     OCI_SPC_STMTCACHE OCI_SPC_HOMOGENEOUS
     OCI_SESSGET_SPOOL OCI_SESSGET_CREDPROXY OCI_SESSGET_STMTCACHE
-    OCI_SESSRLS_DROPSESS OCI_ATTR_PURITY_DEFAULT
+    OCI_SESSGET_CREDEXT OCI_SESSRLS_DROPSESS OCI_ATTR_PURITY_DEFAULT
     '''.split()
 
     for c in constants:

Modified: pypy/trunk/pypy/module/oracle/test/test_connect.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/test/test_connect.py	(original)
+++ pypy/trunk/pypy/module/oracle/test/test_connect.py	Fri Nov 27 19:30:28 2009
@@ -158,5 +158,6 @@
                                   2, 8, 3, homogeneous=False)
         assert pool.homogeneous is False
         e = raises(oracle.DatabaseError, pool.acquire, user="proxyuser")
+        # ORA-01017: invalid username/password; logon denied
         # ORA-28150: proxy not authorized to connect as client
-        assert e.value[0].code == 28150
+        assert e.value[0].code in (1017, 28150)



More information about the Pypy-commit mailing list