[Python-modules-commits] [pyodbc] 01/05: New upstream version 4.0.17

Laurent Bigonville bigon at moszumanska.debian.org
Fri Sep 29 09:52:55 UTC 2017


This is an automated email from the git hooks/post-receive script.

bigon pushed a commit to branch master
in repository pyodbc.

commit a19ae145b61345b643f8750cee11e1ccd5ba8ea1
Author: Laurent Bigonville <bigon at debian.org>
Date:   Thu Sep 28 11:51:30 2017 +0200

    New upstream version 4.0.17
---
 PKG-INFO                    |  40 +++++++-------
 pyodbc.egg-info/PKG-INFO    |  40 +++++++-------
 pyodbc.egg-info/SOURCES.txt |   2 -
 setup.cfg                   |  18 ++----
 setup.py                    |   0
 src/cnxninfo.cpp            |   7 ++-
 src/getdata.cpp             |  35 +++++++-----
 src/params.cpp              |  39 +++++++++----
 src/pyodbcmodule.cpp        | 132 ++++++++++++++++++++++++++++++++------------
 src/pyodbcmodule.h          |  22 +++++---
 tests2/accesstests.py       |   0
 tests2/dbapi20.py           |   0
 tests2/dbapitests.py        |   0
 tests2/exceltests.py        |   0
 tests2/freetdstests.py      |   0
 tests2/informixtests.py     |   0
 tests2/mysqltests.py        |   0
 tests2/pgtests.py           |   0
 tests2/pgtests.pyc          | Bin 20699 -> 0 bytes
 tests2/sqlitetests.py       |   0
 tests2/sqlservertests.py    |   0
 tests2/test.py              |   0
 tests2/testbase.py          |   0
 tests2/testutils.py         |   0
 tests2/testutils.pyc        | Bin 4531 -> 4451 bytes
 tests3/mysqltests.py        |   0
 tests3/pgtests.py           |  24 +++++++-
 tests3/testutils.pyc        | Bin 3968 -> 4182 bytes
 28 files changed, 231 insertions(+), 128 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 3e29a8f..1e7bce6 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,20 +1,20 @@
-Metadata-Version: 1.1
-Name: pyodbc
-Version: 4.0.14
-Summary: DB API Module for ODBC
-Home-page: https://github.com/mkleehammer/pyodbc
-Author: Michael Kleehammer
-Author-email: michael at kleehammer.com
-License: MIT
-Description: A Python DB API 2 module for ODBC. This project provides an up-to-date, convenient interface to ODBC using native data types like datetime and decimal.
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: POSIX
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 3
-Classifier: Topic :: Database
+Metadata-Version: 1.1
+Name: pyodbc
+Version: 4.0.17
+Summary: DB API Module for ODBC
+Home-page: https://github.com/mkleehammer/pyodbc
+Author: Michael Kleehammer
+Author-email: michael at kleehammer.com
+License: MIT
+Description: A Python DB API 2 module for ODBC. This project provides an up-to-date, convenient interface to ODBC using native data types like datetime and decimal.
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Database
diff --git a/pyodbc.egg-info/PKG-INFO b/pyodbc.egg-info/PKG-INFO
index 3e29a8f..1e7bce6 100644
--- a/pyodbc.egg-info/PKG-INFO
+++ b/pyodbc.egg-info/PKG-INFO
@@ -1,20 +1,20 @@
-Metadata-Version: 1.1
-Name: pyodbc
-Version: 4.0.14
-Summary: DB API Module for ODBC
-Home-page: https://github.com/mkleehammer/pyodbc
-Author: Michael Kleehammer
-Author-email: michael at kleehammer.com
-License: MIT
-Description: A Python DB API 2 module for ODBC. This project provides an up-to-date, convenient interface to ODBC using native data types like datetime and decimal.
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: POSIX
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 3
-Classifier: Topic :: Database
+Metadata-Version: 1.1
+Name: pyodbc
+Version: 4.0.17
+Summary: DB API Module for ODBC
+Home-page: https://github.com/mkleehammer/pyodbc
+Author: Michael Kleehammer
+Author-email: michael at kleehammer.com
+License: MIT
+Description: A Python DB API 2 module for ODBC. This project provides an up-to-date, convenient interface to ODBC using native data types like datetime and decimal.
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Database
diff --git a/pyodbc.egg-info/SOURCES.txt b/pyodbc.egg-info/SOURCES.txt
index 65016a1..dcd8128 100644
--- a/pyodbc.egg-info/SOURCES.txt
+++ b/pyodbc.egg-info/SOURCES.txt
@@ -1,7 +1,6 @@
 LICENSE.txt
 MANIFEST.in
 README.md
