diff options
author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2020-04-06 02:30:29 +1200 |
---|---|---|
committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2020-04-06 14:10:02 +1200 |
commit | 62743c3be1de686154c3c927f1d6df99e5203b39 (patch) | |
tree | 0e126cb17a4520b3a59b385c84df51d9fc5e7d0b | |
parent | 2bee47efacd3c114fd93ce84880f91799b0b72af (diff) | |
download | psycopg2-62743c3be1de686154c3c927f1d6df99e5203b39.tar.gz |
Fixed copy() on DictRowfix-1073
Close #1073.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | lib/extras.py | 8 | ||||
-rwxr-xr-x | tests/test_extras_dictcursor.py | 29 |
3 files changed, 37 insertions, 1 deletions
@@ -10,6 +10,7 @@ What's new in psycopg 2.8.5 `~psycopg2.extras.LoggingConnection` (:ticket:`#1026`). - `~psycopg2.extensions.Column` objects in `cursor.description` can be sliced (:ticket:`#1034`). +- Fixed `~copy.copy()` of `~psycopg2.extras.DictCursor` rows (:ticket:`#1073`). What's new in psycopg 2.8.4 diff --git a/lib/extras.py b/lib/extras.py index 85c1a44..ccb8b3f 100644 --- a/lib/extras.py +++ b/lib/extras.py @@ -196,6 +196,10 @@ class DictRow(list): def __contains__(self, x): return x in self._index + def __reduce__(self): + # this is apparently useless, but it fixes #1073 + return super(DictRow, self).__reduce__() + def __getstate__(self): return self[:], self._index.copy() @@ -392,6 +396,7 @@ class NamedTupleCursor(_cursor): def _cached_make_nt(cls, key): return cls._do_make_nt(key) + # Exposed for testability, and if someone wants to monkeypatch to tweak # the cache size. NamedTupleCursor._cached_make_nt = classmethod(_cached_make_nt) @@ -410,7 +415,8 @@ class LoggingConnection(_connection): instance from the standard logging module. """ self._logobj = logobj - if _logging and isinstance(logobj, (_logging.Logger, _logging.LoggerAdapter)): + if _logging and isinstance( + logobj, (_logging.Logger, _logging.LoggerAdapter)): self.log = self._logtologger else: self.log = self._logtofile diff --git a/tests/test_extras_dictcursor.py b/tests/test_extras_dictcursor.py index d4bb12f..180d996 100755 --- a/tests/test_extras_dictcursor.py +++ b/tests/test_extras_dictcursor.py @@ -15,6 +15,7 @@ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public # License for more details. +import copy import time import pickle import unittest @@ -158,6 +159,20 @@ class ExtrasDictCursorTests(_DictCursorBase): self.assertEqual(r['b'], r1['b']) self.assertEqual(r._index, r1._index) + def test_copy(self): + curs = self.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + curs.execute("select 10 as foo, 'hi' as bar") + rv = curs.fetchone() + self.assertEqual(len(rv), 2) + + rv2 = copy.copy(rv) + self.assertEqual(len(rv2), 2) + self.assertEqual(len(rv), 2) + + rv3 = copy.deepcopy(rv) + self.assertEqual(len(rv3), 2) + self.assertEqual(len(rv), 2) + @skip_from_python(3) def test_iter_methods_2(self): curs = self.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) @@ -267,6 +282,20 @@ class ExtrasDictCursorRealTests(_DictCursorBase): self.assertEqual(r['a'], r1['a']) self.assertEqual(r['b'], r1['b']) + def test_copy(self): + curs = self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) + curs.execute("select 10 as foo, 'hi' as bar") + rv = curs.fetchone() + self.assertEqual(len(rv), 2) + + rv2 = copy.copy(rv) + self.assertEqual(len(rv2), 2) + self.assertEqual(len(rv), 2) + + rv3 = copy.deepcopy(rv) + self.assertEqual(len(rv3), 2) + self.assertEqual(len(rv), 2) + def testDictCursorRealWithNamedCursorFetchOne(self): self._testWithNamedCursorReal(lambda curs: curs.fetchone()) |