util.cache: New module handling both in-memory and on-file system caching.
This commit is contained in:
parent
769bc6d3bf
commit
037912ee89
@ -13,3 +13,5 @@
|
|||||||
from slixmpp.util.misc_ops import bytes, unicode, hashes, hash, \
|
from slixmpp.util.misc_ops import bytes, unicode, hashes, hash, \
|
||||||
num_to_bytes, bytes_to_num, quote, \
|
num_to_bytes, bytes_to_num, quote, \
|
||||||
XOR
|
XOR
|
||||||
|
from slixmpp.util.cache import MemoryCache, MemoryPerJidCache, \
|
||||||
|
FileSystemCache, FileSystemPerJidCache
|
||||||
|
105
slixmpp/util/cache.py
Normal file
105
slixmpp/util/cache.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
"""
|
||||||
|
Slixmpp: The Slick XMPP Library
|
||||||
|
Copyright (C) 2018 Emmanuel Gil Peyrot
|
||||||
|
This file is part of Slixmpp.
|
||||||
|
|
||||||
|
See the file LICENSE for copying permission.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class Cache:
|
||||||
|
def retrieve(self, key):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def store(self, key, value):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
class PerJidCache:
|
||||||
|
def retrieve_by_jid(self, jid, key):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def store_by_jid(self, jid, key, value):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
class MemoryCache(Cache):
|
||||||
|
def __init__(self):
|
||||||
|
self.cache = {}
|
||||||
|
|
||||||
|
def retrieve(self, key):
|
||||||
|
return self.cache.get(key, None)
|
||||||
|
|
||||||
|
def store(self, key, value):
|
||||||
|
self.cache[key] = value
|
||||||
|
return True
|
||||||
|
|
||||||
|
class MemoryPerJidCache(PerJidCache):
|
||||||
|
def __init__(self):
|
||||||
|
self.cache = {}
|
||||||
|
|
||||||
|
def retrieve_by_jid(self, jid, key):
|
||||||
|
cache = self.cache.get(jid.bare, None)
|
||||||
|
if cache is None:
|
||||||
|
return None
|
||||||
|
return cache.get(key, None)
|
||||||
|
|
||||||
|
def store_by_jid(self, jid, key, value):
|
||||||
|
cache = self.cache.setdefault(jid.bare, {})
|
||||||
|
cache[key] = value
|
||||||
|
return True
|
||||||
|
|
||||||
|
class FileSystemStorage:
|
||||||
|
def __init__(self, encode, decode, binary):
|
||||||
|
self.encode = encode
|
||||||
|
self.decode = decode
|
||||||
|
self.read = 'rb' if binary else 'r'
|
||||||
|
self.write = 'wb' if binary else 'w'
|
||||||
|
|
||||||
|
def _retrieve(self, directory, key):
|
||||||
|
filename = os.path.join(directory, key.replace('/', '_'))
|
||||||
|
try:
|
||||||
|
with open(filename, self.read) as cache_file:
|
||||||
|
return self.decode(cache_file.read())
|
||||||
|
except FileNotFoundError:
|
||||||
|
log.debug('%s not present in cache', key)
|
||||||
|
except OSError:
|
||||||
|
log.debug('Failed to read %s from cache:', key, exc_info=True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _store(self, directory, key, value):
|
||||||
|
filename = os.path.join(directory, key.replace('/', '_'))
|
||||||
|
try:
|
||||||
|
os.makedirs(directory, exist_ok=True)
|
||||||
|
with open(filename, self.write) as output:
|
||||||
|
output.write(self.encode(value))
|
||||||
|
return True
|
||||||
|
except OSError:
|
||||||
|
log.debug('Failed to store %s to cache:', key, exc_info=True)
|
||||||
|
return False
|
||||||
|
|
||||||
|
class FileSystemCache(Cache, FileSystemStorage):
|
||||||
|
def __init__(self, directory, cache_type, *, encode, decode, binary=False):
|
||||||
|
FileSystemStorage.__init__(self, encode, decode, binary)
|
||||||
|
self.base_dir = os.path.join(directory, cache_type)
|
||||||
|
|
||||||
|
def retrieve(self, key):
|
||||||
|
return self._retrieve(self.base_dir, key)
|
||||||
|
|
||||||
|
def store(self, key, value):
|
||||||
|
return self._store(self.base_dir, key, value)
|
||||||
|
|
||||||
|
class FileSystemPerJidCache(PerJidCache, FileSystemStorage):
|
||||||
|
def __init__(self, directory, cache_type, *, encode, decode, binary=False):
|
||||||
|
FileSystemStorage.__init__(self, encode, decode, binary)
|
||||||
|
self.base_dir = os.path.join(directory, cache_type)
|
||||||
|
|
||||||
|
def retrieve_by_jid(self, jid, key):
|
||||||
|
directory = os.path.join(self.base_dir, jid.bare)
|
||||||
|
return self._retrieve(directory, key)
|
||||||
|
|
||||||
|
def store_by_jid(self, jid, key, value):
|
||||||
|
directory = os.path.join(self.base_dir, jid.bare)
|
||||||
|
return self._store(directory, key, value)
|
Loading…
x
Reference in New Issue
Block a user