From 9e9933faedd92b77309bb513d3cadf804fc3a15a Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 4 Dec 2010 21:41:31 +0000 Subject: [PATCH 01/11] Update classifier URLs for PyPI. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index a77907a7..628a021e 100644 --- a/setup.py +++ b/setup.py @@ -429,8 +429,8 @@ setup(name="psycopg2", maintainer_email="fog@initd.org", author="Federico Di Gregorio", author_email="fog@initd.org", - url="http://initd.org/tracker/psycopg", - download_url = "http://initd.org/pub/software/psycopg2", + url="http://initd.org/psycopg/", + download_url = "http://initd.org/psycopg/download/", license="GPL with exceptions or ZPL", platforms = ["any"], description=__doc__.split("\n")[0], From 13c2f5a78b79771489ba9376d9e38e21eb70c081 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 4 Dec 2010 21:45:14 +0000 Subject: [PATCH 02/11] Added target to package the docs for PyPI documentation. --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index e73b5f68..ffc7cc58 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,9 @@ docs-html: doc/html/genindex.html docs-txt: doc/psycopg2.txt +# for PyPI documentation +docs-zip: doc/docs.zip + sdist: $(SDIST) # The environment is currently required to build the documentation. @@ -119,6 +122,8 @@ doc/html/genindex.html: $(PLATLIB) $(PURELIB) $(SOURCE_DOC) doc/psycopg2.txt: $(PLATLIB) $(PURELIB) $(SOURCE_DOC) PYTHONPATH=$(ENV_LIB):$(BUILD_DIR) $(MAKE) SPHINXBUILD=$(ENV_BIN)/sphinx-build -C doc text +doc/docs.zip: doc/html/genindex.html + (cd doc/html && zip -r ../docs.zip *) clean: rm -rf build MANIFEST From cf243ccf370942b23180c0c632aec14dd999b538 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 4 Dec 2010 23:21:16 +0000 Subject: [PATCH 03/11] Shorter "never ending query" to test query canceling. If the cancel signal misses the race, this query will stay in the backend until the sleep expires. --- tests/test_cancel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cancel.py b/tests/test_cancel.py index 52383f83..94daec14 100644 --- a/tests/test_cancel.py +++ b/tests/test_cancel.py @@ -35,7 +35,7 @@ class CancelTests(unittest.TestCase): cur = conn.cursor() try: self.assertRaises(psycopg2.extensions.QueryCanceledError, - cur.execute, "select pg_sleep(10000)") + cur.execute, "select pg_sleep(60)") # make sure the connection still works conn.rollback() cur.execute("select 1") From 5a0cfad95f85859607623551d45e46e8b469953d Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 12 Dec 2010 13:39:02 +0000 Subject: [PATCH 04/11] Bump to next dev version. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 628a021e..7faefd40 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,7 @@ from distutils.ccompiler import get_default_compiler # Take a look at http://www.python.org/dev/peps/pep-0386/ # for a consistent versioning pattern. -PSYCOPG_VERSION = '2.3.1' +PSYCOPG_VERSION = '2.3.2.dev0' version_flags = ['dt', 'dec'] From a08419406cdb52a4d0b1f7ac3dbc2f655b5ed67d Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Thu, 9 Dec 2010 16:22:20 +0200 Subject: [PATCH 05/11] Don't segfault when PQparameterStatus(DateStyle) returns NULL pgbouncer for example does not pass on DateStyle. --- psycopg/connection_int.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c index 73292b88..8451b453 100644 --- a/psycopg/connection_int.c +++ b/psycopg/connection_int.c @@ -299,6 +299,10 @@ conn_is_datestyle_ok(PGconn *pgconn) ds = PQparameterStatus(pgconn, "DateStyle"); Dprintf("conn_connect: DateStyle %s", ds); + /* pgbouncer does not pass on DateStyle */ + if (ds == NULL) + return 0; + /* Return true if ds starts with "ISO" * e.g. "ISO, DMY" is fine, "German" not. */ return (ds[0] == 'I' && ds[1] == 'S' && ds[2] == 'O'); From ddd2de0410eb455b78f0bc3695075487cfa35a5e Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 18 Dec 2010 15:38:56 +0000 Subject: [PATCH 06/11] Updated ChangeLog/NEWS after ticket #24 patch commit. --- ChangeLog | 8 ++++++++ NEWS-2.3 | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/ChangeLog b/ChangeLog index 41a90c6f..b12c675f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-12-18 Daniele Varrazzo + + * setup.py: bumped to version 2.3.2.dev0 + + * psycopg/connection_int.c: applied patch from Marti Raudsepp to close + ticket #24. Fixed segfault in connection when DateStyle not available + (e.g. pgbouncer appars not passing it to the client) + 2010-12-04 Daniele Varrazzo * setup.py: bumped to version 2.3.1.dev0 diff --git a/NEWS-2.3 b/NEWS-2.3 index d8208d9b..179ab299 100644 --- a/NEWS-2.3 +++ b/NEWS-2.3 @@ -1,3 +1,10 @@ +What's new in psycopg 2.3.2 +--------------------------- + + - Fixed segfault with middleware not passing DateStyle to the client + (ticket #24). Bug report and patch by Marti Raudsepp. + + What's new in psycopg 2.3.1 --------------------------- From 69c66a3a3fa8e0f9d662ddc986aa32c5a86e2474 Mon Sep 17 00:00:00 2001 From: Federico Di Gregorio Date: Mon, 20 Dec 2010 13:33:21 +0100 Subject: [PATCH 07/11] Preparing release 2.3.2 --- ZPsycopgDA/DA.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ZPsycopgDA/DA.py b/ZPsycopgDA/DA.py index e9f4312f..d88766ef 100644 --- a/ZPsycopgDA/DA.py +++ b/ZPsycopgDA/DA.py @@ -16,7 +16,7 @@ # their work without bothering about the module dependencies. -ALLOWED_PSYCOPG_VERSIONS = ('2.3.0','2.3.1') +ALLOWED_PSYCOPG_VERSIONS = ('2.3.0','2.3.1','2.3.2') import sys import time diff --git a/setup.py b/setup.py index 7faefd40..4417f527 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,7 @@ from distutils.ccompiler import get_default_compiler # Take a look at http://www.python.org/dev/peps/pep-0386/ # for a consistent versioning pattern. -PSYCOPG_VERSION = '2.3.2.dev0' +PSYCOPG_VERSION = '2.3.2' version_flags = ['dt', 'dec'] From b5a8facb9cc54990b5248b3fae1b1eaa14090e11 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 31 Dec 2010 18:40:28 +0100 Subject: [PATCH 08/11] Added test to show failed adaptation of None in records. --- tests/types_extras.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/types_extras.py b/tests/types_extras.py index 6f77d976..3986c77f 100644 --- a/tests/types_extras.py +++ b/tests/types_extras.py @@ -349,6 +349,22 @@ class HstoreTestCase(unittest.TestCase): ok(dict(zip(ab, ab))) +class AdaptTypeTestCase(unittest.TestCase): + def setUp(self): + self.conn = psycopg2.connect(tests.dsn) + + def tearDown(self): + self.conn.close() + + def test_none_in_record(self): + curs = self.conn.cursor() + s = curs.mogrify("SELECT %s;", [(42, None)]) + self.assertEqual("SELECT (42, NULL);", s) + curs.execute("SELECT %s;", [(42, None)]) + d = curs.fetchone()[0] + self.assertEqual("(42,)", d) + + def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__) From 30921b58a8a3fb89f14f5db3b9a724fbe2f46efa Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 31 Dec 2010 18:55:33 +0100 Subject: [PATCH 09/11] Dropped conversion from None to NULL in adapter. It was an error as the string is not conform to the protocol. The error is masked by the None fast path in _mogrify, but surfaces when adapting a tuple contains a None. --- psycopg/microprotocols.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/psycopg/microprotocols.c b/psycopg/microprotocols.c index 12ec7fb0..a00f20d2 100644 --- a/psycopg/microprotocols.c +++ b/psycopg/microprotocols.c @@ -135,11 +135,6 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) /* we don't check for exact type conformance as specified in PEP 246 because the ISQLQuote type is abstract and there is no way to get a quotable object to be its instance */ - - /* None is always adapted to NULL */ - - if (obj == Py_None) - return PyString_FromString("NULL"); Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name); From 506ce93a5b2de01116c0023cc0da681e825fb3e7 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 1 Jan 2011 12:55:41 +0100 Subject: [PATCH 10/11] Bump to the next dev version. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4417f527..84fa3600 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,7 @@ from distutils.ccompiler import get_default_compiler # Take a look at http://www.python.org/dev/peps/pep-0386/ # for a consistent versioning pattern. -PSYCOPG_VERSION = '2.3.2' +PSYCOPG_VERSION = '2.3.3.dev0' version_flags = ['dt', 'dec'] From fdfa2de1a1744cabf918d8e4bf2a8740cbba101e Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 31 Dec 2010 19:21:44 +0100 Subject: [PATCH 11/11] Fixed adaptation of None in composite types (ticket #26). Added an adapter for None: it is usually not invoked as adaptation to NULL is a fast path in mogrify, but can be invoked by composite types. Notice that composite types still have the option to fast-path None (e.g. list adapter does). --- NEWS-2.3 | 7 +++++++ lib/__init__.py | 1 + lib/extensions.py | 13 +++++++++++++ tests/types_extras.py | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/NEWS-2.3 b/NEWS-2.3 index 179ab299..ff211a31 100644 --- a/NEWS-2.3 +++ b/NEWS-2.3 @@ -1,3 +1,10 @@ +What's new in psycopg 2.3.3 +--------------------------- + + - Fixed adaptation of None in composite types (ticket #26). Bug report by + Karsten Hilbert. + + What's new in psycopg 2.3.2 --------------------------- diff --git a/lib/__init__.py b/lib/__init__.py index 2968284c..065b2a70 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -82,6 +82,7 @@ from _psycopg import __version__ import psycopg2.extensions as _ext _ext.register_adapter(tuple, _ext.SQL_IN) +_ext.register_adapter(type(None), _ext.NoneAdapter) __all__ = filter(lambda k: not k.startswith('_'), locals().keys()) diff --git a/lib/extensions.py b/lib/extensions.py index fca79738..24a9a6b8 100644 --- a/lib/extensions.py +++ b/lib/extensions.py @@ -128,4 +128,17 @@ class SQL_IN(object): __str__ = getquoted +class NoneAdapter(object): + """Adapt None to NULL. + + This adapter is not used normally as a fast path in mogrify uses NULL, + but it makes easier to adapt composite types. + """ + def __init__(self, obj): + pass + + def getquoted(self): + return "NULL" + + __all__ = filter(lambda k: not k.startswith('_'), locals().keys()) diff --git a/tests/types_extras.py b/tests/types_extras.py index 3986c77f..7f18c96e 100644 --- a/tests/types_extras.py +++ b/tests/types_extras.py @@ -364,6 +364,26 @@ class AdaptTypeTestCase(unittest.TestCase): d = curs.fetchone()[0] self.assertEqual("(42,)", d) + def test_none_fast_path(self): + # the None adapter is not actually invoked in regular adaptation + ext = psycopg2.extensions + + class WonkyAdapter(object): + def __init__(self, obj): pass + def getquoted(self): return "NOPE!" + + curs = self.conn.cursor() + + orig_adapter = ext.adapters[type(None), ext.ISQLQuote] + try: + ext.register_adapter(type(None), WonkyAdapter) + self.assertEqual(ext.adapt(None).getquoted(), "NOPE!") + + s = curs.mogrify("SELECT %s;", (None,)) + self.assertEqual("SELECT NULL;", s) + + finally: + ext.register_adapter(type(None), orig_adapter) def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__)