<s> import os , time <EOL> from . cross import pickle , md5hex <EOL> from funcy import wraps <EOL> from . conf import settings <EOL> from . utils import func_cache_key , cached_view_fab <EOL> from . redis import redis_client , handle_connection_failure <EOL> __all__ = ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) <EOL> class CacheMiss ( Exception ) : <EOL> pass <EOL> class CacheKey ( str ) : <EOL> @ classmethod <EOL> def make ( cls , value , cache = None , timeout = None ) : <EOL> self = CacheKey ( value ) <EOL> self . cache = cache <EOL> self . timeout = timeout <EOL> return self <EOL> def get ( self ) : <EOL> self . cache . get ( self ) <EOL> def set ( self , value ) : <EOL> self . cache . set ( self , value , self . timeout ) <EOL> def delete ( self ) : <EOL> self . cache . delete ( self ) <EOL> class BaseCache ( object ) : <EOL> """<STR_LIT>""" <EOL> def cached ( self , timeout = None , extra = None , key_func = func_cache_key ) : <EOL> """<STR_LIT>""" <EOL> if callable ( timeout ) : <EOL> return self . cached ( key_func = key_func ) ( timeout ) <EOL> def decorator ( func ) : <EOL> @ wraps ( func ) <EOL> def wrapper ( * args , ** kwargs ) : <EOL> cache_key = '<STR_LIT>' + key_func ( func , args , kwargs , extra ) <EOL> try : <EOL> result = self . get ( cache_key ) <EOL> except CacheMiss : <EOL> result = func ( * args , ** kwargs ) <EOL> self . set ( cache_key , result , timeout ) <EOL> return result <EOL> def invalidate ( * args , ** kwargs ) : <EOL> cache_key = '<STR_LIT>' + key_func ( func , args , kwargs , extra ) <EOL> self . delete ( cache_key ) <EOL> wrapper . invalidate = invalidate <EOL> def key ( * args , ** kwargs ) : <EOL> cache_key = '<STR_LIT>' + key_func ( func , args , kwargs , extra ) <EOL> return CacheKey . make ( cache_key , cache = self , timeout = timeout ) <EOL> wrapper . key = key <EOL> return wrapper <EOL> return decorator <EOL> def cached_view ( self , timeout = None , extra = None ) : <EOL> return cached_view_fab ( self . cached ) ( timeout = timeout , extra = extra ) <EOL> class RedisCache ( BaseCache ) : <EOL> def __init__ ( self , conn ) : <EOL> self . conn = conn <EOL> def get ( self , cache_key ) : <EOL> data = self . conn . get ( cache_key ) <EOL> if data is None : <EOL> raise CacheMiss <EOL> return pickle . loads ( data ) <EOL> @ handle_connection_failure <EOL> def set ( self , cache_key , data , timeout = None ) : <EOL> pickled_data = pickle . dumps ( data , - <NUM_LIT:1> ) <EOL> if timeout is not None : <EOL> self . conn . setex ( cache_key , timeout , pickled_data ) <EOL> else : <EOL> self . conn . set ( cache_key , pickled_data ) <EOL> @ handle_connection_failure <EOL> def delete ( self , cache_key ) : <EOL> self . conn . delete ( cache_key ) <EOL> cache = RedisCache ( redis_client ) <EOL> cached = cache . cached <EOL> cached_view = cache . cached_view <EOL> class FileCache ( BaseCache ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , path , timeout = settings . FILE_CACHE_TIMEOUT ) : <EOL> self . _dir = path <EOL> self . _default_timeout = timeout <EOL> def _key_to_filename ( self , key ) : <EOL> """<STR_LIT>""" <EOL> digest = md5hex ( key ) <EOL> return os . path . join ( self . _dir , digest [ - <NUM_LIT:2> : ] , digest [ : - <NUM_LIT:2> ] ) <EOL> def get ( self , key ) : <EOL> filename = self . _key_to_filename ( key ) <EOL> try : <EOL> if time . time ( ) >= os . stat ( filename ) . st_mtime : <EOL> self . delete ( filename ) <EOL> raise CacheMiss <EOL> with open ( filename , '<STR_LIT:rb>' ) as f : <EOL> return pickle . load ( f ) <EOL> except ( IOError , OSError , EOFError , pickle . PickleError ) : <EOL> raise CacheMiss <EOL> def set ( self , key , data , timeout = None ) : <EOL> filename = self . _key_to_filename ( key ) <EOL> dirname = os . path . dirname ( filename ) <EOL> if timeout is None : <EOL> timeout = self . _default_timeout <EOL> try : <EOL> if not os . path . exists ( dirname ) : <EOL> os . makedirs ( dirname ) <EOL> f = os . open ( filename , os . O_EXCL | os . O_WRONLY | os . O_CREAT ) <EOL> try : <EOL> os . write ( f , pickle . dumps ( data , pickle . HIGHEST_PROTOCOL ) ) <EOL> finally : <EOL> os . close ( f ) <EOL> os . utime ( filename , ( <NUM_LIT:0> , time . time ( ) + timeout ) ) <EOL> except ( IOError , OSError ) : <EOL> pass <EOL> def delete ( self , fname ) : <EOL> try : <EOL> os . remove ( fname ) <EOL> dirname = os . path . dirname ( fname ) <EOL> os . rmdir ( dirname ) <EOL> except ( IOError , OSError ) : <EOL> pass <EOL> file_cache = FileCache ( settings . FILE_CACHE_DIR ) </s>