-setup.cfg
 setup.py
 pyodbc.egg-info/PKG-INFO
 pyodbc.egg-info/SOURCES.txt
@@ -45,7 +44,6 @@ tests2/freetdstests.py
 tests2/informixtests.py
 tests2/mysqltests.py
 tests2/pgtests.py
-tests2/pgtests.pyc
 tests2/sqlite.db
 tests2/sqlitetests.py
 tests2/sqlservertests.py
diff --git a/setup.cfg b/setup.cfg
index 2b59e66..4927abe 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,14 +1,4 @@
-[build_ext]
-include_dirs = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/include
-
-[sqlservertests]
-connection-string = DRIVER={FreeTDS};Server=10.0.2.15;Database=test;UID=test;PWD=test;
-
-[pgtests]
-connection-string = DSN=psqlODBC
-
-[egg_info]
-tag_build = 
-tag_date = 0
-tag_svn_revision = 0
-
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff --git a/setup.py b/setup.py
old mode 100755
new mode 100644
diff --git a/src/cnxninfo.cpp b/src/cnxninfo.cpp
index 9e09c30..9d17f98 100644
--- a/src/cnxninfo.cpp
+++ b/src/cnxninfo.cpp
@@ -52,7 +52,10 @@ static PyObject* GetHash(PyObject* p)
     if (!hash.IsValid())
         return 0;
 
-    PyObject_CallMethodObjArgs(hash, update, p, 0);
+    Object result(PyObject_CallMethodObjArgs(hash, update, p, 0));
+    if (!result.IsValid())
+        return 0;
+
     return PyObject_CallMethod(hash, "hexdigest", 0);
 }
 
@@ -72,7 +75,7 @@ inline void GetColumnSize(Connection* cnxn, SQLSMALLINT sqltype, int* psize)
     {
         // I believe some drivers are returning negative numbers for "unlimited" text fields,
         // such as FileMaker.  Ignore anything that seems too small.
-        if (columnsize >= 255)
+        if (columnsize >= 1)
             *psize = (int)columnsize;
     }
 
