# -*- coding: utf-8 -*- """ Copyright (C) 2014-2016 bromix (plugin.video.youtube) Copyright (C) 2016-2019 plugin.video.youtube SPDX-License-Identifier: GPL-2.0-only See LICENSES/GPL-2.0-only for more information. """ from functools import partial import hashlib from .storage import Storage class FunctionCache(Storage): ONE_MINUTE = 60 ONE_HOUR = 60 * ONE_MINUTE ONE_DAY = 24 * ONE_HOUR ONE_WEEK = 7 * ONE_DAY ONE_MONTH = 4 * ONE_WEEK def __init__(self, filename, max_file_size_mb=5): max_file_size_kb = max_file_size_mb * 1024 Storage.__init__(self, filename, max_file_size_kb=max_file_size_kb) self._enabled = True def clear(self): self._clear() def enabled(self): """ Enables the caching :return: """ self._enabled = True def disable(self): """ Disable caching e.g. for tests :return: """ self._enabled = False @staticmethod def _create_id_from_func(partial_func): """ Creats an id from the given function :param partial_func: :return: id for the given function """ m = hashlib.md5() m.update(partial_func.func.__module__.encode('utf-8')) m.update(partial_func.func.__name__.encode('utf-8')) m.update(str(partial_func.args).encode('utf-8')) m.update(str(partial_func.keywords).encode('utf-8')) return m.hexdigest() def _get_cached_data(self, partial_func): cache_id = self._create_id_from_func(partial_func) return self._get(cache_id), cache_id def get_cached_only(self, func, *args, **keywords): partial_func = partial(func, *args, **keywords) # if caching is disabled call the function if not self._enabled: return partial_func() # only return before cached data data, cache_id = self._get_cached_data(partial_func) if data is not None: return data[0] return None def get(self, seconds, func, *args, **keywords): """ Returns the cached data of the given function. :param partial_func: function to cache :param seconds: time to live in seconds :param return_cached_only: return only cached data and don't call the function :return: """ partial_func = partial(func, *args, **keywords) # if caching is disabled call the function if not self._enabled: return partial_func() cached_data = None cached_time = None data, cache_id = self._get_cached_data(partial_func) if data is not None: cached_data = data[0] cached_time = data[1] diff_seconds = 0 if cached_time is not None: # this is so stupid, but we have the function 'total_seconds' only starting with python 2.7 diff_seconds = self.get_seconds_diff(cached_time) if cached_data is None or diff_seconds > seconds: cached_data = partial_func() self._set(cache_id, cached_data) return cached_data def _optimize_item_count(self): # override method from resources/lib/youtube_plugin/kodion/utils/storage.py # for function cache do not optimize by item count, using database size. pass