Use TheMovieDB v3 api
This commit is contained in:
Executable
+121
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#-----------------------
|
||||
# Name: cache.py
|
||||
# Python Library
|
||||
# Author: Raymond Wagner
|
||||
# Purpose: Caching framework to store TMDb API results
|
||||
#-----------------------
|
||||
|
||||
from tmdb_exceptions import *
|
||||
from cache_engine import Engines
|
||||
|
||||
import cache_null
|
||||
import cache_file
|
||||
|
||||
class Cache( object ):
|
||||
"""
|
||||
This class implements a persistent cache, backed in a file specified in
|
||||
the object creation. The file is protected for safe, concurrent access
|
||||
by multiple instances using flock.
|
||||
This cache uses JSON for speed and storage efficiency, so only simple
|
||||
data types are supported.
|
||||
Data is stored in a simple format {key:(expiretimestamp, data)}
|
||||
"""
|
||||
def __init__(self, engine=None, *args, **kwargs):
|
||||
self._engine = None
|
||||
self._data = {}
|
||||
self._age = 0
|
||||
self.configure(engine, *args, **kwargs)
|
||||
|
||||
def _import(self, data=None):
|
||||
if data is None:
|
||||
data = self._engine.get(self._age)
|
||||
for obj in sorted(data, key=lambda x: x.creation):
|
||||
if not obj.expired:
|
||||
self._data[obj.key] = obj
|
||||
self._age = max(self._age, obj.creation)
|
||||
|
||||
def _expire(self):
|
||||
for k,v in self._data.items():
|
||||
if v.expired:
|
||||
del self._data[k]
|
||||
|
||||
def configure(self, engine, *args, **kwargs):
|
||||
if engine is None:
|
||||
engine = 'file'
|
||||
elif engine not in Engines:
|
||||
raise TMDBCacheError("Invalid cache engine specified: "+engine)
|
||||
self._engine = Engines[engine](self)
|
||||
self._engine.configure(*args, **kwargs)
|
||||
|
||||
def put(self, key, data, lifetime=60*60*12):
|
||||
# pull existing data, so cache will be fresh when written back out
|
||||
if self._engine is None:
|
||||
raise TMDBCacheError("No cache engine configured")
|
||||
self._expire()
|
||||
self._import(self._engine.put(key, data, lifetime))
|
||||
|
||||
def get(self, key):
|
||||
if self._engine is None:
|
||||
raise TMDBCacheError("No cache engine configured")
|
||||
self._expire()
|
||||
if key not in self._data:
|
||||
self._import()
|
||||
try:
|
||||
return self._data[key].data
|
||||
except:
|
||||
return None
|
||||
|
||||
def cached(self, callback):
|
||||
"""
|
||||
Returns a decorator that uses a callback to specify the key to use
|
||||
for caching the responses from the decorated function.
|
||||
"""
|
||||
return self.Cached(self, callback)
|
||||
|
||||
class Cached( object ):
|
||||
def __init__(self, cache, callback, func=None, inst=None):
|
||||
self.cache = cache
|
||||
self.callback = callback
|
||||
self.func = func
|
||||
self.inst = inst
|
||||
|
||||
if func:
|
||||
self.__module__ = func.__module__
|
||||
self.__name__ = func.__name__
|
||||
self.__doc__ = func.__doc__
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if self.func is None: # decorator is waiting to be given a function
|
||||
if len(kwargs) or (len(args) != 1):
|
||||
raise TMDBCacheError('Cache.Cached decorator must be called '+\
|
||||
'a single callable argument before it '+\
|
||||
'be used.')
|
||||
elif args[0] is None:
|
||||
raise TMDBCacheError('Cache.Cached decorator called before '+\
|
||||
'being given a function to wrap.')
|
||||
elif not callable(args[0]):
|
||||
raise TMDBCacheError('Cache.Cached must be provided a '+\
|
||||
'callable object.')
|
||||
return self.__class__(self.cache, self.callback, args[0])
|
||||
elif self.inst.lifetime == 0:
|
||||
return self.func(*args, **kwargs)
|
||||
else:
|
||||
key = self.callback()
|
||||
data = self.cache.get(key)
|
||||
if data is None:
|
||||
data = self.func(*args, **kwargs)
|
||||
if hasattr(self.inst, 'lifetime'):
|
||||
self.cache.put(key, data, self.inst.lifetime)
|
||||
else:
|
||||
self.cache.put(key, data)
|
||||
return data
|
||||
|
||||
def __get__(self, inst, owner):
|
||||
if inst is None:
|
||||
return self
|
||||
func = self.func.__get__(inst, owner)
|
||||
callback = self.callback.__get__(inst, owner)
|
||||
return self.__class__(self.cache, callback, func, inst)
|
||||
|
||||
Reference in New Issue
Block a user