Skip to content
Browse files

Merge branch 'close-idempotent' into devel

  • Loading branch information...
2 parents b975991 + 84f2a37 commit 37aa62ca52149360331e54740a2f70567343710e @dvarrazzo dvarrazzo committed Mar 5, 2012
Showing with 29 additions and 8 deletions.
  1. +2 −0 NEWS
  2. +7 −4 psycopg/connection_int.c
  3. +0 −2 psycopg/connection_type.c
  4. +5 −1 psycopg/cursor_type.c
  5. +3 −1 tests/dbapi20.py
  6. +6 −0 tests/test_connection.py
  7. +6 −0 tests/test_cursor.py
View
2 NEWS
@@ -1,6 +1,8 @@
What's new in psycopg 2.4.5
---------------------------
+ - The close() methods on connections and cursors don't raise exceptions
+ if called on already closed objects.
- Fixed fetchmany() with no argument in cursor subclasses
(ticket #84).
- Use lo_creat() instead of lo_create() when possible for better
View
11 psycopg/connection_int.c
@@ -906,6 +906,10 @@ conn_poll(connectionObject *self)
void
conn_close(connectionObject *self)
{
+ if (self->closed) {
+ return;
+ }
+
/* sets this connection as closed even for other threads; also note that
we need to check the value of pgconn, because we get called even when
the connection fails! */
@@ -922,14 +926,13 @@ conn_close(connectionObject *self)
* closed only in status CONN_STATUS_READY.
*/
- if (self->closed == 0)
- self->closed = 1;
+ self->closed = 1;
if (self->pgconn) {
PQfinish(self->pgconn);
- PQfreeCancel(self->cancel);
- Dprintf("conn_close: PQfinish called");
self->pgconn = NULL;
+ Dprintf("conn_close: PQfinish called");
+ PQfreeCancel(self->cancel);
self->cancel = NULL;
}
View
2 psycopg/connection_type.c
@@ -122,8 +122,6 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds)
static PyObject *
psyco_conn_close(connectionObject *self, PyObject *args)
{
- EXC_IF_CONN_CLOSED(self);
-
Dprintf("psyco_conn_close: closing connection at %p", self);
conn_close(self);
Dprintf("psyco_conn_close: connection at %p closed", self);
View
6 psycopg/cursor_type.c
@@ -52,9 +52,12 @@ extern PyObject *pyPsycopgTzFixedOffsetTimezone;
static PyObject *
psyco_curs_close(cursorObject *self, PyObject *args)
{
- EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, close);
+ if (self->closed) {
+ goto exit;
+ }
+
if (self->name != NULL) {
char buffer[128];
@@ -66,6 +69,7 @@ psyco_curs_close(cursorObject *self, PyObject *args)
self->closed = 1;
Dprintf("psyco_curs_close: cursor at %p closed", self);
+exit:
Py_INCREF(Py_None);
return Py_None;
}
View
4 tests/dbapi20.py
@@ -380,7 +380,9 @@ def test_close(self):
self.assertRaises(self.driver.Error,con.commit)
# connection.close should raise an Error if called more than once
- self.assertRaises(self.driver.Error,con.close)
+ # Issue discussed on DB-SIG: consensus seem that close() should not
+ # raised if called on closed objects. Issue reported back to Stuart.
+ # self.assertRaises(self.driver.Error,con.close)
def test_execute(self):
con = self._connect()
View
6 tests/test_connection.py
@@ -48,6 +48,12 @@ def test_closed_attribute(self):
conn.close()
self.assertEqual(conn.closed, True)
+ def test_close_idempotent(self):
+ conn = self.conn
+ conn.close()
+ conn.close()
+ self.assert_(conn.closed)
+
def test_cursor_closed_attribute(self):
conn = self.conn
curs = conn.cursor()
View
6 tests/test_cursor.py
@@ -37,6 +37,12 @@ def setUp(self):
def tearDown(self):
self.conn.close()
+ def test_close_idempotent(self):
+ cur = self.conn.cursor()
+ cur.close()
+ cur.close()
+ self.assert_(cur.closed)
+
def test_empty_query(self):
cur = self.conn.cursor()
self.assertRaises(psycopg2.ProgrammingError, cur.execute, "")

0 comments on commit 37aa62c

Please sign in to comment.
Something went wrong with that request. Please try again.