From 21d16b6f6754e5d8ddf10b0d383fe731f13bce8e Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 5 Apr 2019 19:03:38 +0100 Subject: [PATCH] Fixed RealDictCursor.pop() Addresses #886, but there might be something else broken there. --- NEWS | 1 + lib/extras.py | 7 +++++++ tests/test_extras_dictcursor.py | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/NEWS b/NEWS index da7950bd..7aa146e5 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ Current release What's new in psycopg 2.8.1 --------------------------- +- Fixed `RealDictRow.pop()` (:ticket:`#886`). - Fixed "there's no async cursor" error polling a connection with no cursor (:ticket:`#887`). diff --git a/lib/extras.py b/lib/extras.py index ad31e8ed..c5294cef 100644 --- a/lib/extras.py +++ b/lib/extras.py @@ -290,6 +290,13 @@ class RealDictRow(dict): def items(self): return ((k, self[k]) for k in self._column_mapping) + def pop(self, key, *args): + found = key in self + rv = super(RealDictRow, self).pop(key, *args) + if found: + self._column_mapping.remove(key) + return rv + if PY2: iterkeys = keys itervalues = values diff --git a/tests/test_extras_dictcursor.py b/tests/test_extras_dictcursor.py index 7eee4cce..119110e8 100755 --- a/tests/test_extras_dictcursor.py +++ b/tests/test_extras_dictcursor.py @@ -221,6 +221,12 @@ class ExtrasDictCursorTests(_DictCursorBase): class ExtrasDictCursorRealTests(_DictCursorBase): + def testRealMeansReal(self): + curs = self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) + curs.execute("SELECT * FROM ExtrasDictCursorTests") + row = curs.fetchone() + self.assert_(isinstance(row, dict)) + def testDictCursorWithPlainCursorRealFetchOne(self): self._testWithPlainCursorReal(lambda curs: curs.fetchone()) @@ -358,6 +364,19 @@ class ExtrasDictCursorRealTests(_DictCursorBase): self.assertEqual(list(r1.itervalues()), list(r.itervalues())) self.assertEqual(list(r1.iteritems()), list(r.iteritems())) + def test_pop(self): + curs = self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) + curs.execute("select 1 as a, 2 as b, 3 as c") + r = curs.fetchone() + self.assertEqual(r.pop('b'), 2) + self.assertEqual(list(r), ['a', 'c']) + self.assertEqual(list(r.keys()), ['a', 'c']) + self.assertEqual(list(r.values()), [1, 3]) + self.assertEqual(list(r.items()), [('a', 1), ('c', 3)]) + + self.assertEqual(r.pop('b', None), None) + self.assertRaises(KeyError, r.pop, 'b') + class NamedTupleCursorTest(ConnectingTestCase): def setUp(self):