mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-11-04 01:37:31 +03:00 
			
		
		
		
	
						commit
						1911b250e3
					
				
							
								
								
									
										2
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								NEWS
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -35,6 +35,8 @@ Bug fixes:
 | 
			
		|||
 | 
			
		||||
- Fixed error caused by missing decoding `~psycopg2.extras.LoggingConnection`
 | 
			
		||||
  (:ticket:`#483`).
 | 
			
		||||
- Added ``async_`` as an alias for ``async`` to support Python 3.7 where
 | 
			
		||||
  ``async`` will become a keyword (:ticket:`#495`).
 | 
			
		||||
 | 
			
		||||
Other changes:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -706,9 +706,13 @@ The ``connection`` class
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
    .. attribute:: async
 | 
			
		||||
                   async_
 | 
			
		||||
 | 
			
		||||
        Read only attribute: 1 if the connection is asynchronous, 0 otherwise.
 | 
			
		||||
 | 
			
		||||
        .. versionchanged:: 2.7 added the `!async_` alias for Python versions
 | 
			
		||||
            where `!async` is a keyword.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    .. method:: poll()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,8 @@ introspection etc.
 | 
			
		|||
 | 
			
		||||
    For a complete description of the class, see `connection`.
 | 
			
		||||
 | 
			
		||||
    .. versionchanged:: 2.7
 | 
			
		||||
        *async_* can be used as alias for *async*.
 | 
			
		||||
 | 
			
		||||
.. class:: cursor(conn, name=None)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,7 +64,8 @@ The module interface respects the standard defined in the |DBAPI|_.
 | 
			
		|||
    cursors you can use this parameter instead of subclassing a connection.
 | 
			
		||||
 | 
			
		||||
    Using *async*\=\ `!True` an asynchronous connection will be created: see
 | 
			
		||||
    :ref:`async-support` to know about advantages and limitations.
 | 
			
		||||
    :ref:`async-support` to know about advantages and limitations. *async_* is
 | 
			
		||||
    a valid alias for the Python version where ``async`` is a keyword.
 | 
			
		||||
 | 
			
		||||
    .. versionchanged:: 2.4.3
 | 
			
		||||
        any keyword argument is passed to the connection. Previously only the
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +77,9 @@ The module interface respects the standard defined in the |DBAPI|_.
 | 
			
		|||
    .. versionchanged:: 2.7
 | 
			
		||||
        both *dsn* and keyword arguments can be specified.
 | 
			
		||||
 | 
			
		||||
    .. versionchanged:: 2.7
 | 
			
		||||
        added *async_* alias.
 | 
			
		||||
 | 
			
		||||
    .. seealso::
 | 
			
		||||
 | 
			
		||||
        - `~psycopg2.extensions.parse_dsn`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,8 +82,7 @@ else:
 | 
			
		|||
    del Decimal, Adapter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def connect(dsn=None, connection_factory=None, cursor_factory=None,
 | 
			
		||||
            async=False, **kwargs):
 | 
			
		||||