diff --git a/src/getdata.cpp b/src/getdata.cpp
index 4f2d1e4..b9fd627 100644
--- a/src/getdata.cpp
+++ b/src/getdata.cpp
@@ -111,7 +111,7 @@ static bool ReadVarColumn(Cursor* cur, Py_ssize_t iCol, SQLSMALLINT ctype, bool&
         // cbUsed.
 
         Py_ssize_t cbAvailable = cbAllocated - cbUsed;
-        SQLLEN cbData;
+        SQLLEN cbData = 0;
 
         Py_BEGIN_ALLOW_THREADS
         ret = SQLGetData(cur->hstmt, (SQLUSMALLINT)(iCol+1), ctype, &pb[cbUsed], (SQLLEN)cbAvailable, &cbData);
@@ -125,7 +125,7 @@ static bool ReadVarColumn(Cursor* cur, Py_ssize_t iCol, SQLSMALLINT ctype, bool&
             return false;
         }
 
-        if (ret == SQL_SUCCESS && cbData < 0)
+        if (ret == SQL_SUCCESS && (int)cbData < 0)
         {
             // HACK: FreeTDS 0.91 on OS/X returns -4 for NULL data instead of SQL_NULL_DATA
             // (-1).  I've traced into the code and it appears to be the result of assigning -1
@@ -455,10 +455,14 @@ static PyObject* GetDataDecimal(Cursor* cur, Py_ssize_t iCol)
     Object str(PyString_FromStringAndSize(ascii, (Py_ssize_t)asciilen));
     if (!str)
         return 0;
-    return PyObject_CallFunction(decimal_type, "O", str.Get());
+    PyObject* decimal_type = GetClassForThread("decimal", "Decimal");
+    if (!decimal_type)
+        return 0;
+    PyObject* decimal = PyObject_CallFunction(decimal_type, "O", str.Get());
+    Py_DECREF(decimal_type);
+    return decimal;
 }
 
-
 static PyObject* GetDataBit(Cursor* cur, Py_ssize_t iCol)
 {
     SQLCHAR ch;
@@ -598,7 +602,13 @@ static PyObject* GetUUID(Cursor* cur, Py_ssize_t iCol)
     Object args(Py_BuildValue(szFmt, NULL, NULL, &guid, (int)sizeof(guid)));
     if (!args)
         return 0;
-    return PyObject_CallObject(uuid_type, args.Get());
+
+    PyObject* uuid_type = GetClassForThread("uuid", "UUID");
+    if (!uuid_type)
+        return 0;
+    PyObject* uuid = PyObject_CallObject(uuid_type, args.Get());
+    Py_DECREF(uuid_type);
+    return uuid;
 }
 
 static PyObject* GetDataTimestamp(Cursor* cur, Py_ssize_t iCol)
@@ -664,6 +674,7 @@ PyObject* PythonTypeFromSqlType(Cursor* cur, SQLSMALLINT type)
         return (PyObject*)&PyString_Type;
 
     PyObject* pytype = 0;
+    bool incref = true;
 
     switch (type)
     {
@@ -683,7 +694,8 @@ PyObject* PythonTypeFromSqlType(Cursor* cur, SQLSMALLINT type)
     case SQL_GUID:
         if (UseNativeUUID())
         {
-            pytype = uuid_type;
+            pytype = GetClassForThread("uuid", "UUID");
+            incref = false;
         }
         else
         {
@@ -708,7 +720,8 @@ PyObject* PythonTypeFromSqlType(Cursor* cur, SQLSMALLINT type)
 
     case SQL_DECIMAL:
     case SQL_NUMERIC:
-        pytype = (PyObject*)decimal_type;
+        pytype = GetClassForThread("decimal", "Decimal");
+        incref = false;
         break;
 
     case SQL_REAL:
@@ -756,7 +769,8 @@ PyObject* PythonTypeFromSqlType(Cursor* cur, SQLSMALLINT type)
         break;
     }
 
-    Py_INCREF(pytype);
+    if (pytype && incref)
+        Py_INCREF(pytype);
     return pytype;
 }
 
@@ -801,12 +815,7 @@ PyObject* GetData(Cursor* cur, Py_ssize_t iCol)
 
     case SQL_DECIMAL:
     case SQL_NUMERIC:
-    {
-        if (decimal_type == 0)
-            break;
-
         return GetDataDecimal(cur, iCol);
-    }
 
     case SQL_BIT:
         return GetDataBit(cur, iCol);
diff --git a/src/params.cpp b/src/params.cpp
index 451a601..4d152d2 100644
--- a/src/params.cpp
+++ b/src/params.cpp
@@ -421,8 +421,11 @@ static char* CreateDecimalString(long sign, PyObject* digits, long exp)
     return pch;
 }
 
-static bool GetUUIDInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
+static bool GetUUIDInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info, PyObject* uuid_type)
 {
+    // uuid_type: This is a new reference that we are responsible for freeing.
+    Object tmp(uuid_type);
+
     info.ValueType = SQL_C_GUID;
     info.ParameterType = SQL_GUID;
     info.ColumnSize = 16;
@@ -443,8 +446,12 @@ static bool GetUUIDInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInf
     return true;
 }
 
