예제 #1
0
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
예제 #2
0
    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)
예제 #3
0
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
예제 #4
0
 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)
예제 #5
0
    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
예제 #6
0
 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)
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
0
 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)
예제 #10
0
    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
예제 #11
0
    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
 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)