Merge branch 'python2' into python3

Conflicts:
	ChangeLog
	NEWS-2.3
	lib/extensions.py
	psycopg/microprotocols.c
	setup.py
This commit is contained in:
Daniele Varrazzo 2011-01-01 17:14:54 +01:00
commit 3e94375cf7
11 changed files with 86 additions and 11 deletions

View File

@ -3,6 +3,12 @@
* connection.h: added codec attribute to avoid repeated codec name * connection.h: added codec attribute to avoid repeated codec name
lookups during unicode query/params manipulations. lookups during unicode query/params manipulations.
* 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-15 Daniele Varrazzo <daniele.varrazzo@gmail.com> 2010-12-15 Daniele Varrazzo <daniele.varrazzo@gmail.com>
* psycopg/utils.c: Added psycopg_strdup function. * psycopg/utils.c: Added psycopg_strdup function.

View File

@ -62,6 +62,9 @@ docs-html: doc/html/genindex.html
docs-txt: doc/psycopg2.txt docs-txt: doc/psycopg2.txt
# for PyPI documentation
docs-zip: doc/docs.zip
sdist: $(SDIST) sdist: $(SDIST)
# The environment is currently required to build the documentation. # 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) doc/psycopg2.txt: $(PLATLIB) $(PURELIB) $(SOURCE_DOC)
PYTHONPATH=$(ENV_LIB):$(BUILD_DIR) $(MAKE) SPHINXBUILD=$(ENV_BIN)/sphinx-build -C doc text 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: clean:
rm -rf build MANIFEST rm -rf build MANIFEST

View File

@ -1,12 +1,26 @@
What's new in psycopg 2.3.2 What's new in psycopg 2.3.3
--------------------------- ---------------------------
* Changes:
- Improved PostgreSQL-Python encodings mapping. Added a few - Improved PostgreSQL-Python encodings mapping. Added a few
missing encodings: EUC_CN, EUC_JIS_2004, ISO885910, ISO885916, missing encodings: EUC_CN, EUC_JIS_2004, ISO885910, ISO885916,
LATIN10, SHIFT_JIS_2004. LATIN10, SHIFT_JIS_2004.
- Dropped repeated dictionary lookups with unicode query/parameters. - Dropped repeated dictionary lookups with unicode query/parameters.
- Empty lists correctly roundtrip Python -> PostgreSQL -> Python. - Empty lists correctly roundtrip Python -> PostgreSQL -> Python.
* Bug fixes
- Fixed adaptation of None in composite types (ticket #26). Bug report by
Karsten Hilbert.
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 What's new in psycopg 2.3.1
--------------------------- ---------------------------

View File

@ -16,7 +16,7 @@
# their work without bothering about the module dependencies. # 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 sys
import time import time

View File

@ -82,6 +82,7 @@ from _psycopg import __version__
import psycopg2.extensions as _ext import psycopg2.extensions as _ext
_ext.register_adapter(tuple, _ext.SQL_IN) _ext.register_adapter(tuple, _ext.SQL_IN)
_ext.register_adapter(type(None), _ext.NoneAdapter)
__all__ = filter(lambda k: not k.startswith('_'), locals().keys()) __all__ = filter(lambda k: not k.startswith('_'), locals().keys())

View File

@ -138,6 +138,19 @@ class SQL_IN(object):
__str__ = getquoted __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"
# Add the "cleaned" version of the encodings to the key. # Add the "cleaned" version of the encodings to the key.
# When the encoding is set its name is cleaned up from - and _ and turned # When the encoding is set its name is cleaned up from - and _ and turned
# uppercase, so an encoding not respecting these rules wouldn't be found in the # uppercase, so an encoding not respecting these rules wouldn't be found in the
@ -146,4 +159,5 @@ for k, v in encodings.items():
k = k.replace('_', '').replace('-', '').upper() k = k.replace('_', '').replace('-', '').upper()
encodings[k] = v encodings[k] = v
__all__ = filter(lambda k: not k.startswith('_'), locals().keys()) __all__ = filter(lambda k: not k.startswith('_'), locals().keys())

View File

@ -373,6 +373,10 @@ conn_is_datestyle_ok(PGconn *pgconn)
ds = PQparameterStatus(pgconn, "DateStyle"); ds = PQparameterStatus(pgconn, "DateStyle");
Dprintf("conn_connect: DateStyle %s", ds); Dprintf("conn_connect: DateStyle %s", ds);
/* pgbouncer does not pass on DateStyle */
if (ds == NULL)
return 0;
/* Return true if ds starts with "ISO" /* Return true if ds starts with "ISO"
* e.g. "ISO, DMY" is fine, "German" not. */ * e.g. "ISO, DMY" is fine, "German" not. */
return (ds[0] == 'I' && ds[1] == 'S' && ds[2] == 'O'); return (ds[0] == 'I' && ds[1] == 'S' && ds[2] == 'O');

View File

@ -135,11 +135,6 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
because the ISQLQuote type is abstract and there is no way to get a because the ISQLQuote type is abstract and there is no way to get a
quotable object to be its instance */ quotable object to be its instance */
/* None is always adapted to NULL */
if (obj == Py_None)
return Bytes_FromString("NULL");
Dprintf("microprotocols_adapt: trying to adapt %s", Dprintf("microprotocols_adapt: trying to adapt %s",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);

View File

@ -66,7 +66,7 @@ except ImportError:
# Take a look at http://www.python.org/dev/peps/pep-0386/ # Take a look at http://www.python.org/dev/peps/pep-0386/
# for a consistent versioning pattern. # for a consistent versioning pattern.
PSYCOPG_VERSION = '2.3.2.dev0' PSYCOPG_VERSION = '2.3.3.dev0'
version_flags = ['dt', 'dec'] version_flags = ['dt', 'dec']
@ -471,8 +471,8 @@ setup(name="psycopg2",
maintainer_email="fog@initd.org", maintainer_email="fog@initd.org",
author="Federico Di Gregorio", author="Federico Di Gregorio",
author_email="fog@initd.org", author_email="fog@initd.org",
url="http://initd.org/tracker/psycopg", url="http://initd.org/psycopg/",
download_url = "http://initd.org/pub/software/psycopg2", download_url = "http://initd.org/psycopg/download/",
license="GPL with exceptions or ZPL", license="GPL with exceptions or ZPL",
platforms = ["any"], platforms = ["any"],
description=__doc__.split("\n")[0], description=__doc__.split("\n")[0],

View File

@ -35,7 +35,7 @@ class CancelTests(unittest.TestCase):
cur = conn.cursor() cur = conn.cursor()
try: try:
self.assertRaises(psycopg2.extensions.QueryCanceledError, self.assertRaises(psycopg2.extensions.QueryCanceledError,
cur.execute, "select pg_sleep(10000)") cur.execute, "select pg_sleep(60)")
# make sure the connection still works # make sure the connection still works
conn.rollback() conn.rollback()
cur.execute("select 1") cur.execute("select 1")

View File

@ -354,6 +354,42 @@ class HstoreTestCase(unittest.TestCase):
ok(dict(zip(ab, ab))) 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_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(): def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__) return unittest.TestLoader().loadTestsFromName(__name__)