diff options
author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2019-02-02 19:21:39 +0000 |
---|---|---|
committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2019-02-02 19:29:20 +0000 |
commit | 35ec7ad9c1ecb165eaeb2b8d4dae84ed8bad182b (patch) | |
tree | 88669b2a2413bfc04ec68f7dca646e83c3e68643 /lib/extras.py | |
parent | 805527fcd6bedc2671a37c59299c1fa9148f9e6e (diff) | |
download | psycopg2-fast-namedtuple.tar.gz |
Use a proper LRU cache for namedtuplesfast-namedtuple
Previous one didn't refresh by last use. Use the stdlib version for py3
and one of our own for py2.
Max size set to 512, which should be fine for everyone (tweaking is
still possible by monkeypatching, as the tests do, but I don't want to
make an interface of it).
Diffstat (limited to 'lib/extras.py')
-rw-r--r-- | lib/extras.py | 26 |
1 files changed, 13 insertions, 13 deletions
diff --git a/lib/extras.py b/lib/extras.py index a4012e2..d73c5b2 100644 --- a/lib/extras.py +++ b/lib/extras.py @@ -35,9 +35,10 @@ import logging as _logging import psycopg2 from psycopg2 import extensions as _ext -from psycopg2.extensions import cursor as _cursor -from psycopg2.extensions import connection as _connection -from psycopg2.extensions import adapt as _A, quote_ident +from .extensions import cursor as _cursor +from .extensions import connection as _connection +from .extensions import adapt as _A, quote_ident +from .compat import lru_cache from psycopg2._psycopg import ( # noqa REPLICATION_PHYSICAL, REPLICATION_LOGICAL, @@ -386,28 +387,27 @@ class NamedTupleCursor(_cursor): _re_clean = _re.compile( '[' + _re.escape(' !"#$%&\'()*+,-./:;<=>?@[\\]^`{|}~') + ']') - _nt_cache = OrderedDict() - def _make_nt(self): - key = tuple(d[0] for d in (self.description or ())) - nt = self._nt_cache.get(key) - if nt is not None: - return nt + key = tuple(d[0] for d in self.description) if self.description else () + return self._cached_make_nt(key) + def _do_make_nt(self, key): fields = [] for s in key: s = self._re_clean.sub('_', s) + # Python identifier cannot start with numbers, namedtuple fields + # cannot start with underscore. So... if s[0] == '_' or '0' <= s[0] <= '9': s = 'f' + s fields.append(s) nt = namedtuple("Record", fields) - self._nt_cache[key] = nt - while len(self._nt_cache) > self.MAX_CACHE: - self._nt_cache.popitem(last=False) - return nt + # Exposed for testability, and if someone wants to monkeypatch to tweak + # the cache size. + _cached_make_nt = lru_cache(512)(_do_make_nt) + class LoggingConnection(_connection): """A connection that logs all queries to a file or logger__ object. |