From ef3d84318ea8d1c96fcdf02cd6034fbd17cf81c8 Mon Sep 17 00:00:00 2001 From: Anthony Tuininga Date: Mon, 2 Nov 2020 15:24:23 -0700 Subject: [PATCH] The ability to pickle/unpickle Database and API types has been restored. --- doc/src/release_notes.rst | 1 + src/cxoApiType.c | 22 ++++- src/cxoDbType.c | 20 +++++ test/test_1500_dbtypes.py | 132 ---------------------------- test/test_1500_types.py | 179 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 221 insertions(+), 133 deletions(-) delete mode 100644 test/test_1500_dbtypes.py create mode 100644 test/test_1500_types.py diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index c720241..e3a1780 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -20,6 +20,7 @@ Version 8.1 (TBD) #) Builds are now done with setuptools and most metadata has moved from `setup.py` to `setup.cfg` in order to take advantage of Python packaging improvements. +#) The ability to pickle/unpickle Database and API types has been restored. #) Tests can now be run with tox in order to automate testing of the different environments that are supported. #) Improved documentation and test suite. diff --git a/src/cxoApiType.c b/src/cxoApiType.c index 4ba1c25..e82cc88 100644 --- a/src/cxoApiType.c +++ b/src/cxoApiType.c @@ -46,6 +46,25 @@ static PyObject *cxoApiType_repr(cxoApiType *apiType) } +//----------------------------------------------------------------------------- +// cxoApiType_reduce() +// Method provided for pickling/unpickling of API types. +//----------------------------------------------------------------------------- +static PyObject *cxoApiType_reduce(cxoApiType *apiType) +{ + return PyUnicode_DecodeASCII(apiType->name, strlen(apiType->name), NULL); +} + + +//----------------------------------------------------------------------------- +// declaration of methods +//----------------------------------------------------------------------------- +static PyMethodDef cxoMethods[] = { + { "__reduce__", (PyCFunction) cxoApiType_reduce, METH_NOARGS }, + { NULL, NULL } +}; + + //----------------------------------------------------------------------------- // declaration of members //----------------------------------------------------------------------------- @@ -65,5 +84,6 @@ PyTypeObject cxoPyTypeApiType = { .tp_dealloc = (destructor) cxoApiType_free, .tp_repr = (reprfunc) cxoApiType_repr, .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_members = cxoMembers + .tp_members = cxoMembers, + .tp_methods = cxoMethods }; diff --git a/src/cxoDbType.c b/src/cxoDbType.c index 0de2d4a..d051be4 100644 --- a/src/cxoDbType.c +++ b/src/cxoDbType.c @@ -241,6 +241,25 @@ cxoDbType *cxoDbType_fromTransformNum(cxoTransformNum transformNum) } +//----------------------------------------------------------------------------- +// cxoDBType_reduce() +// Method provided for pickling/unpickling of DB types. +//----------------------------------------------------------------------------- +static PyObject *cxoDBType_reduce(cxoDbType *dbType) +{ + return PyUnicode_DecodeASCII(dbType->name, strlen(dbType->name), NULL); +} + + +//----------------------------------------------------------------------------- +// declaration of methods +//----------------------------------------------------------------------------- +static PyMethodDef cxoMethods[] = { + { "__reduce__", (PyCFunction) cxoDBType_reduce, METH_NOARGS }, + { NULL, NULL} +}; + + //----------------------------------------------------------------------------- // declaration of members //----------------------------------------------------------------------------- @@ -261,6 +280,7 @@ PyTypeObject cxoPyTypeDbType = { .tp_repr = (reprfunc) cxoDbType_repr, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_members = cxoMembers, + .tp_methods = cxoMethods, .tp_richcompare = (richcmpfunc) cxoDbType_richCompare, .tp_hash = (hashfunc) cxoDbType_hash }; diff --git a/test/test_1500_dbtypes.py b/test/test_1500_dbtypes.py deleted file mode 100644 index 790827e..0000000 --- a/test/test_1500_dbtypes.py +++ /dev/null @@ -1,132 +0,0 @@ -#------------------------------------------------------------------------------ -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -#------------------------------------------------------------------------------ - -""" -1500 - Module for testing comparisons with database types and API types. This -also contains tests for comparisons with database types and variable types, for -backwards compatibility. -""" - -import TestEnv - -import cx_Oracle - -class TestCase(TestEnv.BaseTestCase): - - def __testCompare(self, dbType, apiType): - self.assertEqual(dbType, dbType) - self.assertEqual(dbType, apiType) - self.assertEqual(apiType, dbType) - self.assertNotEqual(dbType, 5) - self.assertNotEqual(dbType, cx_Oracle.DB_TYPE_OBJECT) - - def test_1500_Bfile(self): - "1500 - test cx_Oracle.DB_TYPE_BFILE comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_BFILE, cx_Oracle.BFILE) - - def test_1501_BinaryDouble(self): - "1501 - test cx_Oracle.DB_TYPE_BINARY_DOUBLE comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_BINARY_DOUBLE, cx_Oracle.NUMBER) - self.assertEqual(cx_Oracle.DB_TYPE_BINARY_DOUBLE, - cx_Oracle.NATIVE_FLOAT) - - def test_1502_BinaryFloat(self): - "1502 - test cx_Oracle.DB_TYPE_BINARY_FLOAT comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_BINARY_FLOAT, cx_Oracle.NUMBER) - - def test_1503_BinaryInteger(self): - "1503 - test cx_Oracle.DB_TYPE_BINARY_INTEGER comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_BINARY_INTEGER, cx_Oracle.NUMBER) - self.assertEqual(cx_Oracle.DB_TYPE_BINARY_INTEGER, - cx_Oracle.NATIVE_INT) - - def test_1504_Blob(self): - "1504 - test cx_Oracle.DB_TYPE_BLOB comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_BLOB, cx_Oracle.BLOB) - - def test_1505_Boolean(self): - "1505 - test cx_Oracle.DB_TYPE_BOOLEAN comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_BOOLEAN, cx_Oracle.BOOLEAN) - - def test_1506_Char(self): - "1506 - test cx_Oracle.DB_TYPE_CHAR comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.STRING) - self.assertEqual(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.FIXED_CHAR) - - def test_1507_Clob(self): - "1507 - test cx_Oracle.DB_TYPE_CLOB comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_CLOB, cx_Oracle.CLOB) - - def test_1508_Cursor(self): - "1508 - test cx_Oracle.DB_TYPE_CURSOR comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_CURSOR, cx_Oracle.CURSOR) - - def test_1509_Date(self): - "1509 - test cx_Oracle.DB_TYPE_DATE comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_DATE, cx_Oracle.DATETIME) - - def test_1510_IntervalDS(self): - "1510 - test cx_Oracle.DB_TYPE_INTERVAL_DS comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_INTERVAL_DS, cx_Oracle.INTERVAL) - - def test_1511_Long(self): - "1511 - test cx_Oracle.DB_TYPE_LONG comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_LONG, cx_Oracle.STRING) - self.assertEqual(cx_Oracle.DB_TYPE_LONG, cx_Oracle.LONG_STRING) - - def test_1512_LongRaw(self): - "1512 - test cx_Oracle.DB_TYPE_LONG_RAW comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.BINARY) - self.assertEqual(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.LONG_BINARY) - - def test_1513_Nchar(self): - "1513 - test cx_Oracle.DB_TYPE_NCHAR comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.STRING) - self.assertEqual(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.FIXED_NCHAR) - - def test_1514_Nclob(self): - "1514 - test cx_Oracle.DB_TYPE_NCLOB comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_NCLOB, cx_Oracle.NCLOB) - - def test_1515_Number(self): - "1515 - test cx_Oracle.DB_TYPE_NUMBER comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.NUMBER) - - def test_1516_Nvarchar(self): - "1516 - test cx_Oracle.DB_TYPE_NVARCHAR comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.STRING) - self.assertEqual(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.NCHAR) - - def test_1517_Object(self): - "1517 - test cx_Oracle.DB_TYPE_OBJECT comparisons" - self.assertEqual(cx_Oracle.DB_TYPE_OBJECT, cx_Oracle.OBJECT) - - def test_1518_Raw(self): - "1518 - test cx_Oracle.DB_TYPE_RAW comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_RAW, cx_Oracle.BINARY) - - def test_1519_Rowid(self): - "1519 - test cx_Oracle.DB_TYPE_ROWID comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_ROWID, cx_Oracle.ROWID) - - def test_1520_Timestamp(self): - "1520 - test cx_Oracle.DB_TYPE_TIMESTAMP comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.DATETIME) - self.assertEqual(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.TIMESTAMP) - - def test_1521_TimestampLTZ(self): - "1521 - test cx_Oracle.DB_TYPE_TIMESTAMP_LTZ comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_LTZ, cx_Oracle.DATETIME) - - def test_1522_TimestampTZ(self): - "1522 - test cx_Oracle.DB_TYPE_TIMESTAMP_TZ comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_TZ, cx_Oracle.DATETIME) - - def test_1523_Varchar(self): - "1523 - test cx_Oracle.DB_TYPE_VARCHAR comparisons" - self.__testCompare(cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.STRING) - - -if __name__ == "__main__": - TestEnv.RunTestCases() diff --git a/test/test_1500_types.py b/test/test_1500_types.py new file mode 100644 index 0000000..6bf1707 --- /dev/null +++ b/test/test_1500_types.py @@ -0,0 +1,179 @@ +#------------------------------------------------------------------------------ +# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +#------------------------------------------------------------------------------ + +""" +1500 - Module for testing comparisons with database types and API types, +including the synonyms retained for backwards compatibility. This module also +tests for pickling/unpickling of database types and API types. +""" + +import TestEnv + +import cx_Oracle +import pickle + +class TestCase(TestEnv.BaseTestCase): + + def __testCompare(self, dbType, apiType): + self.assertEqual(dbType, dbType) + self.assertEqual(dbType, apiType) + self.assertEqual(apiType, dbType) + self.assertNotEqual(dbType, 5) + self.assertNotEqual(dbType, cx_Oracle.DB_TYPE_OBJECT) + + def __testPickle(self, typ): + self.assertIs(typ, pickle.loads(pickle.dumps(typ))) + + def test_1500_DB_TYPE_BFILE(self): + "1500 - test cx_Oracle.DB_TYPE_BFILE comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_BFILE, cx_Oracle.BFILE) + self.__testPickle(cx_Oracle.DB_TYPE_BFILE) + + def test_1501_DB_TYPE_BINARY_DOUBLE(self): + "1501 - test cx_Oracle.DB_TYPE_BINARY_DOUBLE comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_BINARY_DOUBLE, cx_Oracle.NUMBER) + self.assertEqual(cx_Oracle.DB_TYPE_BINARY_DOUBLE, + cx_Oracle.NATIVE_FLOAT) + self.__testPickle(cx_Oracle.DB_TYPE_BINARY_DOUBLE) + + def test_1502_DB_TYPE_BINARY_FLOAT(self): + "1502 - test cx_Oracle.DB_TYPE_BINARY_FLOAT comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_BINARY_FLOAT, cx_Oracle.NUMBER) + self.__testPickle(cx_Oracle.DB_TYPE_BINARY_FLOAT) + + def test_1503_DB_TYPE_BINARY_INTEGER(self): + "1503 - test cx_Oracle.DB_TYPE_BINARY_INTEGER comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_BINARY_INTEGER, cx_Oracle.NUMBER) + self.assertEqual(cx_Oracle.DB_TYPE_BINARY_INTEGER, + cx_Oracle.NATIVE_INT) + self.__testPickle(cx_Oracle.DB_TYPE_BINARY_INTEGER) + + def test_1504_DB_TYPE_BLOB(self): + "1504 - test cx_Oracle.DB_TYPE_BLOB comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_BLOB, cx_Oracle.BLOB) + self.__testPickle(cx_Oracle.DB_TYPE_BLOB) + + def test_1505_DB_TYPE_BOOLEAN(self): + "1505 - test cx_Oracle.DB_TYPE_BOOLEAN comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_BOOLEAN, cx_Oracle.BOOLEAN) + self.__testPickle(cx_Oracle.DB_TYPE_BOOLEAN) + + def test_1506_DB_TYPE_CHAR(self): + "1506 - test cx_Oracle.DB_TYPE_CHAR comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.STRING) + self.assertEqual(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.FIXED_CHAR) + self.__testPickle(cx_Oracle.DB_TYPE_CHAR) + + def test_1507_DB_TYPE_CLOB(self): + "1507 - test cx_Oracle.DB_TYPE_CLOB comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_CLOB, cx_Oracle.CLOB) + self.__testPickle(cx_Oracle.DB_TYPE_CLOB) + + def test_1508_DB_TYPE_CURSOR(self): + "1508 - test cx_Oracle.DB_TYPE_CURSOR comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_CURSOR, cx_Oracle.CURSOR) + self.__testPickle(cx_Oracle.DB_TYPE_CURSOR) + + def test_1509_DB_TYPE_DATE(self): + "1509 - test cx_Oracle.DB_TYPE_DATE comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_DATE, cx_Oracle.DATETIME) + self.__testPickle(cx_Oracle.DB_TYPE_DATE) + + def test_1510_DB_TYPE_INTERVAL_DS(self): + "1510 - test cx_Oracle.DB_TYPE_INTERVAL_DS comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_INTERVAL_DS, cx_Oracle.INTERVAL) + self.__testPickle(cx_Oracle.DB_TYPE_INTERVAL_DS) + + def test_1511_DB_TYPE_LONG(self): + "1511 - test cx_Oracle.DB_TYPE_LONG comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_LONG, cx_Oracle.STRING) + self.assertEqual(cx_Oracle.DB_TYPE_LONG, cx_Oracle.LONG_STRING) + self.__testPickle(cx_Oracle.DB_TYPE_LONG) + + def test_1512_DB_TYPE_LONG_RAW(self): + "1512 - test cx_Oracle.DB_TYPE_LONG_RAW comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.BINARY) + self.assertEqual(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.LONG_BINARY) + self.__testPickle(cx_Oracle.DB_TYPE_LONG_RAW) + + def test_1513_DB_TYPE_NCHAR(self): + "1513 - test cx_Oracle.DB_TYPE_NCHAR comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.STRING) + self.assertEqual(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.FIXED_NCHAR) + self.__testPickle(cx_Oracle.DB_TYPE_NCHAR) + + def test_1514_DB_TYPE_NCLOB(self): + "1514 - test cx_Oracle.DB_TYPE_NCLOB comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_NCLOB, cx_Oracle.NCLOB) + self.__testPickle(cx_Oracle.DB_TYPE_NCLOB) + + def test_1515_DB_TYPE_NUMBER(self): + "1515 - test cx_Oracle.DB_TYPE_NUMBER comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.NUMBER) + self.__testPickle(cx_Oracle.DB_TYPE_NUMBER) + + def test_1516_DB_TYPE_NVARCHAR(self): + "1516 - test cx_Oracle.DB_TYPE_NVARCHAR comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.STRING) + self.assertEqual(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.NCHAR) + self.__testPickle(cx_Oracle.DB_TYPE_NVARCHAR) + + def test_1517_DB_TYPE_OBJECT(self): + "1517 - test cx_Oracle.DB_TYPE_OBJECT comparisons and pickling" + self.assertEqual(cx_Oracle.DB_TYPE_OBJECT, cx_Oracle.OBJECT) + self.__testPickle(cx_Oracle.DB_TYPE_OBJECT) + + def test_1518_DB_TYPE_RAW(self): + "1518 - test cx_Oracle.DB_TYPE_RAW comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_RAW, cx_Oracle.BINARY) + self.__testPickle(cx_Oracle.DB_TYPE_RAW) + + def test_1519_DB_TYPE_ROWID(self): + "1519 - test cx_Oracle.DB_TYPE_ROWID comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_ROWID, cx_Oracle.ROWID) + self.__testPickle(cx_Oracle.DB_TYPE_ROWID) + + def test_1520_DB_TYPE_TIMESTAMP(self): + "1520 - test cx_Oracle.DB_TYPE_TIMESTAMP comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.DATETIME) + self.assertEqual(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.TIMESTAMP) + self.__testPickle(cx_Oracle.DB_TYPE_TIMESTAMP) + + def test_1521_DB_TYPE_TIMESTAMP_LTZ(self): + "1521 - test cx_Oracle.DB_TYPE_TIMESTAMP_LTZ comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_LTZ, cx_Oracle.DATETIME) + self.__testPickle(cx_Oracle.DB_TYPE_TIMESTAMP_LTZ) + + def test_1522_DB_TYPE_TIMESTAMP_TZ(self): + "1522 - test cx_Oracle.DB_TYPE_TIMESTAMP_TZ comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_TZ, cx_Oracle.DATETIME) + self.__testPickle(cx_Oracle.DB_TYPE_TIMESTAMP_TZ) + + def test_1523_DB_TYPE_VARCHAR(self): + "1523 - test cx_Oracle.DB_TYPE_VARCHAR comparisons and pickling" + self.__testCompare(cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.STRING) + self.__testPickle(cx_Oracle.DB_TYPE_VARCHAR) + + def test_1524_NUMBER(self): + "1524 - test cx_Oracle.NUMBER pickling" + self.__testPickle(cx_Oracle.NUMBER) + + def test_1525_STRING(self): + "1525 - test cx_Oracle.STRING pickling" + self.__testPickle(cx_Oracle.STRING) + + def test_1526_DATETIME(self): + "1526 - test cx_Oracle.DATETIME pickling" + self.__testPickle(cx_Oracle.DATETIME) + + def test_1527_BINARY(self): + "1527 - test cx_Oracle.BINARY pickling" + self.__testPickle(cx_Oracle.BINARY) + + def test_1528_ROWID(self): + "1528 - test cx_Oracle.ROWID pickling" + self.__testPickle(cx_Oracle.ROWID) + +if __name__ == "__main__": + TestEnv.RunTestCases()