def count_calls(function): ''' Decorator for counting the calls made to a function. The number of calls is available in the decorated function's `.call_count` attribute. Example usage: >>> @count_calls ... def f(x): ... return x*x ... >>> f(3) 9 >>> f(6) 36 >>> f.call_count 2 >>> f(9) 81 >>> f.call_count 3 ''' def _count_calls(function, *args, **kwargs): decorated_function.call_count += 1 return function(*args, **kwargs) decorated_function = decorator_tools.decorator(_count_calls, function) decorated_function.call_count = 0 return decorated_function
def __call__(self, function): '''Decorate `function` to use this context manager when it's called.''' def inner(function_, *args, **kwargs): with self: return function_(*args, **kwargs) return decorator_tools.decorator(inner, function)
def __call__(self, method_function): ''' Decorate method to use value of `CachedProperty` as a context manager. ''' def inner(same_method_function, self_obj, *args, **kwargs): with getattr(self_obj, self.get_our_name(self_obj)): return method_function(self_obj, *args, **kwargs) return decorator_tools.decorator(inner, method_function)
def decorator(function): def inner(function_, *args, **kwargs): if decorated_function.condition is not None: if decorated_function.condition is True or \ decorated_function.condition( decorated_function.original_function, *args, **kwargs ): decorated_function.profiling_on = True if decorated_function.profiling_on: if decorated_function.off_after: decorated_function.profiling_on = False decorated_function.condition = None # This line puts it in locals, weird: decorated_function.original_function result, profile_ = profile_expression( 'decorated_function.original_function(*args, **kwargs)', globals(), locals() ) decorated_function.profile_handler(profile_) return result else: # decorated_function.profiling_on is False return decorated_function.original_function(*args, **kwargs) decorated_function = decorator_tools.decorator(inner, function) decorated_function.original_function = function decorated_function.profiling_on = None decorated_function.condition = condition decorated_function.off_after = off_after decorated_function.profile_handler = \ profile_handling.get_profile_handler(profile_handler) return decorated_function
def factory(cls, callable): ''' Decorator to make generators return a `LazyTuple`. Example: @LazyTuple.factory def my_generator(): yield 'hello'; yield 'world'; yield 'have'; yield 'fun' This works on any function that returns an iterator. todo: Make it work on iterator classes. ''' def inner(function, *args, **kwargs): return cls(callable(*args, **kwargs)) return decorator_tools.decorator(inner, callable)
def factory(cls, definitely_infinite=False): ''' Decorator to make generators return a `LazyTuple`. Example: @LazyTuple.factory() def my_generator(): yield from ['hello', 'world', 'have', 'fun'] This works on any function that returns an iterator. todo: Make it work on iterator classes. ''' def inner(function, *args, **kwargs): return cls(function(*args, **kwargs), definitely_infinite=definitely_infinite) return decorator_tools.decorator(inner)
def decorator(function): # In case we're being given a function that is already cached: if getattr(function, 'is_cached', False): return function if max_size == infinity: if time_to_keep: sorting_key_function = lambda sleek_call_args: \ cached._cache[sleek_call_args][1] def remove_expired_entries(): almost_cutting_point = \ binary_search.binary_search_by_index( list(cached._cache.keys()), _get_now(), sorting_key_function, rounding=binary_search.LOW ) if almost_cutting_point is not None: cutting_point = almost_cutting_point + 1 for key in cached._cache.keys()[:cutting_point]: del cached._cache[key] @misc_tools.set_attributes(_cache=OrderedDict()) def cached(function, *args, **kwargs): remove_expired_entries() sleek_call_args = \ SleekCallArgs(cached._cache, function, *args, **kwargs) try: return cached._cache[sleek_call_args][0] except KeyError: value = function(*args, **kwargs) cached._cache[sleek_call_args] = (value, _get_now() + time_to_keep) cached._cache.sort(key=sorting_key_function) return value else: # not time_to_keep @misc_tools.set_attributes(_cache={}) def cached(function, *args, **kwargs): sleek_call_args = \ SleekCallArgs(cached._cache, function, *args, **kwargs) try: return cached._cache[sleek_call_args] except KeyError: cached._cache[sleek_call_args] = value = \ function(*args, **kwargs) return value else: # max_size < infinity @misc_tools.set_attributes(_cache=OrderedDict()) def cached(function, *args, **kwargs): sleek_call_args = \ SleekCallArgs(cached._cache, function, *args, **kwargs) try: result = cached._cache[sleek_call_args] cached._cache.move_to_end(sleek_call_args) return result except KeyError: cached._cache[sleek_call_args] = value = \ function(*args, **kwargs) if len(cached._cache) > max_size: cached._cache.popitem(last=False) return value result = decorator_tools.decorator(cached, function) def cache_clear(key=CLEAR_ENTIRE_CACHE): if key is CLEAR_ENTIRE_CACHE: cached._cache.clear() else: try: del cached._cache[key] except KeyError: pass result.cache_clear = cache_clear result.is_cached = True return result
def decorator(function): # In case we're being given a function that is already cached: if getattr(function, 'is_cached', False): return function if max_size == infinity: if time_to_keep: cache_dict = OrderedDict() sorting_key_function = lambda sleek_call_args: \ cached._cache[sleek_call_args][1] def remove_expired_entries(): almost_cutting_point = \ binary_search.binary_search_by_index( list(cached._cache.keys()), sorting_key_function, _get_now(), rounding=binary_search.LOW ) if almost_cutting_point is not None: cutting_point = almost_cutting_point + 1 for key in list(cached._cache.keys())[:cutting_point]: del cached._cache[key] def cached(function, *args, **kwargs): remove_expired_entries() sleek_call_args = \ SleekCallArgs(cache_dict, function, *args, **kwargs) try: return cached._cache[sleek_call_args][0] except KeyError: value = function(*args, **kwargs) cached._cache[sleek_call_args] = ( value, _get_now() + time_to_keep ) cached._cache.sort(key=sorting_key_function) return value else: # not time_to_keep cache_dict = {} def cached(function, *args, **kwargs): sleek_call_args = \ SleekCallArgs(cache_dict, function, *args, **kwargs) try: return cached._cache[sleek_call_args] except KeyError: cached._cache[sleek_call_args] = value = \ function(*args, **kwargs) return value else: # max_size < infinity cache_dict = OrderedDict() def cached(function, *args, **kwargs): sleek_call_args = \ SleekCallArgs(cache_dict, function, *args, **kwargs) try: result = cached._cache[sleek_call_args] cached._cache.move_to_end(sleek_call_args) return result except KeyError: cached._cache[sleek_call_args] = value = \ function(*args, **kwargs) if len(cached._cache) > max_size: cached._cache.popitem(last=False) return value cached._cache = cache_dict result = decorator_tools.decorator(cached, function) def cache_clear(key=CLEAR_ENTIRE_CACHE): if key is CLEAR_ENTIRE_CACHE: cached._cache.clear() else: try: del cached._cache[key] except KeyError: pass result.cache_clear = cache_clear result.is_cached = True return result