"""Memcached and in-memory cache result backend."""fromkombu.utils.encodingimportbytes_to_str,ensure_bytesfromkombu.utils.objectsimportcached_propertyfromcelery.exceptionsimportImproperlyConfiguredfromcelery.utils.functionalimportLRUCachefrom.baseimportKeyValueStoreBackend__all__=('CacheBackend',)_imp=[None]REQUIRES_BACKEND="""\The Memcached backend requires either pylibmc or python-memcached.\"""UNKNOWN_BACKEND="""\The cache backend {0!r} is unknown,Please use one of the following backends instead: {1}\"""# Global shared in-memory cache for in-memory cache client# This is to share cache between threads_DUMMY_CLIENT_CACHE=LRUCache(limit=5000)defimport_best_memcache():if_imp[0]isNone:is_pylibmc,memcache_key_t=False,bytes_to_strtry:importpylibmcasmemcacheis_pylibmc=TrueexceptImportError:try:importmemcacheexceptImportError:raiseImproperlyConfigured(REQUIRES_BACKEND)_imp[0]=(is_pylibmc,memcache,memcache_key_t)return_imp[0]defget_best_memcache(*args,**kwargs):# pylint: disable=unpacking-non-sequence# This is most definitely a sequence, but pylint thinks it's not.is_pylibmc,memcache,key_t=import_best_memcache()Client=_Client=memcache.Clientifnotis_pylibmc:defClient(*args,**kwargs):# noqa: F811kwargs.pop('behaviors',None)return_Client(*args,**kwargs)returnClient,key_tclassDummyClient:def__init__(self,*args,**kwargs):self.cache=_DUMMY_CLIENT_CACHEdefget(self,key,*args,**kwargs):returnself.cache.get(key)defget_multi(self,keys):cache=self.cachereturn{k:cache[k]forkinkeysifkincache}defset(self,key,value,*args,**kwargs):self.cache[key]=valuedefdelete(self,key,*args,**kwargs):self.cache.pop(key,None)defincr(self,key,delta=1):returnself.cache.incr(key,delta)deftouch(self,key,expire):passbackends={'memcache':get_best_memcache,'memcached':get_best_memcache,'pylibmc':get_best_memcache,'memory':lambda:(DummyClient,ensure_bytes),}
[文档]classCacheBackend(KeyValueStoreBackend):"""Cache result backend."""servers=Nonesupports_autoexpire=Truesupports_native_join=Trueimplements_incr=Truedef__init__(self,app,expires=None,backend=None,options=None,url=None,**kwargs):options={}ifnotoptionselseoptionssuper().__init__(app,**kwargs)self.url=urlself.options=dict(self.app.conf.cache_backend_options,**options)self.backend=urlorbackendorself.app.conf.cache_backendifself.backend:self.backend,_,servers=self.backend.partition('://')self.servers=servers.rstrip('/').split(';')self.expires=self.prepare_expires(expires,type=int)try:self.Client,self.key_t=backends[self.backend]()exceptKeyError:raiseImproperlyConfigured(UNKNOWN_BACKEND.format(self.backend,', '.join(backends)))self._encode_prefixes()# rencode the keyprefixes
[文档]defas_uri(self,*args,**kwargs):"""Return the backend as an URI. This properly handles the case of multiple servers. """servers=';'.join(self.servers)returnf'{self.backend}://{servers}/'