From c2fbe9a80144920a7f82f1de81803f9df3ddb31e Mon Sep 17 00:00:00 2001 From: Anthony Tuininga Date: Thu, 16 Oct 2008 21:37:08 +0000 Subject: [PATCH] Further work toward supporting Python 3.x. --- LongVar.c | 7 ++++--- NumberVar.c | 33 ++++++++++++++++++++++++--------- StringUtils.c | 44 +++++++++++++++++++++++++++++++++++++++++++- StringVar.c | 7 ++++--- Variable.c | 16 +++++++++++----- cx_Oracle.c | 14 +++++++++++--- 6 files changed, 97 insertions(+), 24 deletions(-) diff --git a/LongVar.c b/LongVar.c index 5d8ee73..513b9a1 100644 --- a/LongVar.c +++ b/LongVar.c @@ -130,10 +130,11 @@ static int LongVar_SetValue( if (PyBytes_Check(value)) { if (StringBuffer_FromBytes(&buffer, value) < 0) return -1; - } else if (PyBuffer_Check(value)) { - StringBuffer_Init(&buffer); - if (PyObject_AsReadBuffer(value, &buffer.ptr, &buffer.size) < 0) +#if PY_MAJOR_VERSION < 3 + } else if (cxBinary_Check(value)) { + if (StringBuffer_FromBinary(&buffer, value) < 0) return -1; +#endif } else { PyErr_SetString(PyExc_TypeError, "expecting string or buffer data"); diff --git a/NumberVar.c b/NumberVar.c index 23c8e07..86b5dbe 100644 --- a/NumberVar.c +++ b/NumberVar.c @@ -130,6 +130,7 @@ static udt_VariableType vt_NativeFloat = { #endif +#if PY_MAJOR_VERSION < 3 static udt_VariableType vt_Integer = { (InitializeProc) NULL, (FinalizeProc) NULL, @@ -147,6 +148,7 @@ static udt_VariableType vt_Integer = { 1, // can be copied 1 // can be in array }; +#endif static udt_VariableType vt_LongInteger = { @@ -234,10 +236,13 @@ static int NumberVar_PreDefine( if (Environment_CheckForError(var->environment, status, "NumberVar_PreDefine(): precision") < 0) return -1; - if (scale == 0 && precision > 0 && precision < 10) - var->type = &vt_Integer; - else if (scale == 0 || (scale == -127 && precision == 0)) + if (scale == 0 || (scale == -127 && precision == 0)) { var->type = &vt_LongInteger; +#if PY_MAJOR_VERSION < 3 + if (precision > 0 && precision < 10) + var->type = &vt_Integer; +#endif + } } return 0; @@ -264,6 +269,7 @@ static int NumberVar_SetValueFromBoolean( } +#if PY_MAJOR_VERSION < 3 //----------------------------------------------------------------------------- // NumberVar_SetValueFromInteger() // Set the value of the variable from a Python integer. @@ -282,6 +288,7 @@ static int NumberVar_SetValueFromInteger( return Environment_CheckForError(var->environment, status, "NumberVar_SetValueFromInteger()"); } +#endif //----------------------------------------------------------------------------- @@ -455,15 +462,17 @@ static int NumberVar_SetValue( unsigned pos, // array position to set PyObject *value) // value to set { +#if PY_MAJOR_VERSION < 3 if (PyInt_Check(value)) return NumberVar_SetValueFromInteger(var, pos, value); - else if (PyBool_Check(value)) - return NumberVar_SetValueFromBoolean(var, pos, value); - else if (PyFloat_Check(value)) - return NumberVar_SetValueFromFloat(var, pos, value); - else if (PyLong_Check(value)) +#endif + if (PyLong_Check(value)) return NumberVar_SetValueFromLong(var, pos, value); - else if (Py_TYPE(value) == g_DecimalType) + if (PyBool_Check(value)) + return NumberVar_SetValueFromBoolean(var, pos, value); + if (PyFloat_Check(value)) + return NumberVar_SetValueFromFloat(var, pos, value); + if (Py_TYPE(value) == g_DecimalType) return NumberVar_SetValueFromDecimal(var, pos, value); PyErr_SetString(PyExc_TypeError, "expecting numeric data"); return -1; @@ -484,14 +493,20 @@ static PyObject *NumberVar_GetValue( ub4 stringLength; sword status; +#if PY_MAJOR_VERSION < 3 if (var->type == &vt_Integer || var->type == &vt_Boolean) { +#else + if (var->type == &vt_Boolean) { +#endif status = OCINumberToInt(var->environment->errorHandle, &var->data[pos], sizeof(long), OCI_NUMBER_SIGNED, (dvoid*) &integerValue); if (Environment_CheckForError(var->environment, status, "NumberVar_GetValue(): as integer") < 0) return NULL; +#if PY_MAJOR_VERSION < 3 if (var->type == &vt_Integer) return PyInt_FromLong(integerValue); +#endif return PyBool_FromLong(integerValue); } diff --git a/StringUtils.c b/StringUtils.c index 8a1fd60..de351b5 100644 --- a/StringUtils.c +++ b/StringUtils.c @@ -26,6 +26,16 @@ typedef struct { #endif +// define binary type and methods +#if PY_MAJOR_VERSION >= 3 + #define cxBinary_Type PyBytes_Type + #define cxBinary_Check PyBytes_Check +#else + #define cxBinary_Type PyBuffer_Type + #define cxBinary_Check PyBuffer_Check +#endif + + //----------------------------------------------------------------------------- // StringBuffer_Init() // Initialize the string buffer with an empty string. Returns 0 as a @@ -89,6 +99,34 @@ static int StringBuffer_FromBytes( } +#if PY_MAJOR_VERSION < 3 +//----------------------------------------------------------------------------- +// StringBuffer_FromBuffer() +// Populate the string buffer from a buffer object. +//----------------------------------------------------------------------------- +static int StringBuffer_FromBuffer( + udt_StringBuffer *buf, // buffer to fill + PyObject *obj) // bytes object expected +{ + if (!obj) + return StringBuffer_Init(buf); + if (PyObject_AsReadBuffer(obj, &buf->ptr, &buf->size) < 0) + return -1; +#ifdef Py_UNICODE_WIDE + buf->encodedString = NULL; +#endif + return 0; +} +#endif + + +#if PY_MAJOR_VERSION >= 3 +#define StringBuffer_FromBinary StringBuffer_FromBytes +#else +#define StringBuffer_FromBinary StringBuffer_FromBuffer +#endif + + #ifdef WITH_UNICODE #define CXORA_CHARSETID OCI_UTF16ID #define CXORA_BYTES_PER_CHAR 2 @@ -96,7 +134,11 @@ static int StringBuffer_FromBytes( #define cxString_Format PyUnicode_Format #define cxString_Check PyUnicode_Check #define cxString_GetSize PyUnicode_GET_SIZE - #define cxString_FromObject PyObject_Unicode + #if PY_MAJOR_VERSION >= 3 + #define cxString_FromObject PyObject_Str + #else + #define cxString_FromObject PyObject_Unicode + #endif #define cxString_FromAscii(str) \ PyUnicode_DecodeASCII(str, strlen(str), NULL) #ifdef Py_UNICODE_WIDE diff --git a/StringVar.c b/StringVar.c index a3283c9..e2e913d 100644 --- a/StringVar.c +++ b/StringVar.c @@ -361,7 +361,6 @@ static int StringVar_SetValue( udt_StringBuffer buffer; // get the buffer data and size for binding - StringBuffer_Init(&buffer); #ifdef WITH_UNICODE if (!var->type->isCharacterData) { #else @@ -369,9 +368,11 @@ static int StringVar_SetValue( #endif if (PyBytes_Check(value)) { StringBuffer_FromBytes(&buffer, value); - } else if (PyBuffer_Check(value)) { - if (PyObject_AsReadBuffer(value, &buffer.ptr, &buffer.size) < 0) +#if PY_MAJOR_VERSION < 3 + } else if (cxBinary_Check(value)) { + if (StringBuffer_FromBinary(&buffer, value) < 0) return -1; +#endif } else { PyErr_SetString(PyExc_TypeError, "expecting string or buffer data"); diff --git a/Variable.c b/Variable.c index f1c94bd..8444f98 100644 --- a/Variable.c +++ b/Variable.c @@ -380,7 +380,7 @@ static udt_VariableType *Variable_TypeByPythonType( return &vt_Rowid; if (type == (PyObject*) &g_BinaryVarType) return &vt_Binary; - if (type == (PyObject*) &PyBuffer_Type) + if (type == (PyObject*) &cxBinary_Type) return &vt_Binary; if (type == (PyObject*) &g_LongStringVarType) return &vt_LongString; @@ -399,8 +399,10 @@ static udt_VariableType *Variable_TypeByPythonType( } if (type == (PyObject*) &PyFloat_Type) return &vt_Float; +#if PY_MAJOR_VERSION < 3 if (type == (PyObject*) &PyInt_Type) return &vt_Integer; +#endif if (type == (PyObject*) &PyLong_Type) return &vt_LongInteger; if (type == (PyObject*) &PyBool_Type) @@ -465,16 +467,20 @@ static udt_VariableType *Variable_TypeByValue( return &vt_NationalCharString; } #endif +#if PY_MAJOR_VERSION < 3 if (PyInt_Check(value)) return &vt_Integer; +#endif if (PyLong_Check(value)) return &vt_LongInteger; if (PyFloat_Check(value)) return &vt_Float; - if (PyBuffer_Check(value)) { - const void *buffer; - if (PyObject_AsReadBuffer(value, &buffer, (sb4*) size) < 0) + if (cxBinary_Check(value)) { + udt_StringBuffer temp; + if (StringBuffer_FromBinary(&temp, value) < 0) return NULL; + *size = temp.size; + StringBuffer_Clear(&temp); if (*size > MAX_BINARY_BYTES) return &vt_LongBinary; return &vt_Binary; @@ -1107,7 +1113,7 @@ static int Variable_Bind( var->boundPos = pos; var->boundCursorHandle = cursor->handle; Py_XDECREF(var->boundName); -#if defined(WITH_UNICODE) && Py_MAJOR_VERSION < 3 +#if defined(WITH_UNICODE) && PY_MAJOR_VERSION < 3 if (name && PyBytes_Check(name)) { var->boundName = PyObject_Unicode(name); if (!var->boundName) diff --git a/cx_Oracle.c b/cx_Oracle.c index 69a2bb1..9760575 100644 --- a/cx_Oracle.c +++ b/cx_Oracle.c @@ -49,6 +49,14 @@ typedef int Py_ssize_t; #ifndef PyInt_Check #define PyInt_Check PyLong_Check #define PyInt_FromLong PyLong_FromLong +#define PyInt_Type PyLong_Type +#endif + +// define base exception +#if PY_MAJOR_VERSION >= 3 +#define CXORA_BASE_EXCEPTION NULL +#else +#define CXORA_BASE_EXCEPTION PyExc_StandardError #endif // define simple construct for determining endianness of the platform @@ -344,10 +352,10 @@ void initcx_Oracle(void) // create exception object and add it to the dictionary if (SetException(module, &g_WarningException, - "Warning", PyExc_StandardError) < 0) + "Warning", CXORA_BASE_EXCEPTION) < 0) return; if (SetException(module, &g_ErrorException, - "Error", PyExc_StandardError) < 0) + "Error", CXORA_BASE_EXCEPTION) < 0) return; if (SetException(module, &g_InterfaceErrorException, "InterfaceError", g_ErrorException) < 0) @@ -375,7 +383,7 @@ void initcx_Oracle(void) return; // set up the types that are available - ADD_TYPE_OBJECT("Binary", &PyBuffer_Type) + ADD_TYPE_OBJECT("Binary", &cxBinary_Type) ADD_TYPE_OBJECT("Connection", &g_ConnectionType) ADD_TYPE_OBJECT("Cursor", &g_CursorType) ADD_TYPE_OBJECT("Timestamp", PyDateTimeAPI->DateTimeType)