Hello community,
here is the log from the commit of package python-psycopg2 for openSUSE:Factory
checked in at 2020-03-03 10:15:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-psycopg2 (Old)
and /work/SRC/openSUSE:Factory/.python-psycopg2.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-psycopg2"
Tue Mar 3 10:15:22 2020 rev:32 rq:780392 version:2.8.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-psycopg2/python-psycopg2.changes
2019-10-16 09:15:17.215467320 +0200
+++
/work/SRC/openSUSE:Factory/.python-psycopg2.new.26092/python-psycopg2.changes
2020-03-03 10:15:49.514598836 +0100
@@ -1,0 +2,16 @@
+Fri Feb 28 21:49:40 UTC 2020 - Dirk Mueller <[email protected]>
+
+- update to 2.8.4:
+ - Fixed building with Python 3.8 (:ticket:`#854`).
+ - Don't swallow keyboard interrupts on connect when a password is specified
+ in the connection string (:ticket:`#898`).
+ - Don't advance replication cursor when the message wasn't confirmed
+ (:ticket:`#940`).
+ - Fixed inclusion of ``time.h`` on linux (:ticket:`#951`).
+ - Fixed int overflow for large values in
`~psycopg2.extensions.Column.table_oid`
+ and `~psycopg2.extensions.Column.type_code` (:ticket:`#961`).
+ - `~psycopg2.errorcodes` map and `~psycopg2.errors` classes updated to
+ PostgreSQL 12.
+ - Wheel package compiled against OpenSSL 1.1.1d and PostgreSQL at least 11.4.
+
+-------------------------------------------------------------------
Old:
----
psycopg2-2.8.3.tar.gz
New:
----
psycopg2-2.8.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-psycopg2.spec ++++++
--- /var/tmp/diff_new_pack.ldglhc/_old 2020-03-03 10:15:50.910601724 +0100
+++ /var/tmp/diff_new_pack.ldglhc/_new 2020-03-03 10:15:50.914601732 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-psycopg2
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-psycopg2
-Version: 2.8.3
+Version: 2.8.4
Release: 0
Summary: Python-PostgreSQL Database Adapter
License: LGPL-3.0-or-later AND (LGPL-3.0-or-later OR ZPL-2.0) AND
SUSE-GPL-2.0-with-openssl-exception
++++++ psycopg2-2.8.3.tar.gz -> psycopg2-2.8.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/NEWS new/psycopg2-2.8.4/NEWS
--- old/psycopg2-2.8.3/NEWS 2019-06-11 00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/NEWS 2019-10-20 02:45:30.000000000 +0200
@@ -1,6 +1,22 @@
Current release
---------------
+What's new in psycopg 2.8.4
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Fixed building with Python 3.8 (:ticket:`#854`).
+- Don't swallow keyboard interrupts on connect when a password is specified
+ in the connection string (:ticket:`#898`).
+- Don't advance replication cursor when the message wasn't confirmed
+ (:ticket:`#940`).
+- Fixed inclusion of ``time.h`` on linux (:ticket:`#951`).
+- Fixed int overflow for large values in
`~psycopg2.extensions.Column.table_oid`
+ and `~psycopg2.extensions.Column.type_code` (:ticket:`#961`).
+- `~psycopg2.errorcodes` map and `~psycopg2.errors` classes updated to
+ PostgreSQL 12.
+- Wheel package compiled against OpenSSL 1.1.1d and PostgreSQL at least 11.4.
+
+
What's new in psycopg 2.8.3
^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/PKG-INFO new/psycopg2-2.8.4/PKG-INFO
--- old/psycopg2-2.8.3/PKG-INFO 2019-06-11 00:38:59.000000000 +0200
+++ new/psycopg2-2.8.4/PKG-INFO 2019-10-20 02:45:39.000000000 +0200
@@ -1,12 +1,11 @@
Metadata-Version: 1.2
Name: psycopg2
-Version: 2.8.3
+Version: 2.8.4
Summary: psycopg2 - Python-PostgreSQL Database Adapter
Home-page: http://initd.org/psycopg/
Author: Federico Di Gregorio
Author-email: [email protected]
License: LGPL with exceptions or ZPL
-Download-URL:
http://initd.org/psycopg/tarballs/PSYCOPG-2-8/psycopg2-2.8.3.tar.gz
Description-Content-Type: UNKNOWN
Description: Psycopg is the most popular PostgreSQL database adapter for the
Python
programming language. Its main features are the complete
implementation of
@@ -93,6 +92,7 @@
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: C
Classifier: Programming Language :: SQL
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/doc/src/connection.rst
new/psycopg2-2.8.4/doc/src/connection.rst
--- old/psycopg2-2.8.3/doc/src/connection.rst 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/doc/src/connection.rst 2019-10-20 02:45:30.000000000
+0200
@@ -117,7 +117,7 @@
with a `~connection.commit()`/`~connection.rollback()` before
closing.
- .. _PgBouncer: http://pgbouncer.projects.postgresql.org/
+ .. _PgBouncer: http://www.pgbouncer.org/
.. index::
@@ -639,7 +639,7 @@
:param new_oid: Create a new object using the specified OID. The
function raises `~psycopg2.OperationalError` if the OID is already
in use. Default is 0, meaning assign a new one automatically.
- :param new_file: The name of a file to be imported in the the database
+ :param new_file: The name of a file to be imported in the database
(using the |lo_import|_ function)
:param lobject_factory: Subclass of
`~psycopg2.extensions.lobject` to be instantiated.
@@ -749,7 +749,7 @@
.. rubric:: informative methods of the native connection
- .. note::
+ .. note::
These methods are better accessed using the `~connection.info`
attributes and may be dropped in future versions.
@@ -822,8 +822,10 @@
Also available as `~connection.info`\ `!.`\
`~psycopg2.extensions.ConnectionInfo.backend_pid`.
- Returns the process ID (PID) of the backend server process handling
- this connection.
+ Returns the process ID (PID) of the backend server process *you
+ connected to*. Note that if you use a connection pool service such as
+ PgBouncer_ this value will not be updated if your connection is
+ switched to a different backend.
Note that the PID belongs to a process executing on the database
server host, not the local host!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/doc/src/errorcodes.rst
new/psycopg2-2.8.4/doc/src/errorcodes.rst
--- old/psycopg2-2.8.3/doc/src/errorcodes.rst 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/doc/src/errorcodes.rst 2019-10-20 02:45:30.000000000
+0200
@@ -50,7 +50,7 @@
'42P01'
Constants representing all the error values defined by PostgreSQL versions
-between 8.1 and 11 are included in the module.
+between 8.1 and 12 are included in the module.
.. autofunction:: lookup(code)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/doc/src/errors.rst
new/psycopg2-2.8.4/doc/src/errors.rst
--- old/psycopg2-2.8.3/doc/src/errors.rst 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/doc/src/errors.rst 2019-10-20 02:45:30.000000000
+0200
@@ -10,11 +10,13 @@
.. versionadded:: 2.8
+.. versionchanged:: 2.8.4 added errors introduced in PostgreSQL 12
+
This module exposes the classes psycopg raises upon receiving an error from
the database with a :sql:`SQLSTATE` value attached (available in the
`~psycopg2.Error.pgcode` attribute). The content of the module is generated
from the PostgreSQL source code and includes classes for every error defined
-by PostgreSQL in versions between 9.1 and 11.
+by PostgreSQL in versions between 9.1 and 12.
Every class in the module is named after what referred as "condition name" `in
the documentation`__, converted to CamelCase: e.g. the error 22012,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/doc/src/extensions.rst
new/psycopg2-2.8.4/doc/src/extensions.rst
--- old/psycopg2-2.8.3/doc/src/extensions.rst 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/doc/src/extensions.rst 2019-10-20 02:45:30.000000000
+0200
@@ -413,9 +413,9 @@
.. method:: getquoted()
- Return the string enclosed in single quotes. Any single quote
- appearing in the the string is escaped by doubling it according to SQL
- string constants syntax. Backslashes are escaped too.
+ Return the string enclosed in single quotes. Any single quote appearing
+ in the string is escaped by doubling it according to SQL string
+ constants syntax. Backslashes are escaped too.
>>> QuotedString(r"O'Reilly").getquoted()
"'O''Reilly'"
@@ -758,8 +758,8 @@
.. data:: ISOLATION_LEVEL_READ_COMMITTED
- This is usually the the default PostgreSQL value, but a different default
- may be set in the database configuration.
+ This is usually the default PostgreSQL value, but a different default may
+ be set in the database configuration.
A new transaction is started at the first `~cursor.execute()` command on a
cursor and at each new `!execute()` after a `~connection.commit()` or a
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/doc/src/extras.rst
new/psycopg2-2.8.4/doc/src/extras.rst
--- old/psycopg2-2.8.3/doc/src/extras.rst 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/doc/src/extras.rst 2019-10-20 02:45:30.000000000
+0200
@@ -643,6 +643,13 @@
loads = lambda x: json.loads(x, parse_float=Decimal)
psycopg2.extras.register_json(conn, loads=loads)
+Or, if you want to use an alternative JSON module implementation, such as the
+faster UltraJSON_, you can use::
+
+ psycopg2.extras.register_default_json(loads=ujson.loads, globally=True)
+ psycopg2.extras.register_default_jsonb(loads=ujson.loads, globally=True)
+
+.. _UltraJSON: https://pypi.org/project/ujson/
.. autoclass:: Json
@@ -1011,7 +1018,7 @@
The current implementation of `~cursor.executemany()` is (using an extremely
charitable understatement) not particularly performing. These functions can
-be used to speed up the repeated execution of a statement againts a set of
+be used to speed up the repeated execution of a statement against a set of
parameters. By reducing the number of server roundtrips the performance can be
`orders of magnitude better`__ than using `!executemany()`.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/doc/src/faq.rst
new/psycopg2-2.8.4/doc/src/faq.rst
--- old/psycopg2-2.8.3/doc/src/faq.rst 2019-06-11 00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/doc/src/faq.rst 2019-10-20 02:45:30.000000000 +0200
@@ -271,7 +271,7 @@
What are the advantages or disadvantages of using named cursors?
The only disadvantages is that they use up resources on the server and
- that there is a little overhead because a at least two queries (one to
+ that there is a little overhead because at least two queries (one to
create the cursor and one to fetch the initial result set) are issued to
the backend. The advantage is that data is fetched one chunk at a time:
using small `~cursor.fetchmany()` values it is possible to use very
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/doc/src/install.rst
new/psycopg2-2.8.4/doc/src/install.rst
--- old/psycopg2-2.8.3/doc/src/install.rst 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/doc/src/install.rst 2019-10-20 02:45:30.000000000
+0200
@@ -35,8 +35,8 @@
NOTE: keep consistent with setup.py and the /features/ page.
- Python version 2.7
-- Python 3 versions from 3.4 to 3.7
-- PostgreSQL server versions from 7.4 to 11
+- Python 3 versions from 3.4 to 3.8
+- PostgreSQL server versions from 7.4 to 12
- PostgreSQL client library version from 9.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/lib/errorcodes.py
new/psycopg2-2.8.4/lib/errorcodes.py
--- old/psycopg2-2.8.3/lib/errorcodes.py 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/lib/errorcodes.py 2019-10-20 02:45:30.000000000
+0200
@@ -205,6 +205,21 @@
ARRAY_SUBSCRIPT_ERROR = '2202E'
INVALID_TABLESAMPLE_REPEAT = '2202G'
INVALID_TABLESAMPLE_ARGUMENT = '2202H'
+DUPLICATE_JSON_OBJECT_KEY_VALUE = '22030'
+INVALID_JSON_TEXT = '22032'
+INVALID_SQL_JSON_SUBSCRIPT = '22033'
+MORE_THAN_ONE_SQL_JSON_ITEM = '22034'
+NO_SQL_JSON_ITEM = '22035'
+NON_NUMERIC_SQL_JSON_ITEM = '22036'
+NON_UNIQUE_KEYS_IN_A_JSON_OBJECT = '22037'
+SINGLETON_SQL_JSON_ITEM_REQUIRED = '22038'
+SQL_JSON_ARRAY_NOT_FOUND = '22039'
+SQL_JSON_MEMBER_NOT_FOUND = '2203A'
+SQL_JSON_NUMBER_NOT_FOUND = '2203B'
+SQL_JSON_OBJECT_NOT_FOUND = '2203C'
+TOO_MANY_JSON_ARRAY_ELEMENTS = '2203D'
+TOO_MANY_JSON_OBJECT_MEMBERS = '2203E'
+SQL_JSON_SCALAR_REQUIRED = '2203F'
FLOATING_POINT_EXCEPTION = '22P01'
INVALID_TEXT_REPRESENTATION = '22P02'
INVALID_BINARY_REPRESENTATION = '22P03'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/connection.h
new/psycopg2-2.8.4/psycopg/connection.h
--- old/psycopg2-2.8.3/psycopg/connection.h 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/connection.h 2019-10-20 02:45:30.000000000
+0200
@@ -164,7 +164,8 @@
HIDDEN void conn_notice_clean(connectionObject *self);
HIDDEN void conn_notifies_process(connectionObject *self);
RAISES_NEG HIDDEN int conn_setup(connectionObject *self);
-HIDDEN int conn_connect(connectionObject *self, long int async);
+HIDDEN int conn_connect(connectionObject *self, const char *dsn, long int
async);
+HIDDEN char *conn_obscure_password(const char *dsn);
HIDDEN void conn_close(connectionObject *self);
HIDDEN void conn_close_locked(connectionObject *self);
RAISES_NEG HIDDEN int conn_commit(connectionObject *self);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/connection_int.c
new/psycopg2-2.8.4/psycopg/connection_int.c
--- old/psycopg2-2.8.3/psycopg/connection_int.c 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/connection_int.c 2019-10-20 02:45:30.000000000
+0200
@@ -705,7 +705,7 @@
/* conn_connect - execute a connection to the database */
static int
-_conn_sync_connect(connectionObject *self)
+_conn_sync_connect(connectionObject *self, const char *dsn)
{
int green;
@@ -714,26 +714,26 @@
green = psyco_green();
if (!green) {
Py_BEGIN_ALLOW_THREADS;
- self->pgconn = PQconnectdb(self->dsn);
+ self->pgconn = PQconnectdb(dsn);
Py_END_ALLOW_THREADS;
Dprintf("conn_connect: new PG connection at %p", self->pgconn);
}
else {
Py_BEGIN_ALLOW_THREADS;
- self->pgconn = PQconnectStart(self->dsn);
+ self->pgconn = PQconnectStart(dsn);
Py_END_ALLOW_THREADS;
Dprintf("conn_connect: new green PG connection at %p", self->pgconn);
}
if (!self->pgconn)
{
- Dprintf("conn_connect: PQconnectdb(%s) FAILED", self->dsn);
+ Dprintf("conn_connect: PQconnectdb(%s) FAILED", dsn);
PyErr_SetString(OperationalError, "PQconnectdb() failed");
return -1;
}
else if (PQstatus(self->pgconn) == CONNECTION_BAD)
{
- Dprintf("conn_connect: PQconnectdb(%s) returned BAD", self->dsn);
+ Dprintf("conn_connect: PQconnectdb(%s) returned BAD", dsn);
PyErr_SetString(OperationalError, PQerrorMessage(self->pgconn));
return -1;
}
@@ -763,23 +763,23 @@
}
static int
-_conn_async_connect(connectionObject *self)
+_conn_async_connect(connectionObject *self, const char *dsn)
{
PGconn *pgconn;
- self->pgconn = pgconn = PQconnectStart(self->dsn);
+ self->pgconn = pgconn = PQconnectStart(dsn);
Dprintf("conn_connect: new postgresql connection at %p", pgconn);
if (pgconn == NULL)
{
- Dprintf("conn_connect: PQconnectStart(%s) FAILED", self->dsn);
+ Dprintf("conn_connect: PQconnectStart(%s) FAILED", dsn);
PyErr_SetString(OperationalError, "PQconnectStart() failed");
return -1;
}
else if (PQstatus(pgconn) == CONNECTION_BAD)
{
- Dprintf("conn_connect: PQconnectdb(%s) returned BAD", self->dsn);
+ Dprintf("conn_connect: PQconnectdb(%s) returned BAD", dsn);
PyErr_SetString(OperationalError, PQerrorMessage(pgconn));
return -1;
}
@@ -800,17 +800,17 @@
}
int
-conn_connect(connectionObject *self, long int async)
+conn_connect(connectionObject *self, const char *dsn, long int async)
{
int rv;
if (async == 1) {
Dprintf("con_connect: connecting in ASYNC mode");
- rv = _conn_async_connect(self);
+ rv = _conn_async_connect(self, dsn);
}
else {
Dprintf("con_connect: connecting in SYNC mode");
- rv = _conn_sync_connect(self);
+ rv = _conn_sync_connect(self, dsn);
}
if (rv != 0) {
@@ -1157,6 +1157,60 @@
Py_END_ALLOW_THREADS;
}
+
+/* Return a copy of the 'dsn' string with the password scrubbed.
+ *
+ * The string returned is allocated on the Python heap.
+ *
+ * In case of error return NULL and raise an exception.
+ */
+char *
+conn_obscure_password(const char *dsn)
+{
+ PQconninfoOption *options = NULL;
+ PyObject *d = NULL, *v = NULL, *pydsn = NULL;
+ char *rv = NULL;
+
+ if (!dsn) {
+ PyErr_SetString(InternalError, "unexpected null string");
+ goto exit;
+ }
+
+ if (!(options = PQconninfoParse(dsn, NULL))) {
+ /* unlikely: the dsn was already tested valid */
+ PyErr_SetString(InternalError, "the connection string is not valid");
+ goto exit;
+ }
+
+ if (!(d = psyco_dict_from_conninfo_options(
+ options, /* include_password = */ 1))) {
+ goto exit;
+ }
+ if (NULL == PyDict_GetItemString(d, "password")) {
+ /* the dsn doesn't have a password */
+ psyco_strdup(&rv, dsn, -1);
+ goto exit;
+ }
+
+ /* scrub the password and put back the connection string together */
+ if (!(v = Text_FromUTF8("xxx"))) { goto exit; }
+ if (0 > PyDict_SetItemString(d, "password", v)) { goto exit; }
+ if (!(pydsn = psyco_make_dsn(Py_None, d))) { goto exit; }
+ if (!(pydsn = psyco_ensure_bytes(pydsn))) { goto exit; }
+
+ /* Return the connection string with the password replaced */
+ psyco_strdup(&rv, Bytes_AS_STRING(pydsn), -1);
+
+exit:
+ PQconninfoFree(options);
+ Py_XDECREF(v);
+ Py_XDECREF(d);
+ Py_XDECREF(pydsn);
+
+ return rv;
+}
+
+
/* conn_close_locked - shut down the connection with the lock already taken */
void conn_close_locked(connectionObject *self)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/connection_type.c
new/psycopg2-2.8.4/psycopg/connection_type.c
--- old/psycopg2-2.8.3/psycopg/connection_type.c 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/psycopg/connection_type.c 2019-10-20
02:45:30.000000000 +0200
@@ -968,7 +968,7 @@
Dprintf("psyco_conn_lobject: new lobject for connection at %p", self);
Dprintf("psyco_conn_lobject: parameters: oid = %u, mode = %s",
oid, smode);
- Dprintf("psyco_conn_lobject: parameters: new_oid = %d, new_file = %s",
+ Dprintf("psyco_conn_lobject: parameters: new_oid = %u, new_file = %s",
new_oid, new_file);
if (new_file)
@@ -1297,55 +1297,6 @@
/* initialization and finalization methods */
-RAISES_NEG static int
-obscure_password(connectionObject *conn)
-{
- PQconninfoOption *options;
- PyObject *d = NULL, *v = NULL, *dsn = NULL;
- char *tmp;
- int rv = -1;
-
- if (!conn || !conn->dsn) {
- return 0;
- }
-
- if (!(options = PQconninfoParse(conn->dsn, NULL))) {
- /* unlikely: the dsn was already tested valid */
- return 0;
- }
-
- if (!(d = psyco_dict_from_conninfo_options(
- options, /* include_password = */ 1))) {
- goto exit;
- }
- if (NULL == PyDict_GetItemString(d, "password")) {
- /* the dsn doesn't have a password */
- rv = 0;
- goto exit;
- }
-
- /* scrub the password and put back the connection string together */
- if (!(v = Text_FromUTF8("xxx"))) { goto exit; }
- if (0 > PyDict_SetItemString(d, "password", v)) { goto exit; }
- if (!(dsn = psyco_make_dsn(Py_None, d))) { goto exit; }
- if (!(dsn = psyco_ensure_bytes(dsn))) { goto exit; }
-
- /* Replace the connection string on the connection object */
- tmp = conn->dsn;
- psyco_strdup(&conn->dsn, Bytes_AS_STRING(dsn), -1);
- PyMem_Free(tmp);
-
- rv = 0;
-
-exit:
- PQconninfoFree(options);
- Py_XDECREF(v);
- Py_XDECREF(d);
- Py_XDECREF(dsn);
-
- return rv;
-}
-
static int
connection_setup(connectionObject *self, const char *dsn, long int async)
{
@@ -1356,7 +1307,7 @@
self, async, Py_REFCNT(self)
);
- if (0 > psyco_strdup(&self->dsn, dsn, -1)) { goto exit; }
+ if (!(self->dsn = conn_obscure_password(dsn))) { goto exit; }
if (!(self->notice_list = PyList_New(0))) { goto exit; }
if (!(self->notifies = PyList_New(0))) { goto exit; }
self->async = async;
@@ -1378,7 +1329,7 @@
goto exit;
}
- if (conn_connect(self, async) != 0) {
+ if (conn_connect(self, dsn, async) != 0) {
Dprintf("connection_init: FAILED");
goto exit;
}
@@ -1390,13 +1341,6 @@
self, Py_REFCNT(self));
exit:
- /* here we obfuscate the password even if there was a connection error */
- {
- PyObject *ptype = NULL, *pvalue = NULL, *ptb = NULL;
- PyErr_Fetch(&ptype, &pvalue, &ptb);
- obscure_password(self);
- PyErr_Restore(ptype, pvalue, ptb);
- }
return rv;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/conninfo_type.c
new/psycopg2-2.8.4/psycopg/conninfo_type.c
--- old/psycopg2-2.8.3/psycopg/conninfo_type.c 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/conninfo_type.c 2019-10-20 02:45:30.000000000
+0200
@@ -147,7 +147,7 @@
static const char options_doc[] =
-"The command-line options passed in the the connection request.\n"
+"The command-line options passed in the connection request.\n"
"\n"
".. seealso:: libpq docs for `PQoptions()`__ for details.\n"
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
@@ -362,7 +362,7 @@
static const char backend_pid_doc[] =
-"The process ID (PID) of the backend process handling this connection.\n"
+"The process ID (PID) of the backend process you connected to.\n"
"\n"
":type: `!int`\n"
"\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/cursor_type.c
new/psycopg2-2.8.4/psycopg/cursor_type.c
--- old/psycopg2-2.8.3/psycopg/cursor_type.c 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/cursor_type.c 2019-10-20 02:45:30.000000000
+0200
@@ -1827,7 +1827,7 @@
"Number of records ``iter(cur)`` must fetch per network roundtrip."},
{"description", T_OBJECT, OFFSETOF(description), READONLY,
"Cursor description as defined in DBAPI-2.0."},
- {"lastrowid", T_LONG, OFFSETOF(lastoid), READONLY,
+ {"lastrowid", T_OID, OFFSETOF(lastoid), READONLY,
"The ``oid`` of the last row inserted by the cursor."},
/* DBAPI-2.0 extensions */
{"rownumber", T_LONG, OFFSETOF(row), READONLY,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/lobject_int.c
new/psycopg2-2.8.4/psycopg/lobject_int.c
--- old/psycopg2-2.8.3/psycopg/lobject_int.c 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/lobject_int.c 2019-10-20 02:45:30.000000000
+0200
@@ -176,7 +176,7 @@
self->oid = lo_creat(self->conn->pgconn, INV_READ | INV_WRITE);
}
- Dprintf("lobject_open: large object created with oid = %d",
+ Dprintf("lobject_open: large object created with oid = %u",
self->oid);
if (self->oid == InvalidOid) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/lobject_type.c
new/psycopg2-2.8.4/psycopg/lobject_type.c
--- old/psycopg2-2.8.3/psycopg/lobject_type.c 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/lobject_type.c 2019-10-20 02:45:30.000000000
+0200
@@ -327,7 +327,7 @@
/* object member list */
static struct PyMemberDef lobjectObject_members[] = {
- {"oid", T_UINT, offsetof(lobjectObject, oid), READONLY,
+ {"oid", T_OID, offsetof(lobjectObject, oid), READONLY,
"The backend OID associated to this lobject."},
{"mode", T_STRING, offsetof(lobjectObject, smode), READONLY,
"Open mode."},
@@ -368,7 +368,7 @@
Dprintf("lobject_setup: good lobject object at %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T, self, Py_REFCNT(self));
- Dprintf("lobject_setup: oid = %d, fd = %d", self->oid, self->fd);
+ Dprintf("lobject_setup: oid = %u, fd = %d", self->oid, self->fd);
return 0;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/pqpath.c
new/psycopg2-2.8.4/psycopg/pqpath.c
--- old/psycopg2-2.8.3/psycopg/pqpath.c 2019-06-11 00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/psycopg/pqpath.c 2019-10-20 02:45:30.000000000 +0200
@@ -51,10 +51,10 @@
#include <winsock2.h>
/* gettimeofday() */
#include "win32_support.h"
-#endif
-
-#if defined(__sun) && defined(__SVR4)
+#elif defined(__sun) && defined(__SVR4)
#include "solaris_support.h"
+#else
+#include <sys/time.h>
#endif
extern HIDDEN PyObject *psyco_DescriptionType;
@@ -995,9 +995,9 @@
PyObject *rv = NULL;
Oid ftype = PQftype(pgres, i);
- if (!(type = PyInt_FromLong(ftype))) { goto exit; }
+ if (!(type = PyLong_FromOid(ftype))) { goto exit; }
- Dprintf("_pq_fetch_tuples: looking for cast %d:", ftype);
+ Dprintf("_pq_fetch_tuples: looking for cast %u:", ftype);
if (!(cast = curs_get_cast(curs, type))) { goto exit; }
/* else if we got binary tuples and if we got a field that
@@ -1006,11 +1006,11 @@
*/
if (cast == psyco_default_binary_cast && PQbinaryTuples(pgres)) {
Dprintf("_pq_fetch_tuples: Binary cursor and "
- "binary field: %i using default cast", ftype);
+ "binary field: %u using default cast", ftype);
cast = psyco_default_cast;
}
- Dprintf("_pq_fetch_tuples: using cast at %p for type %d", cast, ftype);
+ Dprintf("_pq_fetch_tuples: using cast at %p for type %u", cast, ftype);
/* success */
Py_INCREF(cast);
@@ -1041,7 +1041,7 @@
/* fill the type and name fields */
{
PyObject *tmp;
- if (!(tmp = PyInt_FromLong(ftype))) {
+ if (!(tmp = PyLong_FromOid(ftype))) {
goto exit;
}
column->type_code = tmp;
@@ -1099,7 +1099,7 @@
/* table_oid, table_column */
if (ftable != InvalidOid) {
PyObject *tmp;
- if (!(tmp = PyInt_FromLong((long)ftable))) { goto exit; }
+ if (!(tmp = PyLong_FromOid(ftable))) { goto exit; }
column->table_oid = tmp;
}
@@ -1576,7 +1576,9 @@
/* We can safely forward flush_lsn to the wal_end from the server
keepalive message
* if we know that the client already processed (confirmed) the last
XLogData message */
- if (repl->flush_lsn >= repl->last_msg_data_start && wal_end >
repl->flush_lsn) {
+ if (repl->explicitly_flushed_lsn >= repl->last_msg_data_start
+ && wal_end > repl->explicitly_flushed_lsn
+ && wal_end > repl->flush_lsn) {
repl->flush_lsn = wal_end;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/psycopgmodule.c
new/psycopg2-2.8.4/psycopg/psycopgmodule.c
--- old/psycopg2-2.8.3/psycopg/psycopgmodule.c 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/psycopgmodule.c 2019-10-20 02:45:30.000000000
+0200
@@ -673,8 +673,8 @@
basic_errors_init(PyObject *module)
{
/* the names of the exceptions here reflect the organization of the
- psycopg2 module and not the fact the the original error objects
- live in _psycopg */
+ psycopg2 module and not the fact the original error objects live in
+ _psycopg */
int i;
PyObject *dict = NULL;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/python.h
new/psycopg2-2.8.4/psycopg/python.h
--- old/psycopg2-2.8.3/psycopg/python.h 2019-06-11 00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/psycopg/python.h 2019-10-20 02:45:30.000000000 +0200
@@ -91,6 +91,11 @@
#define INIT_MODULE(m) init ## m
+/* fix #961, but don't change all types to longs. Sure someone will complain.
*/
+#define PyLong_FromOid(x) (((x) & 0x80000000) ? \
+ PyLong_FromUnsignedLong((unsigned long)(x)) : \
+ PyInt_FromLong((x)))
+
#endif /* PY_2 */
#if PY_3
@@ -133,6 +138,11 @@
#define INIT_MODULE(m) PyInit_ ## m
+#define PyLong_FromOid(x) (PyLong_FromUnsignedLong((unsigned long)(x)))
+
#endif /* PY_3 */
+/* expose Oid attributes in Python C objects */
+#define T_OID T_UINT
+
#endif /* !defined(PSYCOPG_PYTHON_H) */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/replication_cursor.h
new/psycopg2-2.8.4/psycopg/replication_cursor.h
--- old/psycopg2-2.8.3/psycopg/replication_cursor.h 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/psycopg/replication_cursor.h 2019-10-20
02:45:30.000000000 +0200
@@ -52,6 +52,7 @@
XLogRecPtr last_msg_data_start; /* WAL pointer to the last non-keepalive
message from the server */
struct timeval last_feedback; /* timestamp of the last feedback message to
the server */
+ XLogRecPtr explicitly_flushed_lsn; /* the flush LSN explicitly set by the
send_feedback call */
} replicationCursorObject;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/replication_cursor_type.c
new/psycopg2-2.8.4/psycopg/replication_cursor_type.c
--- old/psycopg2-2.8.3/psycopg/replication_cursor_type.c 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/psycopg/replication_cursor_type.c 2019-10-20
02:45:30.000000000 +0200
@@ -211,6 +211,9 @@
if (write_lsn > self->write_lsn)
self->write_lsn = write_lsn;
+ if (flush_lsn > self->explicitly_flushed_lsn)
+ self->explicitly_flushed_lsn = flush_lsn;
+
if (flush_lsn > self->flush_lsn)
self->flush_lsn = flush_lsn;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/sqlstate_errors.h
new/psycopg2-2.8.4/psycopg/sqlstate_errors.h
--- old/psycopg2-2.8.3/psycopg/sqlstate_errors.h 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/psycopg/sqlstate_errors.h 2019-10-20
02:45:30.000000000 +0200
@@ -95,6 +95,21 @@
{"2202E", "ArraySubscriptError"},
{"2202G", "InvalidTablesampleRepeat"},
{"2202H", "InvalidTablesampleArgument"},
+{"22030", "DuplicateJsonObjectKeyValue"},
+{"22032", "InvalidJsonText"},
+{"22033", "InvalidSqlJsonSubscript"},
+{"22034", "MoreThanOneSqlJsonItem"},
+{"22035", "NoSqlJsonItem"},
+{"22036", "NonNumericSqlJsonItem"},
+{"22037", "NonUniqueKeysInAJsonObject"},
+{"22038", "SingletonSqlJsonItemRequired"},
+{"22039", "SqlJsonArrayNotFound"},
+{"2203A", "SqlJsonMemberNotFound"},
+{"2203B", "SqlJsonNumberNotFound"},
+{"2203C", "SqlJsonObjectNotFound"},
+{"2203D", "TooManyJsonArrayElements"},
+{"2203E", "TooManyJsonObjectMembers"},
+{"2203F", "SqlJsonScalarRequired"},
{"22P01", "FloatingPointException"},
{"22P02", "InvalidTextRepresentation"},
{"22P03", "InvalidBinaryRepresentation"},
@@ -254,6 +269,7 @@
{"55006", "ObjectInUse"},
{"55P02", "CantChangeRuntimeParam"},
{"55P03", "LockNotAvailable"},
+{"55P04", "UnsafeNewEnumValueUsage"},
/* Class 57 - Operator Intervention */
{"57000", "OperatorIntervention"},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg/typecast_basic.c
new/psycopg2-2.8.4/psycopg/typecast_basic.c
--- old/psycopg2-2.8.3/psycopg/typecast_basic.c 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/psycopg/typecast_basic.c 2019-10-20 02:45:31.000000000
+0200
@@ -114,16 +114,27 @@
static PyObject *
typecast_BOOLEAN_cast(const char *s, Py_ssize_t len, PyObject *curs)
{
- PyObject *res;
+ PyObject *res = NULL;
if (s == NULL) { Py_RETURN_NONE; }
- if (s[0] == 't')
- res = Py_True;
- else
- res = Py_False;
+ switch (s[0]) {
+ case 't':
+ case 'T':
+ res = Py_True;
+ break;
- Py_INCREF(res);
+ case 'f':
+ case 'F':
+ res = Py_False;
+ break;
+
+ default:
+ PyErr_Format(InterfaceError, "can't parse boolean: '%s'", s);
+ break;
+ }
+
+ Py_XINCREF(res);
return res;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/psycopg2.egg-info/PKG-INFO
new/psycopg2-2.8.4/psycopg2.egg-info/PKG-INFO
--- old/psycopg2-2.8.3/psycopg2.egg-info/PKG-INFO 2019-06-11
00:38:58.000000000 +0200
+++ new/psycopg2-2.8.4/psycopg2.egg-info/PKG-INFO 2019-10-20
02:45:39.000000000 +0200
@@ -1,12 +1,11 @@
Metadata-Version: 1.2
Name: psycopg2
-Version: 2.8.3
+Version: 2.8.4
Summary: psycopg2 - Python-PostgreSQL Database Adapter
Home-page: http://initd.org/psycopg/
Author: Federico Di Gregorio
Author-email: [email protected]
License: LGPL with exceptions or ZPL
-Download-URL:
http://initd.org/psycopg/tarballs/PSYCOPG-2-8/psycopg2-2.8.3.tar.gz
Description-Content-Type: UNKNOWN
Description: Psycopg is the most popular PostgreSQL database adapter for the
Python
programming language. Its main features are the complete
implementation of
@@ -93,6 +92,7 @@
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: C
Classifier: Programming Language :: SQL
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/scripts/appveyor.py
new/psycopg2-2.8.4/scripts/appveyor.py
--- old/psycopg2-2.8.3/scripts/appveyor.py 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/scripts/appveyor.py 2019-10-20 02:45:31.000000000
+0200
@@ -698,7 +698,7 @@
def py_ver(self):
"""The Python version to build as 2 digits string."""
rv = os.environ['PY_VER']
- assert rv in ('27', '34', '35', '36', '37'), rv
+ assert rv in ('27', '34', '35', '36', '37', '38'), rv
return rv
@property
@@ -773,9 +773,10 @@
@property
def vs_ver(self):
+ # https://wiki.python.org/moin/WindowsCompilers
# Py 2.7 = VS Ver. 9.0 (VS 2008)
# Py 3.3, 3.4 = VS Ver. 10.0 (VS 2010)
- # Py 3.5, 3.6, 3.7 = VS Ver. 14.0 (VS 2015)
+ # Py 3.5--3.8 = VS Ver. 14.0 (VS 2015)
vsvers = {
'27': '9.0',
'33': '10.0',
@@ -783,6 +784,7 @@
'35': '14.0',
'36': '14.0',
'37': '14.0',
+ '38': '14.0',
}
return vsvers[self.py_ver]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/scripts/make_errorcodes.py
new/psycopg2-2.8.4/scripts/make_errorcodes.py
--- old/psycopg2-2.8.3/scripts/make_errorcodes.py 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/scripts/make_errorcodes.py 2019-10-20
02:45:31.000000000 +0200
@@ -33,7 +33,7 @@
file_start = read_base_file(filename)
# If you add a version to the list fix the docs (in errorcodes.rst)
classes, errors = fetch_errors(
- ['9.1', '9.2', '9.3', '9.4', '9.5', '9.6', '10', '11'])
+ ['9.1', '9.2', '9.3', '9.4', '9.5', '9.6', '10', '11', '12'])
f = open(filename, "w")
for line in file_start:
@@ -109,12 +109,6 @@
# https://github.com/postgres/postgres/commit/12f87b2c82
errors['22']['22020'] = 'INVALID_LIMIT_VALUE'
- # TODO: this error was added in PG 10 beta 1 but dropped in the
- # final release. It doesn't harm leaving it in the file. Check if it
- # will be added back in PG 12.
- # https://github.com/postgres/postgres/commit/28e0727076
- errors['55']['55P04'] = 'UNSAFE_NEW_ENUM_VALUE_USAGE'
-
for c, cerrs in e1.items():
errors[c].update(cerrs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/scripts/make_errors.py
new/psycopg2-2.8.4/scripts/make_errors.py
--- old/psycopg2-2.8.3/scripts/make_errors.py 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/scripts/make_errors.py 2019-10-20 02:45:31.000000000
+0200
@@ -30,7 +30,7 @@
# If you add a version to the list fix the docs (in errors.rst)
classes, errors = fetch_errors(
- ['9.1', '9.2', '9.3', '9.4', '9.5', '9.6', '10', '11'])
+ ['9.1', '9.2', '9.3', '9.4', '9.5', '9.6', '10', '11', '12'])
f = open(filename, "w")
print("/*\n * Autogenerated by 'scripts/make_errors.py'.\n */\n", file=f)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/scripts/travis_prepare.sh
new/psycopg2-2.8.4/scripts/travis_prepare.sh
--- old/psycopg2-2.8.3/scripts/travis_prepare.sh 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/scripts/travis_prepare.sh 2019-10-20
02:45:31.000000000 +0200
@@ -39,8 +39,20 @@
# install postgres versions not available on the image
if [[ ! -d "${PGDIR}" ]]; then
- wget -O -
http://initd.org/psycopg/upload/postgresql/postgresql-${PACKAGE}-$(lsb_release
-cs).tar.bz2 \
- | sudo tar xjf - -C /usr/lib/postgresql
+ if (( "$VERNUM" >= 904 )); then
+ # A versiou supported by postgres
+ if [[ ! "${apt_updated:-}" ]]; then
+ apt_updated="yeah"
+ sudo apt-get update -y
+ fi
+ sudo apt-get install -y \
+ postgresql-server-dev-${VERSION} postgresql-${VERSION}
+ else
+ # A dinosaur
+ wget -O - \
+
http://initd.org/psycopg/upload/postgresql/postgresql-${PACKAGE}-$(lsb_release
-cs).tar.bz2 \
+ | sudo tar xjf - -C /usr/lib/postgresql
+ fi
fi
sudo -u postgres "$PGBIN/initdb" -D "$DATADIR"
@@ -104,7 +116,9 @@
cd /
# Postgres versions supported by Travis CI
-if [[ -z "$DONT_TEST_PRESENT" ]]; then
+if (( ! "$DONT_TEST_PRESENT" )); then
+ create 12
+ create 11
create 10
create 9.6
create 9.5
@@ -113,7 +127,7 @@
# Unsupported postgres versions that we still support
# Images built by
https://github.com/psycopg/psycopg2-wheels/tree/build-dinosaurs
-if [[ -n "$TEST_PAST" ]]; then
+if (( "$TEST_PAST" )); then
create 7.4
create 8.0
create 8.1
@@ -127,6 +141,6 @@
fi
# Postgres built from master
-if [[ -n "$TEST_FUTURE" ]]; then
- create 11 11-master
+if (( "$TEST_FUTURE" )); then
+ create 13 13-master
fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/scripts/travis_test.sh
new/psycopg2-2.8.4/scripts/travis_test.sh
--- old/psycopg2-2.8.3/scripts/travis_test.sh 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/scripts/travis_test.sh 2019-10-20 02:45:31.000000000
+0200
@@ -16,7 +16,7 @@
run_test () {
VERSION=$1
DBNAME=psycopg2_test
- if [[ -n "$TEST_VERBOSE" ]]; then
+ if (( "$TEST_VERBOSE" )); then
VERBOSE=--verbose
else
VERBOSE=
@@ -45,7 +45,9 @@
}
# Postgres versions supported by Travis CI
-if [[ -z "$DONT_TEST_PRESENT" ]]; then
+if (( ! "$DONT_TEST_PRESENT" )); then
+ run_test 12
+ run_test 11
run_test 10
run_test 9.6
run_test 9.5
@@ -54,7 +56,7 @@
# Unsupported postgres versions that we still support
# Images built by
https://github.com/psycopg/psycopg2-wheels/tree/build-dinosaurs
-if [[ -n "$TEST_PAST" ]]; then
+if (( "$TEST_PAST" )); then
run_test 9.3
run_test 9.2
run_test 9.1
@@ -68,6 +70,6 @@
fi
# Postgres built from master
-if [[ -n "$TEST_FUTURE" ]]; then
- run_test 11
+if (( "$TEST_FUTURE" )); then
+ run_test 13
fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/setup.py new/psycopg2-2.8.4/setup.py
--- old/psycopg2-2.8.3/setup.py 2019-06-11 00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/setup.py 2019-10-20 02:45:31.000000000 +0200
@@ -47,7 +47,7 @@
# Take a look at https://www.python.org/dev/peps/pep-0440/
# for a consistent versioning pattern.
-PSYCOPG_VERSION = '2.8.3'
+PSYCOPG_VERSION = '2.8.4'
# note: if you are changing the list of supported Python version please fix
@@ -65,6 +65,7 @@
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
+Programming Language :: Python :: 3.8
Programming Language :: Python :: Implementation :: CPython
Programming Language :: C
Programming Language :: SQL
@@ -579,12 +580,6 @@
depends=depends,
undef_macros=[]))
-# Compute the direct download url.
-download_url = (
- "http://initd.org/psycopg/tarballs/PSYCOPG-%s/psycopg2-%s.tar.gz"
- % (re.sub(r'^(\d+)\.(\d+).*', r'\1-\2', PSYCOPG_VERSION),
- PSYCOPG_VERSION))
-
try:
f = open("README.rst")
readme = f.read()
@@ -600,7 +595,6 @@
author="Federico Di Gregorio",
author_email="[email protected]",
url="http://initd.org/psycopg/",
- download_url=download_url,
license="LGPL with exceptions or ZPL",
platforms=["any"],
python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/tests/test_async.py
new/psycopg2-2.8.4/tests/test_async.py
--- old/psycopg2-2.8.3/tests/test_async.py 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/tests/test_async.py 2019-10-20 02:45:31.000000000
+0200
@@ -348,6 +348,7 @@
cur.connection.poll()
self.assertEquals(cur.fetchone()[0], 1)
+ @slow
def test_notify(self):
cur = self.conn.cursor()
sync_cur = self.sync_conn.cursor()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/tests/test_types_basic.py
new/psycopg2-2.8.4/tests/test_types_basic.py
--- old/psycopg2-2.8.3/tests/test_types_basic.py 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/tests/test_types_basic.py 2019-10-20
02:45:31.000000000 +0200
@@ -30,7 +30,7 @@
from . import testutils
import unittest
-from .testutils import PY2, long, text_type, ConnectingTestCase
+from .testutils import PY2, long, text_type, ConnectingTestCase, restore_types
import psycopg2
from psycopg2.extensions import AsIs, adapt, register_adapter
@@ -430,6 +430,7 @@
s2 = Sub(s1)
self.assertEqual(adapt(s1).getquoted(), adapt(s2).getquoted())
+ @restore_types
def test_adapt_most_specific(self):
class A(object):
pass
@@ -442,13 +443,10 @@
register_adapter(A, lambda a: AsIs("a"))
register_adapter(B, lambda b: AsIs("b"))
- try:
- self.assertEqual(b'b', adapt(C()).getquoted())
- finally:
- del psycopg2.extensions.adapters[A, psycopg2.extensions.ISQLQuote]
- del psycopg2.extensions.adapters[B, psycopg2.extensions.ISQLQuote]
+ self.assertEqual(b'b', adapt(C()).getquoted())
@testutils.skip_from_python(3)
+ @restore_types
def test_no_mro_no_joy(self):
class A:
pass
@@ -457,12 +455,10 @@
pass
register_adapter(A, lambda a: AsIs("a"))
- try:
- self.assertRaises(psycopg2.ProgrammingError, adapt, B())
- finally:
- del psycopg2.extensions.adapters[A, psycopg2.extensions.ISQLQuote]
+ self.assertRaises(psycopg2.ProgrammingError, adapt, B())
@testutils.skip_before_python(3)
+ @restore_types
def test_adapt_subtype_3(self):
class A:
pass
@@ -471,10 +467,7 @@
pass
register_adapter(A, lambda a: AsIs("a"))
- try:
- self.assertEqual(b"a", adapt(B()).getquoted())
- finally:
- del psycopg2.extensions.adapters[A, psycopg2.extensions.ISQLQuote]
+ self.assertEqual(b"a", adapt(B()).getquoted())
def test_conform_subclass_precedence(self):
class foo(tuple):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/tests/test_types_extras.py
new/psycopg2-2.8.4/tests/test_types_extras.py
--- old/psycopg2-2.8.3/tests/test_types_extras.py 2019-06-11
00:38:50.000000000 +0200
+++ new/psycopg2-2.8.4/tests/test_types_extras.py 2019-10-20
02:45:31.000000000 +0200
@@ -25,7 +25,8 @@
import unittest
from .testutils import (PY2, text_type, skip_if_no_uuid, skip_before_postgres,
- ConnectingTestCase, py3_raises_typeerror, slow, skip_from_python)
+ ConnectingTestCase, py3_raises_typeerror, slow, skip_from_python,
+ restore_types)
import psycopg2
import psycopg2.extras
@@ -75,6 +76,7 @@
s = self.execute("SELECT '{}'::uuid[] AS foo")
self.failUnless(type(s) == list and len(s) == 0)
+ @restore_types
def testINET(self):
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
@@ -87,6 +89,7 @@
s = self.execute("SELECT NULL::inet AS foo")
self.failUnless(s is None)
+ @restore_types
def testINETARRAY(self):
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
@@ -258,26 +261,18 @@
self.assert_(isinstance(t[2].values()[0], unicode))
@skip_if_no_hstore
+ @restore_types
def test_register_globally(self):
- oids = HstoreAdapter.get_oids(self.conn)
+ HstoreAdapter.get_oids(self.conn)
+ register_hstore(self.conn, globally=True)
+ conn2 = self.connect()
try:
- register_hstore(self.conn, globally=True)
- conn2 = self.connect()
- try:
- cur2 = self.conn.cursor()
- cur2.execute("select 'a => b'::hstore")
- r = cur2.fetchone()
- self.assert_(isinstance(r[0], dict))
- finally:
- conn2.close()
+ cur2 = self.conn.cursor()
+ cur2.execute("select 'a => b'::hstore")
+ r = cur2.fetchone()
+ self.assert_(isinstance(r[0], dict))
finally:
- psycopg2.extensions.string_types.pop(oids[0][0])
-
- # verify the caster is not around anymore
- cur = self.conn.cursor()
- cur.execute("select 'a => b'::hstore")
- r = cur.fetchone()
- self.assert_(isinstance(r[0], str))
+ conn2.close()
@skip_if_no_hstore
def test_roundtrip(self):
@@ -332,6 +327,7 @@
ok(dict(zip(ab, ab)))
@skip_if_no_hstore
+ @restore_types
def test_oid(self):
cur = self.conn.cursor()
cur.execute("select 'hstore'::regtype::oid")
@@ -340,15 +336,11 @@
# Note: None as conn_or_cursor is just for testing: not public
# interface and it may break in future.
register_hstore(None, globally=True, oid=oid)
- try:
- cur.execute("select null::hstore, ''::hstore, 'a => b'::hstore")
- t = cur.fetchone()
- self.assert_(t[0] is None)
- self.assertEqual(t[1], {})
- self.assertEqual(t[2], {'a': 'b'})
-
- finally:
- psycopg2.extensions.string_types.pop(oid)
+ cur.execute("select null::hstore, ''::hstore, 'a => b'::hstore")
+ t = cur.fetchone()
+ self.assert_(t[0] is None)
+ self.assertEqual(t[1], {})
+ self.assertEqual(t[2], {'a': 'b'})
@skip_if_no_hstore
@skip_before_postgres(8, 3)
@@ -385,25 +377,21 @@
self.assertEqual(a, [{'a': '1'}, {'b': '2'}])
@skip_if_no_hstore
+ @restore_types
def test_array_cast_oid(self):
cur = self.conn.cursor()
cur.execute("select 'hstore'::regtype::oid, 'hstore[]'::regtype::oid")
oid, aoid = cur.fetchone()
register_hstore(None, globally=True, oid=oid, array_oid=aoid)
- try:
- cur.execute("""
- select null::hstore, ''::hstore,
- 'a => b'::hstore, '{a=>b}'::hstore[]""")
- t = cur.fetchone()
- self.assert_(t[0] is None)
- self.assertEqual(t[1], {})
- self.assertEqual(t[2], {'a': 'b'})
- self.assertEqual(t[3], [{'a': 'b'}])
-
- finally:
- psycopg2.extensions.string_types.pop(oid)
- psycopg2.extensions.string_types.pop(aoid)
+ cur.execute("""
+ select null::hstore, ''::hstore,
+ 'a => b'::hstore, '{a=>b}'::hstore[]""")
+ t = cur.fetchone()
+ self.assert_(t[0] is None)
+ self.assertEqual(t[1], {})
+ self.assertEqual(t[2], {'a': 'b'})
+ self.assertEqual(t[3], [{'a': 'b'}])
@skip_if_no_hstore
def test_non_dbapi_connection(self):
@@ -598,27 +586,20 @@
conn2.close()
@skip_if_no_composite
+ @restore_types
def test_register_globally(self):
self._create_type("type_ii", [("a", "integer"), ("b", "integer")])
conn1 = self.connect()
conn2 = self.connect()
try:
- t = psycopg2.extras.register_composite("type_ii", conn1,
globally=True)
- try:
- curs1 = conn1.cursor()
- curs2 = conn2.cursor()
- curs1.execute("select (1,2)::type_ii")
- self.assertEqual(curs1.fetchone()[0], (1, 2))
- curs2.execute("select (1,2)::type_ii")
- self.assertEqual(curs2.fetchone()[0], (1, 2))
- finally:
- # drop the registered typecasters to help the refcounting
- # script to return precise values.
- del psycopg2.extensions.string_types[t.typecaster.values[0]]
- if t.array_typecaster:
- del psycopg2.extensions.string_types[
- t.array_typecaster.values[0]]
+ psycopg2.extras.register_composite("type_ii", conn1, globally=True)
+ curs1 = conn1.cursor()
+ curs2 = conn2.cursor()
+ curs1.execute("select (1,2)::type_ii")
+ self.assertEqual(curs1.fetchone()[0], (1, 2))
+ curs2.execute("select (1,2)::type_ii")
+ self.assertEqual(curs2.fetchone()[0], (1, 2))
finally:
conn1.close()
@@ -844,16 +825,14 @@
obj = Decimal('123.45')
self.assertQuotedEqual(curs.mogrify("%s", (MyJson(obj),)), b"'123.45'")
+ @restore_types
def test_register_on_dict(self):
psycopg2.extensions.register_adapter(dict, Json)
- try:
- curs = self.conn.cursor()
- obj = {'a': 123}
- self.assertQuotedEqual(
- curs.mogrify("%s", (obj,)), b"""'{"a": 123}'""")
- finally:
- del psycopg2.extensions.adapters[dict, ext.ISQLQuote]
+ curs = self.conn.cursor()
+ obj = {'a': 123}
+ self.assertQuotedEqual(
+ curs.mogrify("%s", (obj,)), b"""'{"a": 123}'""")
def test_type_not_available(self):
curs = self.conn.cursor()
@@ -889,21 +868,12 @@
self.assertEqual(curs.fetchone()[0], {'a': 100.0, 'b': None})
@skip_if_no_json_type
+ @restore_types
def test_register_globally(self):
- old = psycopg2.extensions.string_types.get(114)
- olda = psycopg2.extensions.string_types.get(199)
- try:
- new, newa = psycopg2.extras.register_json(self.conn, globally=True)
- curs = self.conn.cursor()
- curs.execute("""select '{"a": 100.0, "b": null}'::json""")
- self.assertEqual(curs.fetchone()[0], {'a': 100.0, 'b': None})
- finally:
- psycopg2.extensions.string_types.pop(new.values[0])
- psycopg2.extensions.string_types.pop(newa.values[0])
- if old:
- psycopg2.extensions.register_type(old)
- if olda:
- psycopg2.extensions.register_type(olda)
+ new, newa = psycopg2.extras.register_json(self.conn, globally=True)
+ curs = self.conn.cursor()
+ curs.execute("""select '{"a": 100.0, "b": null}'::json""")
+ self.assertEqual(curs.fetchone()[0], {'a': 100.0, 'b': None})
@skip_if_no_json_type
def test_loads(self):
@@ -919,29 +889,20 @@
self.assertEqual(data['a'], Decimal('100.0'))
@skip_if_no_json_type
+ @restore_types
def test_no_conn_curs(self):
oid, array_oid = _get_json_oids(self.conn)
- old = psycopg2.extensions.string_types.get(114)
- olda = psycopg2.extensions.string_types.get(199)
-
def loads(s):
return psycopg2.extras.json.loads(s, parse_float=Decimal)
- try:
- new, newa = psycopg2.extras.register_json(
- loads=loads, oid=oid, array_oid=array_oid)
- curs = self.conn.cursor()
- curs.execute("""select '{"a": 100.0, "b": null}'::json""")
- data = curs.fetchone()[0]
- self.assert_(isinstance(data['a'], Decimal))
- self.assertEqual(data['a'], Decimal('100.0'))
- finally:
- psycopg2.extensions.string_types.pop(new.values[0])
- psycopg2.extensions.string_types.pop(newa.values[0])
- if old:
- psycopg2.extensions.register_type(old)
- if olda:
- psycopg2.extensions.register_type(olda)
+
+ new, newa = psycopg2.extras.register_json(
+ loads=loads, oid=oid, array_oid=array_oid)
+ curs = self.conn.cursor()
+ curs.execute("""select '{"a": 100.0, "b": null}'::json""")
+ data = curs.fetchone()[0]
+ self.assert_(isinstance(data['a'], Decimal))
+ self.assertEqual(data['a'], Decimal('100.0'))
@skip_before_postgres(9, 2)
def test_register_default(self):
@@ -1043,22 +1004,13 @@
curs.execute("""select '{"a": 100.0, "b": null}'::jsonb""")
self.assertEqual(curs.fetchone()[0], {'a': 100.0, 'b': None, 'test':
1})
+ @restore_types
def test_register_globally(self):
- old = psycopg2.extensions.string_types.get(3802)
- olda = psycopg2.extensions.string_types.get(3807)
- try:
- new, newa = psycopg2.extras.register_json(self.conn,
- loads=self.myloads, globally=True, name='jsonb')
- curs = self.conn.cursor()
- curs.execute("""select '{"a": 100.0, "b": null}'::jsonb""")
- self.assertEqual(curs.fetchone()[0], {'a': 100.0, 'b': None,
'test': 1})
- finally:
- psycopg2.extensions.string_types.pop(new.values[0])
- psycopg2.extensions.string_types.pop(newa.values[0])
- if old:
- psycopg2.extensions.register_type(old)
- if olda:
- psycopg2.extensions.register_type(olda)
+ new, newa = psycopg2.extras.register_json(self.conn,
+ loads=self.myloads, globally=True, name='jsonb')
+ curs = self.conn.cursor()
+ curs.execute("""select '{"a": 100.0, "b": null}'::jsonb""")
+ self.assertEqual(curs.fetchone()[0], {'a': 100.0, 'b': None, 'test':
1})
def test_loads(self):
json = psycopg2.extras.json
@@ -1558,6 +1510,7 @@
self.assert_(not r1.lower_inc)
self.assert_(r1.upper_inc)
+ @restore_types
def test_register_range_adapter(self):
cur = self.conn.cursor()
cur.execute("create type textrange as range (subtype=text)")
@@ -1584,9 +1537,6 @@
self.assert_(not r1.lower_inc)
self.assert_(r1.upper_inc)
- # clear the adapters to allow precise count by scripts/refcounter.py
- del ext.adapters[rc.range, ext.ISQLQuote]
-
def test_range_escaping(self):
cur = self.conn.cursor()
cur.execute("create type textrange as range (subtype=text)")
@@ -1645,6 +1595,7 @@
self.assertRaises(psycopg2.ProgrammingError,
register_range, 'nosuchrange', 'FailRange', cur)
+ @restore_types
def test_schema_range(self):
cur = self.conn.cursor()
cur.execute("create schema rs")
@@ -1654,10 +1605,10 @@
cur.execute("create type rs.r3 as range (subtype=text)")
cur.execute("savepoint x")
- ra1 = register_range('r1', 'r1', cur)
+ register_range('r1', 'r1', cur)
ra2 = register_range('r2', 'r2', cur)
rars2 = register_range('rs.r2', 'r2', cur)
- rars3 = register_range('rs.r3', 'r3', cur)
+ register_range('rs.r3', 'r3', cur)
self.assertNotEqual(
ra2.typecaster.values[0],
@@ -1671,10 +1622,6 @@
register_range, 'rs.r1', 'FailRange', cur)
cur.execute("rollback to savepoint x;")
- # clear the adapters to allow precise count by scripts/refcounter.py
- for r in [ra1, ra2, rars2, rars3]:
- del ext.adapters[r.range, ext.ISQLQuote]
-
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg2-2.8.3/tests/testutils.py
new/psycopg2-2.8.4/tests/testutils.py
--- old/psycopg2-2.8.3/tests/testutils.py 2019-06-11 00:38:50.000000000
+0200
+++ new/psycopg2-2.8.4/tests/testutils.py 2019-10-20 02:45:31.000000000
+0200
@@ -425,7 +425,24 @@
"""
@wraps(f)
def slow_(self):
- if os.environ.get('PSYCOPG2_TEST_FAST'):
+ if os.environ.get('PSYCOPG2_TEST_FAST', '0') != '0':
return self.skipTest("slow test")
return f(self)
return slow_
+
+
+def restore_types(f):
+ """Decorator to restore the adaptation system after running a test"""
+ @wraps(f)
+ def restore_types_(self):
+ types = psycopg2.extensions.string_types.copy()
+ adapters = psycopg2.extensions.adapters.copy()
+ try:
+ return f(self)
+ finally:
+ psycopg2.extensions.string_types.clear()
+ psycopg2.extensions.string_types.update(types)
+ psycopg2.extensions.adapters.clear()
+ psycopg2.extensions.adapters.update(adapters)
+
+ return restore_types_