-static bool GetDecimalInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
+
+static bool GetDecimalInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info, PyObject* decimal_type)
 {
+    // decimal_type: This is a new reference that we are responsible for freeing.
+    Object tmp(decimal_type);
+
     // The NUMERIC structure never works right with SQL Server and probably a lot of other drivers.  We'll bind as a
     // string.  Unfortunately, the Decimal class doesn't seem to have a way to force it to return a string without
     // exponents, so we'll have to build it ourselves.
@@ -609,12 +616,6 @@ static bool GetParameterInfo(Cursor* cur, Py_ssize_t index, PyObject* param, Par
     if (PyFloat_Check(param))
         return GetFloatInfo(cur, index, param, info);
 
-    if (PyDecimal_Check(param))
-        return GetDecimalInfo(cur, index, param, info);
-
-    if (uuid_type && PyObject_IsInstance(param, uuid_type))
-        return GetUUIDInfo(cur, index, param, info);
-
 #if PY_VERSION_HEX >= 0x02060000
     if (PyByteArray_Check(param))
         return GetByteArrayInfo(cur, index, param, info);
@@ -628,6 +629,23 @@ static bool GetParameterInfo(Cursor* cur, Py_ssize_t index, PyObject* param, Par
         return GetBufferInfo(cur, index, param, info);
 #endif
 
+    // Decimal
+
+    PyObject* cls = 0;
+    if (!IsInstanceForThread(param, "decimal", "Decimal", &cls))
+        return false;
+
+    if (cls != 0)
+        return GetDecimalInfo(cur, index, param, info, cls);
+
+    // UUID
+
+    if (!IsInstanceForThread(param, "uuid", "UUID", &cls))
+        return false;
+
+    if (cls != 0)
+        return GetUUIDInfo(cur, index, param, info, cls);
+
     RaiseErrorV("HY105", ProgrammingError, "Invalid parameter type.  param-index=%zd param-type=%s", index, Py_TYPE(param)->tp_name);
     return false;
 }
@@ -798,10 +816,7 @@ bool PrepareAndBind(Cursor* cur, PyObject* pSql, PyObject* original_params, bool
 
     for (Py_ssize_t i = 0; i < cParams; i++)
     {
-        // PySequence_GetItem returns a *new* reference, which GetParameterInfo will take ownership of.  It is stored
-        // in paramInfos and will be released in FreeInfos (which is always eventually called).
-
-        PyObject* param = PySequence_GetItem(original_params, i + params_offset);
+        Object param(PySequence_GetItem(original_params, i + params_offset));
         if (!GetParameterInfo(cur, i, param, cur->paramInfos[i]))
         {
             FreeInfos(cur->paramInfos, cParams);
diff --git a/src/pyodbcmodule.cpp b/src/pyodbcmodule.cpp
index c085fcd..a2621f5 100644
--- a/src/pyodbcmodule.cpp
+++ b/src/pyodbcmodule.cpp
@@ -126,9 +126,6 @@ static ExcInfo aExcInfos[] = {
 };
 
 
-PyObject* decimal_type;
-PyObject* uuid_type;
-
 bool UseNativeUUID()
 {
     PyObject* o = PyObject_GetAttrString(pModule, "native_uuid");
@@ -143,6 +140,100 @@ HENV henv = SQL_NULL_HANDLE;
 Py_UNICODE chDecimal = '.';
 
 
+PyObject* GetClassForThread(const char* szModule, const char* szClass)
+{
+    // Returns the given class, specific to the current thread's interpreter.  For performance
+    // these are cached for each thread.
+    //
+    // This is for internal use only, so we'll cache using only the class name.  Make sure they
+    // are unique.  (That is, don't try to import classes with the same name from two different
+    // modules.)
+
+    PyObject* dict = PyThreadState_GetDict();
+    I(dict);
+    if (dict == 0)
+    {
+        // I don't know why there wouldn't be thread state so I'm going to raise an exception
+        // unless I find more info.
+        return PyErr_Format(PyExc_Exception, "pyodbc: PyThreadState_GetDict returned NULL");
+    }
+
+    // Check the cache.  GetItemString returns a borrowed reference.
+    PyObject* cls = PyDict_GetItemString(dict, szClass);
+    if (cls)
+    {
+        Py_INCREF(cls);
+        return cls;
+    }
+
+    // Import the class and cache it.  GetAttrString returns a new reference.
+    PyObject* mod = PyImport_ImportModule(szModule);
+    if (!mod)
+        return 0;
+
+    cls = PyObject_GetAttrString(mod, szClass);
+    Py_DECREF(mod);
+    if (!cls)
+        return 0;
+
+    // SetItemString increments the refcount (not documented)
+    PyDict_SetItemString(dict, szClass, cls);
+
+    return cls;
+}
+
+bool IsInstanceForThread(PyObject* param, const char* szModule, const char* szClass, PyObject** pcls)
+{
+    // Like PyObject_IsInstance but compares against a class specific to the current thread's
+    // interpreter, for proper subinterpreter support.  Uses GetClassForThread.
+    //
+    // If `param` is an instance of the given class, true is returned and a new reference to
+    // the class, specific to the current thread, is returned via pcls.  The caller is
+    // responsible for decrementing the class.
+    //
+    // If `param` is not an instance, true is still returned (!) but *pcls will be zero.
+    //
+    // False is only returned when an exception has been raised.  (That is, the return value is
+    // not used to indicate whether the instance check matched or not.)
+
+    if (param == 0)
+    {
+        *pcls = 0;
+        return true;
+    }
+
+    PyObject* cls = GetClassForThread(szModule, szClass);
+    if (!cls)
+    {
+        *pcls = 0;
+        return false;
+    }
+
+    int n = PyObject_IsInstance(param, cls);
+    // (The checks below can be compressed into just a few lines, but I was concerned it
+    //  wouldn't be clear.)
+
+    if (n == 1)
+    {
+        // We have a match.
+        *pcls = cls;
+        return true;
+    }
+
+    Py_DECREF(cls);
+    *pcls = 0;
+
+    if (n == 0)
+    {
+        // No exception, but not a match.
+        return true;
+    }
+
+    // n == -1; an exception occurred
+    return false;
+}
+
+
 // Initialize the global decimal character and thousands separator character, used when parsing decimal
 // objects.
 //
@@ -175,6 +266,9 @@ static void init_locale_info()
 
 static bool import_types()
 {
+    // Note: We can only import types from C extensions since they are shared among all
+    // interpreters.  Other classes are imported per-thread via GetClassForThread.
+
     // In Python 2.5 final, PyDateTime_IMPORT no longer works unless the datetime module was previously
     // imported (among other problems).
 
@@ -192,36 +286,6 @@ static bool import_types()
     if (!Params_init())
         return false;
 
-    Object mod(PyImport_ImportModule("cdecimal"));
-    if (!mod)
-    {
-        PyErr_Clear();
-        mod.Attach(PyImport_ImportModule("decimal"));
-        if (!mod)
-        {
-            PyErr_SetString(PyExc_RuntimeError, "Unable to import cdecimal or decimal");
-            return false;
-        }
-    }
-
-    Object dec(PyObject_GetAttrString(mod, "Decimal"));
-    if (!dec)
-    {
-        PyErr_SetString(PyExc_RuntimeError, "Unable to import decimal.Decimal.");
-        return false;
-    }
-
-    mod.Attach(PyImport_ImportModule("uuid"));
-    if (!mod)
-        return false;
-
-    Object uuid(PyObject_GetAttrString(mod, "UUID"));
-    if (!uuid)
-        return false;
-
-    decimal_type = dec.Detach();
-    uuid_type    = uuid.Detach();
-
     return true;
 }
 
@@ -737,7 +801,6 @@ static void ErrorInit()
     IntegrityError = 0;
     DataError = 0;
     NotSupportedError = 0;
-    decimal_type = 0;
 }
 
 
@@ -756,7 +819,6 @@ static void ErrorCleanup()
     Py_XDECREF(IntegrityError);
     Py_XDECREF(DataError);
     Py_XDECREF(NotSupportedError);
-    Py_XDECREF(decimal_type);
 }
 
 struct ConstantDef
diff --git a/src/pyodbcmodule.h b/src/pyodbcmodule.h
index abe55b7..d0566a7 100644
--- a/src/pyodbcmodule.h
+++ b/src/pyodbcmodule.h
@@ -1,10 +1,9 @@
-
 /*
  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
@@ -29,15 +28,20 @@ extern PyObject* IntegrityError;
 extern PyObject* DataError;
 extern PyObject* NotSupportedError;
 
-extern PyObject* null_binary;
+/*
+  Returns the given class, specific to the current thread's interpreter.  For performance these
+  are cached for each thread.
 
-extern PyObject* decimal_type;
-extern PyObject* uuid_type;
+  This is for internal use only, so we'll cache using only the class name.  Make sure they are
+  unique.  (That is, don't try to import classes with the same name from two different
+  modules.)
+*/
+PyObject* GetClassForThread(const char* szModule, const char* szClass);
+
+bool IsInstanceForThread(PyObject* param, const char* szModule, const char* szClass, PyObject** pcls);
+
+extern PyObject* null_binary;
 
-inline bool PyDecimal_Check(PyObject* p)
-{
-    return Py_TYPE(p) == (_typeobject*)decimal_type;
-}
 extern HENV henv;
 
 extern PyTypeObject RowType;
diff --git a/tests2/accesstests.py b/tests2/accesstests.py
old mode 100755
new mode 100644
diff --git a/tests2/dbapi20.py b/tests2/dbapi20.py
old mode 100755
new mode 100644
diff --git a/tests2/dbapitests.py b/tests2/dbapitests.py
old mode 100755
new mode 100644
diff --git a/tests2/exceltests.py b/tests2/exceltests.py
old mode 100755
new mode 100644
diff --git a/tests2/freetdstests.py b/tests2/freetdstests.py
old mode 100755
new mode 100644
diff --git a/tests2/informixtests.py b/tests2/informixtests.py
old mode 100755
new mode 100644
diff --git a/tests2/mysqltests.py b/tests2/mysqltests.py
old mode 100755
new mode 100644
diff --git a/tests2/pgtests.py b/tests2/pgtests.py
old mode 100755
new mode 100644
diff --git a/tests2/pgtests.pyc b/tests2/pgtests.pyc
deleted file mode 100644
index 92dafcc..0000000
Binary files a/tests2/pgtests.pyc and /dev/null differ
diff --git a/tests2/sqlitetests.py b/tests2/sqlitetests.py
old mode 100755
new mode 100644
diff --git a/tests2/sqlservertests.py b/tests2/sqlservertests.py
old mode 100755
new mode 100644
diff --git a/tests2/test.py b/tests2/test.py
old mode 100755
new mode 100644
diff --git a/tests2/testbase.py b/tests2/testbase.py
old mode 100755
new mode 100644
diff --git a/tests2/testutils.py b/tests2/testutils.py
old mode 100755
new mode 100644
diff --git a/tests2/testutils.pyc b/tests2/testutils.pyc
index de507ba..3b887ae 100644
Binary files a/tests2/testutils.pyc and b/tests2/testutils.pyc differ
diff --git a/tests3/mysqltests.py b/tests3/mysqltests.py
old mode 100755
new mode 100644
diff --git a/tests3/pgtests.py b/tests3/pgtests.py
old mode 100755
new mode 100644
index c8d4e8f..0cf44e5
--- a/tests3/pgtests.py
+++ b/tests3/pgtests.py
@@ -4,7 +4,7 @@
 
 from __future__ import print_function
 
-import sys, os, re
+import sys, os, re, uuid
 import unittest
 from decimal import Decimal
 from testutils import *
@@ -254,6 +254,28 @@ class PGTestCase(unittest.TestCase):
         self.assertEqual(type(v), Decimal)
         self.assertEqual(v, value)
 
+    def test_nonnative_uuid(self):
+        # The default is False meaning we should return a string.  Note that
+        # SQL Server seems to always return uppercase.
+        value = uuid.uuid4()
+        self.cursor.execute("create table t1(n uuid)")
+        self.cursor.execute("insert into t1 values (?)", value)
+
+        pyodbc.native_uuid = False
+        result = self.cursor.execute("select n from t1").fetchval()
+        self.assertEqual(type(result), str)
+        self.assertEqual(result, str(value).upper())
+
+    def test_native_uuid(self):
+        # When true, we should return a uuid.UUID object.
+        value = uuid.uuid4()
+        self.cursor.execute("create table t1(n uuid)")
+        self.cursor.execute("insert into t1 values (?)", value)
+
+        pyodbc.native_uuid = True
+        result = self.cursor.execute("select n from t1").fetchval()
+        self.assertIsInstance(result, uuid.UUID)
+        self.assertEqual(value, result)
 
     def _exec(self):
         self.cursor.execute(self.sql)
diff --git a/tests3/testutils.pyc b/tests3/testutils.pyc
index 1f26eb0..cfcd65c 100644
Binary files a/tests3/testutils.pyc and b/tests3/testutils.pyc differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pyodbc.git



More information about the Python-modules-commits mailing list