def connect(dsn=None, connection_factory=None, cursor_factory=None, **kwargs):
 | 
			
		||||
    """
 | 
			
		||||
    Create a new database connection.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -111,17 +110,24 @@ def connect(dsn=None, connection_factory=None, cursor_factory=None,
 | 
			
		|||
    Using the *cursor_factory* parameter, a new default cursor factory will be
 | 
			
		||||
    used by cursor().
 | 
			
		||||
 | 
			
		||||
    Using *async*=True an asynchronous connection will be created.
 | 
			
		||||
    Using *async*=True an asynchronous connection will be created. *async_* is
 | 
			
		||||
    a valid alias (for Python versions where ``async`` is a keyword).
 | 
			
		||||
 | 
			
		||||
    Any other keyword parameter will be passed to the underlying client
 | 
			
		||||
    library: the list of supported parameters depends on the library version.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    kwasync = {}
 | 
			
		||||
    if 'async' in kwargs:
 | 
			
		||||
        kwasync['async'] = kwargs.pop('async')
 | 
			
		||||
    if 'async_' in kwargs:
 | 
			
		||||
        kwasync['async_'] = kwargs.pop('async_')
 | 
			
		||||
 | 
			
		||||
    if dsn is None and not kwargs:
 | 
			
		||||
        raise TypeError('missing dsn and no parameters')
 | 
			
		||||
 | 
			
		||||
    dsn = _ext.make_dsn(dsn, **kwargs)
 | 
			
		||||
    conn = _connect(dsn, connection_factory=connection_factory, async=async)
 | 
			
		||||
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
 | 
			
		||||
    if cursor_factory is not None:
 | 
			
		||||
        conn.cursor_factory = cursor_factory
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1040,6 +1040,8 @@ static struct PyMemberDef connectionObject_members[] = {
 | 
			
		|||
        "The current connection string."},
 | 
			
		||||
    {"async", T_LONG, offsetof(connectionObject, async), READONLY,
 | 
			
		||||
        "True if the connection is asynchronous."},
 | 
			
		||||
    {"async_", T_LONG, offsetof(connectionObject, async), READONLY,
 | 
			
		||||
        "True if the connection is asynchronous."},
 | 
			
		||||
    {"status", T_INT,
 | 
			
		||||
        offsetof(connectionObject, status), READONLY,
 | 
			
		||||
        "The current transaction status."},
 | 
			
		||||
| 
						 | 
				
			
			@ -1186,12 +1188,14 @@ static int
 | 
			
		|||
connection_init(PyObject *obj, PyObject *args, PyObject *kwds)
 | 
			
		||||
{
 | 
			
		||||
    const char *dsn;
 | 
			
		||||
    long int async = 0;
 | 
			
		||||
    static char *kwlist[] = {"dsn", "async", NULL};
 | 
			
		||||
    long int async = 0, async_ = 0;
 | 
			
		||||
    static char *kwlist[] = {"dsn", "async", "async_", NULL};
 | 
			
		||||
 | 
			
		||||
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|l", kwlist, &dsn, &async))
 | 
			
		||||
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ll", kwlist,
 | 
			
		||||
            &dsn, &async, &async_))
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    if (async_) { async = async_; }
 | 
			
		||||
    return connection_setup((connectionObject *)obj, dsn, async);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,15 +82,17 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
 | 
			
		|||
    PyObject *conn = NULL;
 | 
			
		||||
    PyObject *factory = NULL;
 | 
			
		||||
    const char *dsn = NULL;
 | 
			
		||||
    int async = 0;
 | 
			
		||||
    int async = 0, async_ = 0;
 | 
			
		||||
 | 
			
		||||
    static char *kwlist[] = {"dsn", "connection_factory", "async", NULL};
 | 
			
		||||
    static char *kwlist[] = {"dsn", "connection_factory", "async", "async_", NULL};
 | 
			
		||||
 | 
			
		||||
    if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|Oi", kwlist,
 | 
			
		||||
                                     &dsn, &factory, &async)) {
 | 
			
		||||
    if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|Oii", kwlist,
 | 
			
		||||
            &dsn, &factory, &async, &async_)) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (async_) { async = async_; }
 | 
			
		||||
 | 
			
		||||
    Dprintf("psyco_connect: dsn = '%s', async = %d", dsn, async);
 | 
			
		||||
 | 
			
		||||
    /* allocate connection, fill with errors and return it */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								setup.py
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -50,7 +50,11 @@ else:
 | 
			
		|||
        # workaround subclass for ticket #153
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    sys.path.insert(0, 'scripts')
 | 
			
		||||
    # Configure distutils to run our custom 2to3 fixers as well
 | 
			
		||||
    from lib2to3.refactor import get_fixers_from_package
 | 
			
		||||
    build_py.fixer_names = [f for f in get_fixers_from_package('lib2to3.fixes')
 | 
			
		||||
        # creates a pending deprecation warning on py 3.4
 | 
			
		||||
        if not f.endswith('.fix_reload')]
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    import configparser
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,11 @@
 | 
			
		|||
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 | 
			
		||||
# License for more details.
 | 
			
		||||
 | 
			
		||||
# Convert warnings into errors here. We can't do it with -W because on
 | 
			
		||||
# Travis importing site raises a warning.
 | 
			
		||||
import warnings
 | 
			
		||||
warnings.simplefilter('error')  # noqa
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
from testconfig import dsn
 | 
			
		||||
from testutils import unittest
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +55,9 @@ import test_types_basic
 | 
			
		|||
import test_types_extras
 | 
			
		||||
import test_with
 | 
			
		||||
 | 
			
		||||
if sys.version_info[:2] < (3, 6):
 | 
			
		||||
    import test_async_keyword
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_suite():
 | 
			
		||||
    # If connection to test db fails, bail out early.
 | 
			
		||||
| 
						 | 
				
			
			@ -65,6 +73,8 @@ def test_suite():
 | 
			
		|||
 | 
			
		||||
    suite = unittest.TestSuite()
 | 
			
		||||
    suite.addTest(test_async.test_suite())
 | 
			
		||||
    if sys.version_info[:2] < (3, 6):
 | 
			
		||||
        suite.addTest(test_async_keyword.test_suite())
 | 
			
		||||
    suite.addTest(test_bugX000.test_suite())
 | 
			
		||||
    suite.addTest(test_bug_gc.test_suite())
 | 
			
		||||
    suite.addTest(test_cancel.test_suite())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ class AsyncTests(ConnectingTestCase):
 | 
			
		|||
        ConnectingTestCase.setUp(self)
 | 
			
		||||
 | 
			
		||||
        self.sync_conn = self.conn
 | 
			
		||||
        self.conn = self.connect(async=True)
 | 
			
		||||
        self.conn = self.connect(async_=True)
 | 
			
		||||
 | 
			
		||||
        self.wait(self.conn)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,8 +71,8 @@ class AsyncTests(ConnectingTestCase):
 | 
			
		|||
        sync_cur = self.sync_conn.cursor()
 | 
			
		||||
        del cur, sync_cur
 | 
			
		||||
 | 
			
		||||
        self.assert_(self.conn.async)
 | 
			
		||||
        self.assert_(not self.sync_conn.async)
 | 
			
		||||
        self.assert_(self.conn.async_)
 | 
			
		||||
        self.assert_(not self.sync_conn.async_)
 | 
			
		||||
 | 
			
		||||
        # the async connection should be in isolevel 0
 | 
			
		||||
        self.assertEquals(self.conn.isolation_level, 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -312,12 +312,12 @@ class AsyncTests(ConnectingTestCase):
 | 
			
		|||
 | 
			
		||||
    def test_async_subclass(self):
 | 
			
		||||
        class MyConn(psycopg2.extensions.connection):
 | 
			
		||||
            def __init__(self, dsn, async=0):
 | 
			
		||||
                psycopg2.extensions.connection.__init__(self, dsn, async=async)
 | 
			
		||||
            def __init__(self, dsn, async_=0):
 | 
			
		||||
                psycopg2.extensions.connection.__init__(self, dsn, async_=async_)
 | 
			
		||||
 | 
			
		||||
        conn = self.connect(connection_factory=MyConn, async=True)
 | 
			
		||||
        conn = self.connect(connection_factory=MyConn, async_=True)
 | 
			
		||||
        self.assert_(isinstance(conn, MyConn))
 | 
			
		||||
        self.assert_(conn.async)
 | 
			
		||||
        self.assert_(conn.async_)
 | 
			
		||||
        conn.close()
 | 
			
		||||
 | 
			
		||||
    @slow
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +441,7 @@ class AsyncTests(ConnectingTestCase):
 | 
			
		|||
 | 
			
		||||
    def test_async_connection_error_message(self):
 | 
			
		||||
        try:
 | 
			
		||||
            cnn = psycopg2.connect('dbname=thisdatabasedoesntexist', async=True)
 | 
			
		||||
            cnn = psycopg2.connect('dbname=thisdatabasedoesntexist', async_=True)
 | 
			
		||||
            self.wait(cnn)
 | 
			
		||||
        except psycopg2.Error, e:
 | 
			
		||||
            self.assertNotEqual(str(e), "asynchronous connection failed",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										217
									
								
								tests/test_async_keyword.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										217
									
								
								tests/test_async_keyword.py
									
									
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,217 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
# test_async_keyword.py - test for objects using 'async' as attribute/param
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2017 Daniele Varrazzo  <daniele.varrazzo@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# psycopg2 is free software: you can redistribute it and/or modify it
 | 
			
		||||
# under the terms of the GNU Lesser General Public License as published
 | 
			
		||||
# by the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# In addition, as a special exception, the copyright holders give
 | 
			
		||||
# permission to link this program with the OpenSSL library (or with
 | 
			
		||||
# modified versions of OpenSSL that use the same license as OpenSSL),
 | 
			
		||||
# and distribute linked combinations including the two.
 | 
			
		||||
#
 | 
			
		||||
# You must obey the GNU Lesser General Public License in all respects for
 | 
			
		||||
# all of the code used other than OpenSSL.
 | 
			
		||||
#
 | 
			
		||||
# psycopg2 is distributed in the hope that it will be useful, but WITHOUT
 | 
			
		||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 | 
			
		||||
# License for more details.
 | 
			
		||||
 | 
			
		||||
import psycopg2
 | 
			
		||||
from psycopg2 import extras
 | 
			
		||||
 | 
			
		||||
from testconfig import dsn
 | 
			
		||||
from testutils import (ConnectingTestCase, unittest, skip_before_postgres,
 | 
			
		||||
    assertDsnEqual)
 | 
			
		||||
from test_replication import ReplicationTestCase, skip_repl_if_green
 | 
			
		||||
from psycopg2.extras import LogicalReplicationConnection, StopReplication
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AsyncTests(ConnectingTestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        ConnectingTestCase.setUp(self)
 | 
			
		||||
 | 
			
		||||
        self.sync_conn = self.conn
 | 
			
		||||
        self.conn = self.connect(async=True)
 | 
			
		||||
 | 
			
		||||
        self.wait(self.conn)
 | 
			
		||||
 | 
			
		||||
        curs = self.conn.cursor()
 | 
			
		||||
        curs.execute('''
 | 
			
		||||
            CREATE TEMPORARY TABLE table1 (
 | 
			
		||||
              id int PRIMARY KEY
 | 
			
		||||
            )''')
 | 
			
		||||
        self.wait(curs)
 | 
			
		||||
 | 
			
		||||
    def test_connection_setup(self):
 | 
			
		||||
        cur = self.conn.cursor()
 | 
			
		||||
        sync_cur = self.sync_conn.cursor()
 | 
			
		||||
        del cur, sync_cur
 | 
			
		||||
 | 
			
		||||
        self.assert_(self.conn.async)
 | 
			
		||||
        self.assert_(not self.sync_conn.async)
 | 
			
		||||
 | 
			
		||||
        # the async connection should be in isolevel 0
 | 
			
		||||
        self.assertEquals(self.conn.isolation_level, 0)
 | 
			
		||||
 | 
			
		||||
        # check other properties to be found on the connection
 | 
			
		||||
        self.assert_(self.conn.server_version)
 | 
			
		||||
        self.assert_(self.conn.protocol_version in (2, 3))
 | 
			
		||||
        self.assert_(self.conn.encoding in psycopg2.extensions.encodings)
 | 
			
		||||
 | 
			
		||||
    def test_async_subclass(self):
 | 
			
		||||
        class MyConn(psycopg2.extensions.connection):
 | 
			
		||||
            def __init__(self, dsn, async=0):
 | 
			
		||||
                psycopg2.extensions.connection.__init__(self, dsn, async=async)
 | 
			
		||||
 | 
			
		||||
        conn = self.connect(connection_factory=MyConn, async=True)
 | 
			
		||||
        self.assert_(isinstance(conn, MyConn))
 | 
			
		||||
        self.assert_(conn.async)
 | 
			
		||||
        conn.close()
 | 
			
		||||
 | 
			
		||||
    def test_async_connection_error_message(self):
 | 
			
		||||
        try:
 | 
			
		||||
            cnn = psycopg2.connect('dbname=thisdatabasedoesntexist', async=True)
 | 
			
		||||
            self.wait(cnn)
 | 
			
		||||
        except psycopg2.Error, e:
 | 
			
		||||
            self.assertNotEqual(str(e), "asynchronous connection failed",
 | 
			
		||||
                "connection error reason lost")
 | 
			
		||||
        else:
 | 
			
		||||
            self.fail("no exception raised")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CancelTests(ConnectingTestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        ConnectingTestCase.setUp(self)
 | 
			
		||||
 | 
			
		||||
        cur = self.conn.cursor()
 | 
			
		||||
        cur.execute('''
 | 
			
		||||
            CREATE TEMPORARY TABLE table1 (
 | 
			
		||||
              id int PRIMARY KEY
 | 
			
		||||
            )''')
 | 
			
		||||
        self.conn.commit()
 | 
			
		||||
 | 
			
		||||
    @skip_before_postgres(8, 2)
 | 
			
		||||
    def test_async_cancel(self):
 | 
			
		||||
        async_conn = psycopg2.connect(dsn, async=True)
 | 
			
		||||
        self.assertRaises(psycopg2.OperationalError, async_conn.cancel)
 | 
			
		||||
        extras.wait_select(async_conn)
 | 
			
		||||
        cur = async_conn.cursor()
 | 
			
		||||
        cur.execute("select pg_sleep(10000)")
 | 
			
		||||
        self.assertTrue(async_conn.isexecuting())
 | 
			
		||||
        async_conn.cancel()
 | 
			
		||||
        self.assertRaises(psycopg2.extensions.QueryCanceledError,
 | 
			
		||||
                          extras.wait_select, async_conn)
 | 
			
		||||
        cur.execute("select 1")
 | 
			
		||||
        extras.wait_select(async_conn)
 | 
			
		||||
        self.assertEqual(cur.fetchall(), [(1, )])
 | 
			
		||||
 | 
			
		||||
    def test_async_connection_cancel(self):
 | 
			
		||||
        async_conn = psycopg2.connect(dsn, async=True)
 | 
			
		||||
        async_conn.close()
 | 
			
		||||
        self.assertTrue(async_conn.closed)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ConnectTestCase(unittest.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.args = None
 | 
			
		||||
 | 
			
		||||
        def connect_stub(dsn, connection_factory=None, async=False):
 | 
			
		||||
            self.args = (dsn, connection_factory, async)
 | 
			
		||||
 | 
			
		||||
        self._connect_orig = psycopg2._connect
 | 
			
		||||
        psycopg2._connect = connect_stub
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        psycopg2._connect = self._connect_orig
 | 
			
		||||
 | 
			
		||||
    def test_there_has_to_be_something(self):
 | 
			
		||||
        self.assertRaises(TypeError, psycopg2.connect)
 | 
			
		||||
        self.assertRaises(TypeError, psycopg2.connect,
 | 
			
		||||
            connection_factory=lambda dsn, async=False: None)
 | 
			
		||||
        self.assertRaises(TypeError, psycopg2.connect,
 | 
			
		||||
            async=True)
 | 
			
		||||
 | 
			
		||||
    def test_factory(self):
 | 
			
		||||
        def f(dsn, async=False):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        psycopg2.connect(database='foo', host='baz', connection_factory=f)
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], f)
 | 
			
		||||
        self.assertEqual(self.args[2], False)
 | 
			
		||||
 | 
			
		||||
        psycopg2.connect("dbname=foo host=baz", connection_factory=f)
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], f)
 | 
			
		||||
        self.assertEqual(self.args[2], False)
 | 
			
		||||
 | 
			
		||||
    def test_async(self):
 | 
			
		||||
        psycopg2.connect(database='foo', host='baz', async=1)
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], None)
 | 
			
		||||
        self.assert_(self.args[2])
 | 
			
		||||
 | 
			
		||||
        psycopg2.connect("dbname=foo host=baz", async=True)
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], None)
 | 
			
		||||
        self.assert_(self.args[2])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AsyncReplicationTest(ReplicationTestCase):
 | 
			
		||||
    @skip_before_postgres(9, 4)     # slots require 9.4
 | 
			
		||||
    @skip_repl_if_green
 | 
			
		||||
    def test_async_replication(self):
 | 
			
		||||
        conn = self.repl_connect(
 | 
			
		||||
            connection_factory=LogicalReplicationConnection, async=1)
 | 
			
		||||
        if conn is None:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        cur = conn.cursor()
 | 
			
		||||
 | 
			
		||||
        self.create_replication_slot(cur, output_plugin='test_decoding')
 | 
			
		||||
        self.wait(cur)
 | 
			
		||||
 | 
			
		||||
        cur.start_replication(self.slot)
 | 
			
		||||
        self.wait(cur)
 | 
			
		||||
 | 
			
		||||
        self.make_replication_events()
 | 
			
		||||
 | 
			
		||||
        self.msg_count = 0
 | 
			
		||||
 | 
			
		||||
        def consume(msg):
 | 
			
		||||
            # just check the methods
 | 
			
		||||
            "%s: %s" % (cur.io_timestamp, repr(msg))
 | 
			
		||||
 | 
			
		||||
            self.msg_count += 1
 | 
			
		||||
            if self.msg_count > 3:
 | 
			
		||||
                cur.send_feedback(reply=True)
 | 
			
		||||
                raise StopReplication()
 | 
			
		||||
 | 
			
		||||
            cur.send_feedback(flush_lsn=msg.data_start)
 | 
			
		||||
 | 
			
		||||
        # cannot be used in asynchronous mode
 | 
			
		||||
        self.assertRaises(psycopg2.ProgrammingError, cur.consume_stream, consume)
 | 
			
		||||
 | 
			
		||||
        def process_stream():
 | 
			
		||||
            from select import select
 | 
			
		||||
            while True:
 | 
			
		||||
                msg = cur.read_message()
 | 
			
		||||
                if msg:
 | 
			
		||||
                    consume(msg)
 | 
			
		||||
                else:
 | 
			
		||||
                    select([cur], [], [])
 | 
			
		||||
        self.assertRaises(StopReplication, process_stream)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_suite():
 | 
			
		||||
    return unittest.TestLoader().loadTestsFromName(__name__)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    unittest.main()
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ class CancelTests(ConnectingTestCase):
 | 
			
		|||
 | 
			
		||||
    @skip_before_postgres(8, 2)
 | 
			
		||||
    def test_async_cancel(self):
 | 
			
		||||
        async_conn = psycopg2.connect(dsn, async=True)
 | 
			
		||||
        async_conn = psycopg2.connect(dsn, async_=True)
 | 
			
		||||
        self.assertRaises(psycopg2.OperationalError, async_conn.cancel)
 | 
			
		||||
        extras.wait_select(async_conn)
 | 
			
		||||
        cur = async_conn.cursor()
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +102,7 @@ class CancelTests(ConnectingTestCase):
 | 
			
		|||
        self.assertEqual(cur.fetchall(), [(1, )])
 | 
			
		||||
 | 
			
		||||
    def test_async_connection_cancel(self):
 | 
			
		||||
        async_conn = psycopg2.connect(dsn, async=True)
 | 
			
		||||
        async_conn = psycopg2.connect(dsn, async_=True)
 | 
			
		||||
        async_conn.close()
 | 
			
		||||
        self.assertTrue(async_conn.closed)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ import psycopg2.errorcodes
 | 
			
		|||
from psycopg2 import extensions as ext
 | 
			
		||||
 | 
			
		||||
from testutils import (
 | 
			
		||||
    unittest, decorate_all_tests, skip_if_no_superuser,
 | 
			
		||||
    unittest, assertDsnEqual, decorate_all_tests, skip_if_no_superuser,
 | 
			
		||||
    skip_before_postgres, skip_after_postgres, skip_before_libpq,
 | 
			
		||||
    ConnectingTestCase, skip_if_tpc_disabled, skip_if_windows, slow)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -396,9 +396,6 @@ class ParseDsnTestCase(ConnectingTestCase):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class MakeDsnTestCase(ConnectingTestCase):
 | 
			
		||||
    def assertDsnEqual(self, dsn1, dsn2):
 | 
			
		||||
        self.assertEqual(set(dsn1.split()), set(dsn2.split()))
 | 
			
		||||
 | 
			
		||||
    def test_empty_arguments(self):
 | 
			
		||||
        self.assertEqual(ext.make_dsn(), '')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -416,7 +413,7 @@ class MakeDsnTestCase(ConnectingTestCase):
 | 
			
		|||
 | 
			
		||||
    def test_empty_param(self):
 | 
			
		||||
        dsn = ext.make_dsn(dbname='sony', password='')
 | 
			
		||||
        self.assertDsnEqual(dsn, "dbname=sony password=''")
 | 
			
		||||
        assertDsnEqual(self, dsn, "dbname=sony password=''")
 | 
			
		||||
 | 
			
		||||
    def test_escape(self):
 | 
			
		||||
        dsn = ext.make_dsn(dbname='hello world')
 | 
			
		||||
| 
						 | 
				
			
			@ -439,10 +436,10 @@ class MakeDsnTestCase(ConnectingTestCase):
 | 
			
		|||
 | 
			
		||||
    def test_params_merging(self):
 | 
			
		||||
        dsn = ext.make_dsn('dbname=foo host=bar', host='baz')
 | 
			
		||||
        self.assertDsnEqual(dsn, 'dbname=foo host=baz')
 | 
			
		||||
        assertDsnEqual(self, dsn, 'dbname=foo host=baz')
 | 
			
		||||
 | 
			
		||||
        dsn = ext.make_dsn('dbname=foo', user='postgres')
 | 
			
		||||
        self.assertDsnEqual(dsn, 'dbname=foo user=postgres')
 | 
			
		||||
        assertDsnEqual(self, dsn, 'dbname=foo user=postgres')
 | 
			
		||||
 | 
			
		||||
    def test_no_dsn_munging(self):
 | 
			
		||||
        dsnin = 'dbname=a host=b user=c password=d'
 | 
			
		||||
| 
						 | 
				
			
			@ -456,7 +453,7 @@ class MakeDsnTestCase(ConnectingTestCase):
 | 
			
		|||
        self.assertEqual(dsn, url)
 | 
			
		||||
 | 
			
		||||
        dsn = ext.make_dsn(url, application_name='woot')
 | 
			
		||||
        self.assertDsnEqual(dsn,
 | 
			
		||||
        assertDsnEqual(self, dsn,
 | 
			
		||||
            'dbname=test user=tester password=secret application_name=woot')
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(psycopg2.ProgrammingError,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,10 @@ from testutils import unittest, ConnectingTestCase, slow
 | 
			
		|||
try:
 | 
			
		||||
    reload
 | 
			
		||||
except NameError:
 | 
			
		||||
    from imp import reload
 | 
			
		||||
    try:
 | 
			
		||||
        from importlib import reload
 | 
			
		||||
    except ImportError:
 | 
			
		||||
        from imp import reload
 | 
			
		||||
 | 
			
		||||
from threading import Thread
 | 
			
		||||
from psycopg2 import errorcodes
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ import sys
 | 
			
		|||
from subprocess import Popen
 | 
			
		||||
 | 
			
		||||
from testutils import (unittest, skip_before_python, skip_before_postgres,
 | 
			
		||||
    ConnectingTestCase, skip_copy_if_green, script_to_py3, slow)
 | 
			
		||||
    ConnectingTestCase, skip_copy_if_green, script_to_py3, assertDsnEqual, slow)
 | 
			
		||||
 | 
			
		||||
import psycopg2
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,24 +36,21 @@ class ConnectTestCase(unittest.TestCase):
 | 
			
		|||
    def setUp(self):
 | 
			
		||||
        self.args = None
 | 
			
		||||
 | 
			
		||||
        def conect_stub(dsn, connection_factory=None, async=False):
 | 
			
		||||
            self.args = (dsn, connection_factory, async)
 | 
			
		||||
        def connect_stub(dsn, connection_factory=None, async_=False):
 | 
			
		||||
            self.args = (dsn, connection_factory, async_)
 | 
			
		||||
 | 
			
		||||
        self._connect_orig = psycopg2._connect
 | 
			
		||||
        psycopg2._connect = conect_stub
 | 
			
		||||
        psycopg2._connect = connect_stub
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        psycopg2._connect = self._connect_orig
 | 
			
		||||
 | 
			
		||||
    def assertDsnEqual(self, dsn1, dsn2):
 | 
			
		||||
        self.assertEqual(set(dsn1.split()), set(dsn2.split()))
 | 
			
		||||
 | 
			
		||||
    def test_there_has_to_be_something(self):
 | 
			
		||||
        self.assertRaises(TypeError, psycopg2.connect)
 | 
			
		||||
        self.assertRaises(TypeError, psycopg2.connect,
 | 
			
		||||
            connection_factory=lambda dsn, async=False: None)
 | 
			
		||||
            connection_factory=lambda dsn, async_=False: None)
 | 
			
		||||
        self.assertRaises(TypeError, psycopg2.connect,
 | 
			
		||||
            async=True)
 | 
			
		||||
            async_=True)
 | 
			
		||||
 | 
			
		||||
    def test_no_keywords(self):
 | 
			
		||||
        psycopg2.connect('')
 | 
			
		||||
| 
						 | 
				
			
			@ -92,27 +89,27 @@ class ConnectTestCase(unittest.TestCase):
 | 
			
		|||
        self.assertEqual(self.args[0], 'options=stuff')
 | 
			
		||||
 | 
			
		||||
    def test_factory(self):
 | 
			
		||||
        def f(dsn, async=False):
 | 
			
		||||
        def f(dsn, async_=False):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        psycopg2.connect(database='foo', host='baz', connection_factory=f)
 | 
			
		||||
        self.assertDsnEqual(self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], f)
 | 
			
		||||
        self.assertEqual(self.args[2], False)
 | 
			
		||||
 | 
			
		||||
        psycopg2.connect("dbname=foo host=baz", connection_factory=f)
 | 
			
		||||
        self.assertDsnEqual(self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], f)
 | 
			
		||||
        self.assertEqual(self.args[2], False)
 | 
			
		||||
 | 
			
		||||
    def test_async(self):
 | 
			
		||||
        psycopg2.connect(database='foo', host='baz', async=1)
 | 
			
		||||
        self.assertDsnEqual(self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        psycopg2.connect(database='foo', host='baz', async_=1)
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], None)
 | 
			
		||||
        self.assert_(self.args[2])
 | 
			
		||||
 | 
			
		||||
        psycopg2.connect("dbname=foo host=baz", async=True)
 | 
			
		||||
        self.assertDsnEqual(self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        psycopg2.connect("dbname=foo host=baz", async_=True)
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo host=baz')
 | 
			
		||||
        self.assertEqual(self.args[1], None)
 | 
			
		||||
        self.assert_(self.args[2])
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +121,7 @@ class ConnectTestCase(unittest.TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_empty_param(self):
 | 
			
		||||
        psycopg2.connect(database='sony', password='')
 | 
			
		||||
        self.assertDsnEqual(self.args[0], "dbname=sony password=''")
 | 
			
		||||
        assertDsnEqual(self, self.args[0], "dbname=sony password=''")
 | 
			
		||||
 | 
			
		||||
    def test_escape(self):
 | 
			
		||||
        psycopg2.connect(database='hello world')
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +144,7 @@ class ConnectTestCase(unittest.TestCase):
 | 
			
		|||
        self.assertEqual(self.args[0], 'dbname=bar')
 | 
			
		||||
 | 
			
		||||
        psycopg2.connect('dbname=foo', user='postgres')
 | 
			
		||||
        self.assertDsnEqual(self.args[0], 'dbname=foo user=postgres')
 | 
			
		||||
        assertDsnEqual(self, self.args[0], 'dbname=foo user=postgres')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ExceptionsTestCase(ConnectingTestCase):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -183,7 +183,7 @@ class AsyncReplicationTest(ReplicationTestCase):
 | 
			
		|||
    @skip_repl_if_green
 | 
			
		||||
    def test_async_replication(self):
 | 
			
		||||
        conn = self.repl_connect(
 | 
			
		||||
            connection_factory=LogicalReplicationConnection, async=1)
 | 
			
		||||
            connection_factory=LogicalReplicationConnection, async_=1)
 | 
			
		||||
        if conn is None:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ from __future__ import with_statement
 | 
			
		|||
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
import warnings
 | 
			
		||||
from decimal import Decimal
 | 
			
		||||
from datetime import date, datetime
 | 
			
		||||
from functools import wraps
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +77,10 @@ class TypesExtrasTests(ConnectingTestCase):
 | 
			
		|||
        self.failUnless(type(s) == list and len(s) == 0)
 | 
			
		||||
 | 
			
		||||
    def testINET(self):
 | 
			
		||||
        psycopg2.extras.register_inet()
 | 
			
		||||
        with warnings.catch_warnings():
 | 
			
		||||
            warnings.simplefilter('ignore', DeprecationWarning)
 | 
			
		||||
            psycopg2.extras.register_inet()
 | 
			
		||||
 | 
			
		||||
        i = psycopg2.extras.Inet("192.168.1.0/24")
 | 
			
		||||
        s = self.execute("SELECT %s AS foo", (i,))
 | 
			
		||||
        self.failUnless(i.addr == s.addr)
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +89,10 @@ class TypesExtrasTests(ConnectingTestCase):
 | 
			
		|||
        self.failUnless(s is None)
 | 
			
		||||
 | 
			
		||||
    def testINETARRAY(self):
 | 
			
		||||
        psycopg2.extras.register_inet()
 | 
			
		||||
        with warnings.catch_warnings():
 | 
			
		||||
            warnings.simplefilter('ignore', DeprecationWarning)
 | 
			
		||||
            psycopg2.extras.register_inet()
 | 
			
		||||
 | 
			
		||||
        i = psycopg2.extras.Inet("192.168.1.0/24")
 | 
			
		||||
        s = self.execute("SELECT %s AS foo", ([i],))
 | 
			
		||||
        self.failUnless(i.addr == s[0].addr)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,9 @@ else:
 | 
			
		|||
            @wraps(f)
 | 
			
		||||
            def skipIf__(self):
 | 
			
		||||
                if cond:
 | 
			
		||||
                    warnings.warn(msg)
 | 
			
		||||
                    with warnings.catch_warnings():
 | 
			
		||||
                        warnings.simplefilter('always', UserWarning)
 | 
			
		||||
                        warnings.warn(msg)
 | 
			
		||||
                    return
 | 
			
		||||
                else:
 | 
			
		||||
                    return f(self)
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +63,9 @@ else:
 | 
			
		|||
        return skipIf(True, msg)
 | 
			
		||||
 | 
			
		||||
    def skipTest(self, msg):
 | 
			
		||||
        warnings.warn(msg)
 | 
			
		||||
        with warnings.catch_warnings():
 | 
			
		||||
            warnings.simplefilter('always', UserWarning)
 | 
			
		||||
            warnings.warn(msg)
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    unittest.TestCase.skipTest = skipTest
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +134,7 @@ class ConnectingTestCase(unittest.TestCase):
 | 
			
		|||
        import psycopg2
 | 
			
		||||
        try:
 | 
			
		||||
            conn = self.connect(**kwargs)
 | 
			
		||||
            if conn.async == 1:
 | 
			
		||||
            if conn.async_ == 1:
 | 
			
		||||
                self.wait(conn)
 | 
			
		||||
        except psycopg2.OperationalError, e:
 | 
			
		||||
            # If pgcode is not set it is a genuine connection error
 | 
			
		||||
| 
						 | 
				
			
			@ -469,3 +473,7 @@ def slow(f):
 | 
			
		|||
            return self.skipTest("slow test")
 | 
			
		||||
        return f(self)
 | 
			
		||||
    return slow_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def assertDsnEqual(testsuite, dsn1, dsn2):
 | 
			
		||||
    testsuite.assertEqual(set(dsn1.split()), set(dsn2.split()))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user