mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-10 19:16:34 +03:00
Merge branch 'fix-namedtuple-cache'
This commit is contained in:
commit
2635f43788
1
NEWS
1
NEWS
|
@ -8,6 +8,7 @@ What's new in psycopg 2.8.3
|
||||||
`~psycopg2.extras.ReplicationCursor.start_replication()` method and other
|
`~psycopg2.extras.ReplicationCursor.start_replication()` method and other
|
||||||
facilities to send automatic replication keepalives at periodic intervals
|
facilities to send automatic replication keepalives at periodic intervals
|
||||||
(:ticket:`#913`).
|
(:ticket:`#913`).
|
||||||
|
- Fixed namedtuples caching introduced in 2.8 (:ticket:`#928`).
|
||||||
|
|
||||||
|
|
||||||
What's new in psycopg 2.8.2
|
What's new in psycopg 2.8.2
|
||||||
|
|
|
@ -372,10 +372,11 @@ class NamedTupleCursor(_cursor):
|
||||||
key = tuple(d[0] for d in self.description) if self.description else ()
|
key = tuple(d[0] for d in self.description) if self.description else ()
|
||||||
return self._cached_make_nt(key)
|
return self._cached_make_nt(key)
|
||||||
|
|
||||||
def _do_make_nt(self, key):
|
@classmethod
|
||||||
|
def _do_make_nt(cls, key):
|
||||||
fields = []
|
fields = []
|
||||||
for s in key:
|
for s in key:
|
||||||
s = self._re_clean.sub('_', s)
|
s = cls._re_clean.sub('_', s)
|
||||||
# Python identifier cannot start with numbers, namedtuple fields
|
# Python identifier cannot start with numbers, namedtuple fields
|
||||||
# cannot start with underscore. So...
|
# cannot start with underscore. So...
|
||||||
if s[0] == '_' or '0' <= s[0] <= '9':
|
if s[0] == '_' or '0' <= s[0] <= '9':
|
||||||
|
@ -385,9 +386,14 @@ class NamedTupleCursor(_cursor):
|
||||||
nt = namedtuple("Record", fields)
|
nt = namedtuple("Record", fields)
|
||||||
return nt
|
return nt
|
||||||
|
|
||||||
# Exposed for testability, and if someone wants to monkeypatch to tweak
|
|
||||||
# the cache size.
|
@lru_cache(512)
|
||||||
_cached_make_nt = lru_cache(512)(_do_make_nt)
|
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)
|
||||||
|
|
||||||
|
|
||||||
class LoggingConnection(_connection):
|
class LoggingConnection(_connection):
|
||||||
|
|
|
@ -615,21 +615,31 @@ class NamedTupleCursorTest(ConnectingTestCase):
|
||||||
self.assertEqual(i + 1, curs.rownumber)
|
self.assertEqual(i + 1, curs.rownumber)
|
||||||
|
|
||||||
def test_cache(self):
|
def test_cache(self):
|
||||||
|
NamedTupleCursor._cached_make_nt.cache_clear()
|
||||||
|
|
||||||
curs = self.conn.cursor()
|
curs = self.conn.cursor()
|
||||||
curs.execute("select 10 as a, 20 as b")
|
curs.execute("select 10 as a, 20 as b")
|
||||||
r1 = curs.fetchone()
|
r1 = curs.fetchone()
|
||||||
curs.execute("select 10 as a, 20 as c")
|
curs.execute("select 10 as a, 20 as c")
|
||||||
r2 = curs.fetchone()
|
r2 = curs.fetchone()
|
||||||
|
|
||||||
|
# Get a new cursor to check that the cache works across multiple ones
|
||||||
|
curs = self.conn.cursor()
|
||||||
curs.execute("select 10 as a, 30 as b")
|
curs.execute("select 10 as a, 30 as b")
|
||||||
r3 = curs.fetchone()
|
r3 = curs.fetchone()
|
||||||
|
|
||||||
self.assert_(type(r1) is type(r3))
|
self.assert_(type(r1) is type(r3))
|
||||||
self.assert_(type(r1) is not type(r2))
|
self.assert_(type(r1) is not type(r2))
|
||||||
|
|
||||||
|
cache_info = NamedTupleCursor._cached_make_nt.cache_info()
|
||||||
|
self.assertEqual(cache_info.hits, 1)
|
||||||
|
self.assertEqual(cache_info.misses, 2)
|
||||||
|
self.assertEqual(cache_info.currsize, 2)
|
||||||
|
|
||||||
def test_max_cache(self):
|
def test_max_cache(self):
|
||||||
old_func = NamedTupleCursor._cached_make_nt
|
old_func = NamedTupleCursor._cached_make_nt
|
||||||
NamedTupleCursor._cached_make_nt = \
|
NamedTupleCursor._cached_make_nt = \
|
||||||
lru_cache(8)(NamedTupleCursor._do_make_nt)
|
lru_cache(8)(NamedTupleCursor._cached_make_nt.__wrapped__)
|
||||||
try:
|
try:
|
||||||
recs = []
|
recs = []
|
||||||
curs = self.conn.cursor()
|
curs = self.conn.cursor()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user