From b6873ee1ab9c38d446508e64a18b44c20951502d Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Wed, 20 Mar 2013 23:40:13 +0000 Subject: [PATCH] Dropped support for Python 2.4 --- NEWS | 1 + doc/src/install.rst | 2 +- lib/__init__.py | 17 ----------------- psycopg/cursor_type.c | 4 ++-- psycopg/error_type.c | 15 +-------------- psycopg/lobject_type.c | 2 +- psycopg/python.h | 33 ++------------------------------- tests/test_types_basic.py | 36 +++++++++++++----------------------- 8 files changed, 21 insertions(+), 89 deletions(-) diff --git a/NEWS b/NEWS index 6e0f7662..065a6b2f 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,7 @@ Bug fixes: Other changes: - Added support for Python 3.3. +- Dropped support for Python 2.4. Please use Psycopg 2.4.x if you need it. - `~psycopg2.errorcodes` map updated to PostgreSQL 9.2. - Dropped Zope adapter from source repository. ZPsycopgDA now has its own project at . diff --git a/doc/src/install.rst b/doc/src/install.rst index 3fa480cf..017be955 100644 --- a/doc/src/install.rst +++ b/doc/src/install.rst @@ -14,7 +14,7 @@ mature as the C implementation yet. The current `!psycopg2` implementation supports: -- Python 2 versions from 2.4 to 2.7 +- Python 2 versions from 2.5 to 2.7 - Python 3 versions from 3.1 to 3.3 - PostgreSQL versions from 7.4 to 9.2 diff --git a/lib/__init__.py b/lib/__init__.py index 892d8038..e9618fd0 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -41,23 +41,6 @@ Homepage: http://initd.org/projects/psycopg2 # Import modules needed by _psycopg to allow tools like py2exe to do # their work without bothering about the module dependencies. -import sys, warnings -if sys.version_info >= (2, 3): - try: - import datetime as _psycopg_needs_datetime - except: - warnings.warn( - "can't import datetime module probably needed by _psycopg", - RuntimeWarning) -if sys.version_info >= (2, 4): - try: - import decimal as _psycopg_needs_decimal - except: - warnings.warn( - "can't import decimal module probably needed by _psycopg", - RuntimeWarning) -del sys, warnings - # Note: the first internal import should be _psycopg, otherwise the real cause # of a failed loading of the C module may get hidden, see # http://archives.postgresql.org/psycopg/2011-02/msg00044.php diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index 8794e7fe..3f5d3ba6 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -1358,7 +1358,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs) PyObject *file, *columns = NULL, *res = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&s|ss" CONV_CODE_PY_SSIZE_T "O", kwlist, + "O&s|ssnO", kwlist, _psyco_curs_has_read_check, &file, &table_name, &sep, &null, &bufsize, &columns)) { @@ -1535,7 +1535,7 @@ psyco_curs_copy_expert(cursorObject *self, PyObject *args, PyObject *kwargs) static char *kwlist[] = {"sql", "file", "size", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "OO|" CONV_CODE_PY_SSIZE_T, kwlist, &sql, &file, &bufsize)) + "OO|n", kwlist, &sql, &file, &bufsize)) { return NULL; } EXC_IF_CURS_CLOSED(self); diff --git a/psycopg/error_type.c b/psycopg/error_type.c index fd0947bc..8e916530 100644 --- a/psycopg/error_type.c +++ b/psycopg/error_type.c @@ -131,8 +131,6 @@ static struct PyGetSetDef error_getsets[] = { }; -#if PY_VERSION_HEX >= 0x02050000 - /* Error.__reduce__ * * The method is required to make exceptions picklable: set the cursor @@ -227,21 +225,10 @@ error: return rv; } -#endif /* PY_VERSION_HEX >= 0x02050000 */ - static PyMethodDef error_methods[] = { -#if PY_VERSION_HEX >= 0x02050000 - /* Make Error and all its subclasses picklable. - * - * TODO: this comment applied to the __reduce_ex__ implementation: now - * pickling may work on Py 2.4 too... but it's 2013 now. - * - * Don't do it it on Py 2.4: [__reduce_ex__] it is not used by the pickle - * protocol, and if called manually fails in an unsettling way, - * probably because the exceptions were old-style classes. */ + /* Make Error and all its subclasses picklable. */ {"__reduce__", (PyCFunction)psyco_error_reduce, METH_NOARGS }, {"__setstate__", (PyCFunction)psyco_error_setstate, METH_O }, -#endif {NULL} }; diff --git a/psycopg/lobject_type.c b/psycopg/lobject_type.c index 90546e79..b25074d9 100644 --- a/psycopg/lobject_type.c +++ b/psycopg/lobject_type.c @@ -128,7 +128,7 @@ psyco_lobj_read(lobjectObject *self, PyObject *args) Py_ssize_t size = -1; char *buffer; - if (!PyArg_ParseTuple(args, "|" CONV_CODE_PY_SSIZE_T, &size)) return NULL; + if (!PyArg_ParseTuple(args, "|n", &size)) return NULL; EXC_IF_LOBJ_CLOSED(self); EXC_IF_LOBJ_LEVEL0(self); diff --git a/psycopg/python.h b/psycopg/python.h index 9fce6e13..90c82516 100644 --- a/psycopg/python.h +++ b/psycopg/python.h @@ -31,36 +31,12 @@ #include #endif -#if PY_VERSION_HEX < 0x02040000 -# error "psycopg requires Python >= 2.4" -#endif - #if PY_VERSION_HEX < 0x02050000 -/* Function missing in Py 2.4 */ -#define PyErr_WarnEx(cat,msg,lvl) PyErr_Warn(cat,msg) -#endif - -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) - typedef int Py_ssize_t; - #define PY_SSIZE_T_MIN INT_MIN - #define PY_SSIZE_T_MAX INT_MAX - #define PY_FORMAT_SIZE_T "" - #define PyInt_FromSsize_t(x) PyInt_FromLong((x)) - - #define lenfunc inquiry - #define ssizeargfunc intargfunc - #define readbufferproc getreadbufferproc - #define writebufferproc getwritebufferproc - #define segcountproc getsegcountproc - #define charbufferproc getcharbufferproc - - #define CONV_CODE_PY_SSIZE_T "i" -#else - #define CONV_CODE_PY_SSIZE_T "n" +# error "psycopg requires Python >= 2.5" #endif /* hash() return size changed around version 3.2a4 on 64bit platforms. Before - * this, the return size was always a long, regardless of arch. ~3.2 + * this, the return size was always a long, regardless of arch. ~3.2 * introduced the Py_hash_t & Py_uhash_t typedefs with the resulting sizes * based upon arch. */ #if PY_VERSION_HEX < 0x030200A4 @@ -76,11 +52,6 @@ typedef unsigned long Py_uhash_t; #define PyVarObject_HEAD_INIT(x,n) PyObject_HEAD_INIT(x) n, #endif -/* Missing at least in Python 2.4 */ -#ifndef Py_MEMCPY -#define Py_MEMCPY memcpy -#endif - /* FORMAT_CODE_PY_SSIZE_T is for Py_ssize_t: */ #define FORMAT_CODE_PY_SSIZE_T "%" PY_FORMAT_SIZE_T "d" diff --git a/tests/test_types_basic.py b/tests/test_types_basic.py index 4e41d9f4..6f7294ee 100755 --- a/tests/test_types_basic.py +++ b/tests/test_types_basic.py @@ -22,10 +22,7 @@ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public # License for more details. -try: - import decimal -except: - pass +import decimal import sys from functools import wraps @@ -66,10 +63,6 @@ class TypesBasicTests(unittest.TestCase): self.failUnless(s == 1971, "wrong integer quoting: " + str(s)) s = self.execute("SELECT %s AS foo", (1971L,)) self.failUnless(s == 1971L, "wrong integer quoting: " + str(s)) - if sys.version_info[0:2] < (2, 4): - s = self.execute("SELECT %s AS foo", (19.10,)) - self.failUnless(abs(s - 19.10) < 0.001, - "wrong float quoting: " + str(s)) def testBoolean(self): x = self.execute("SELECT %s as foo", (False,)) @@ -78,21 +71,18 @@ class TypesBasicTests(unittest.TestCase): self.assert_(x is True) def testDecimal(self): - if sys.version_info[0:2] >= (2, 4): - s = self.execute("SELECT %s AS foo", (decimal.Decimal("19.10"),)) - self.failUnless(s - decimal.Decimal("19.10") == 0, - "wrong decimal quoting: " + str(s)) - s = self.execute("SELECT %s AS foo", (decimal.Decimal("NaN"),)) - self.failUnless(str(s) == "NaN", "wrong decimal quoting: " + str(s)) - self.failUnless(type(s) == decimal.Decimal, "wrong decimal conversion: " + repr(s)) - s = self.execute("SELECT %s AS foo", (decimal.Decimal("infinity"),)) - self.failUnless(str(s) == "NaN", "wrong decimal quoting: " + str(s)) - self.failUnless(type(s) == decimal.Decimal, "wrong decimal conversion: " + repr(s)) - s = self.execute("SELECT %s AS foo", (decimal.Decimal("-infinity"),)) - self.failUnless(str(s) == "NaN", "wrong decimal quoting: " + str(s)) - self.failUnless(type(s) == decimal.Decimal, "wrong decimal conversion: " + repr(s)) - else: - return self.skipTest("decimal not available") + s = self.execute("SELECT %s AS foo", (decimal.Decimal("19.10"),)) + self.failUnless(s - decimal.Decimal("19.10") == 0, + "wrong decimal quoting: " + str(s)) + s = self.execute("SELECT %s AS foo", (decimal.Decimal("NaN"),)) + self.failUnless(str(s) == "NaN", "wrong decimal quoting: " + str(s)) + self.failUnless(type(s) == decimal.Decimal, "wrong decimal conversion: " + repr(s)) + s = self.execute("SELECT %s AS foo", (decimal.Decimal("infinity"),)) + self.failUnless(str(s) == "NaN", "wrong decimal quoting: " + str(s)) + self.failUnless(type(s) == decimal.Decimal, "wrong decimal conversion: " + repr(s)) + s = self.execute("SELECT %s AS foo", (decimal.Decimal("-infinity"),)) + self.failUnless(str(s) == "NaN", "wrong decimal quoting: " + str(s)) + self.failUnless(type(s) == decimal.Decimal, "wrong decimal conversion: " + repr(s)) def testFloatNan(self): try: