mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-08-19 12:59:42 -07:00
Update jaraco.functools-3.3.0
This commit is contained in:
parent
979c70f129
commit
b3ae6bd695
2 changed files with 400 additions and 362 deletions
|
@ -1 +0,0 @@
|
||||||
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
|
|
|
@ -1,30 +1,11 @@
|
||||||
from __future__ import (
|
|
||||||
absolute_import, unicode_literals, print_function, division,
|
|
||||||
)
|
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import time
|
import time
|
||||||
import warnings
|
|
||||||
import inspect
|
import inspect
|
||||||
import collections
|
import collections
|
||||||
from itertools import count
|
import types
|
||||||
|
import itertools
|
||||||
|
|
||||||
__metaclass__ = type
|
import more_itertools
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
from functools import lru_cache
|
|
||||||
except ImportError:
|
|
||||||
try:
|
|
||||||
from backports.functools_lru_cache import lru_cache
|
|
||||||
except ImportError:
|
|
||||||
try:
|
|
||||||
from functools32 import lru_cache
|
|
||||||
except ImportError:
|
|
||||||
warnings.warn("No lru_cache available")
|
|
||||||
|
|
||||||
|
|
||||||
import more_itertools.recipes
|
|
||||||
|
|
||||||
|
|
||||||
def compose(*funcs):
|
def compose(*funcs):
|
||||||
|
@ -32,9 +13,8 @@ def compose(*funcs):
|
||||||
Compose any number of unary functions into a single unary function.
|
Compose any number of unary functions into a single unary function.
|
||||||
|
|
||||||
>>> import textwrap
|
>>> import textwrap
|
||||||
>>> from six import text_type
|
>>> stripped = str.strip(textwrap.dedent(compose.__doc__))
|
||||||
>>> stripped = text_type.strip(textwrap.dedent(compose.__doc__))
|
>>> compose(str.strip, textwrap.dedent)(compose.__doc__) == stripped
|
||||||
>>> compose(text_type.strip, textwrap.dedent)(compose.__doc__) == stripped
|
|
||||||
True
|
True
|
||||||
|
|
||||||
Compose also allows the innermost function to take arbitrary arguments.
|
Compose also allows the innermost function to take arbitrary arguments.
|
||||||
|
@ -47,6 +27,7 @@ def compose(*funcs):
|
||||||
|
|
||||||
def compose_two(f1, f2):
|
def compose_two(f1, f2):
|
||||||
return lambda *args, **kwargs: f1(f2(*args, **kwargs))
|
return lambda *args, **kwargs: f1(f2(*args, **kwargs))
|
||||||
|
|
||||||
return functools.reduce(compose_two, funcs)
|
return functools.reduce(compose_two, funcs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,9 +41,11 @@ def method_caller(method_name, *args, **kwargs):
|
||||||
>>> lower('MyString')
|
>>> lower('MyString')
|
||||||
'mystring'
|
'mystring'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def call_method(target):
|
def call_method(target):
|
||||||
func = getattr(target, method_name)
|
func = getattr(target, method_name)
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return call_method
|
return call_method
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,11 +80,13 @@ def once(func):
|
||||||
>>> add_three(0)
|
>>> add_three(0)
|
||||||
0
|
0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
if not hasattr(wrapper, 'saved_result'):
|
if not hasattr(wrapper, 'saved_result'):
|
||||||
wrapper.saved_result = func(*args, **kwargs)
|
wrapper.saved_result = func(*args, **kwargs)
|
||||||
return wrapper.saved_result
|
return wrapper.saved_result
|
||||||
|
|
||||||
wrapper.reset = lambda: vars(wrapper).__delitem__('saved_result')
|
wrapper.reset = lambda: vars(wrapper).__delitem__('saved_result')
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
@ -153,9 +138,14 @@ def method_cache(method, cache_wrapper=None):
|
||||||
|
|
||||||
>>> a.method.cache_clear()
|
>>> a.method.cache_clear()
|
||||||
|
|
||||||
|
Same for a method that hasn't yet been called.
|
||||||
|
|
||||||
|
>>> c = MyClass()
|
||||||
|
>>> c.method.cache_clear()
|
||||||
|
|
||||||
Another cache wrapper may be supplied:
|
Another cache wrapper may be supplied:
|
||||||
|
|
||||||
>>> cache = lru_cache(maxsize=2)
|
>>> cache = functools.lru_cache(maxsize=2)
|
||||||
>>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache)
|
>>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache)
|
||||||
>>> a = MyClass()
|
>>> a = MyClass()
|
||||||
>>> a.method2()
|
>>> a.method2()
|
||||||
|
@ -168,15 +158,18 @@ def method_cache(method, cache_wrapper=None):
|
||||||
http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/
|
http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/
|
||||||
for another implementation and additional justification.
|
for another implementation and additional justification.
|
||||||
"""
|
"""
|
||||||
cache_wrapper = cache_wrapper or lru_cache()
|
cache_wrapper = cache_wrapper or functools.lru_cache()
|
||||||
|
|
||||||
def wrapper(self, *args, **kwargs):
|
def wrapper(self, *args, **kwargs):
|
||||||
# it's the first call, replace the method with a cached, bound method
|
# it's the first call, replace the method with a cached, bound method
|
||||||
bound_method = functools.partial(method, self)
|
bound_method = types.MethodType(method, self)
|
||||||
cached_method = cache_wrapper(bound_method)
|
cached_method = cache_wrapper(bound_method)
|
||||||
setattr(self, method.__name__, cached_method)
|
setattr(self, method.__name__, cached_method)
|
||||||
return cached_method(*args, **kwargs)
|
return cached_method(*args, **kwargs)
|
||||||
|
|
||||||
|
# Support cache clear even before cache has been created.
|
||||||
|
wrapper.cache_clear = lambda: None
|
||||||
|
|
||||||
return _special_method_cache(method, cache_wrapper) or wrapper
|
return _special_method_cache(method, cache_wrapper) or wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,7 +193,7 @@ def _special_method_cache(method, cache_wrapper):
|
||||||
|
|
||||||
def proxy(self, *args, **kwargs):
|
def proxy(self, *args, **kwargs):
|
||||||
if wrapper_name not in vars(self):
|
if wrapper_name not in vars(self):
|
||||||
bound = functools.partial(method, self)
|
bound = types.MethodType(method, self)
|
||||||
cache = cache_wrapper(bound)
|
cache = cache_wrapper(bound)
|
||||||
setattr(self, wrapper_name, cache)
|
setattr(self, wrapper_name, cache)
|
||||||
else:
|
else:
|
||||||
|
@ -221,8 +214,10 @@ def apply(transform):
|
||||||
>>> list(get_numbers(4))
|
>>> list(get_numbers(4))
|
||||||
[6, 5, 4]
|
[6, 5, 4]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrap(func):
|
def wrap(func):
|
||||||
return compose(transform, func)
|
return compose(transform, func)
|
||||||
|
|
||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,13 +234,16 @@ def result_invoke(action):
|
||||||
>>> x = add_two(2, 3)
|
>>> x = add_two(2, 3)
|
||||||
5
|
5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrap(func):
|
def wrap(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
result = func(*args, **kwargs)
|
result = func(*args, **kwargs)
|
||||||
action(result)
|
action(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,6 +271,7 @@ class Throttler:
|
||||||
"""
|
"""
|
||||||
Rate-limit a function (or other callable)
|
Rate-limit a function (or other callable)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, func, max_rate=float('Inf')):
|
def __init__(self, func, max_rate=float('Inf')):
|
||||||
if isinstance(func, Throttler):
|
if isinstance(func, Throttler):
|
||||||
func = func.func
|
func = func.func
|
||||||
|
@ -304,9 +303,11 @@ def first_invoke(func1, func2):
|
||||||
any parameters (for its side-effect) and then invoke func2
|
any parameters (for its side-effect) and then invoke func2
|
||||||
with whatever parameters were passed, returning its result.
|
with whatever parameters were passed, returning its result.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
func1()
|
func1()
|
||||||
return func2(*args, **kwargs)
|
return func2(*args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -317,7 +318,7 @@ def retry_call(func, cleanup=lambda: None, retries=0, trap=()):
|
||||||
exception. On the final attempt, allow any exceptions
|
exception. On the final attempt, allow any exceptions
|
||||||
to propagate.
|
to propagate.
|
||||||
"""
|
"""
|
||||||
attempts = count() if retries == float('inf') else range(retries)
|
attempts = itertools.count() if retries == float('inf') else range(retries)
|
||||||
for attempt in attempts:
|
for attempt in attempts:
|
||||||
try:
|
try:
|
||||||
return func()
|
return func()
|
||||||
|
@ -341,12 +342,15 @@ def retry(*r_args, **r_kwargs):
|
||||||
>>> my_func.__doc__
|
>>> my_func.__doc__
|
||||||
'this is my funk'
|
'this is my funk'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorate(func):
|
def decorate(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(*f_args, **f_kwargs):
|
def wrapper(*f_args, **f_kwargs):
|
||||||
bound = functools.partial(func, *f_args, **f_kwargs)
|
bound = functools.partial(func, *f_args, **f_kwargs)
|
||||||
return retry_call(bound, *r_args, **r_kwargs)
|
return retry_call(bound, *r_args, **r_kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return decorate
|
return decorate
|
||||||
|
|
||||||
|
|
||||||
|
@ -362,7 +366,7 @@ def print_yielded(func):
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
print_all = functools.partial(map, print)
|
print_all = functools.partial(map, print)
|
||||||
print_results = compose(more_itertools.recipes.consume, print_all, func)
|
print_results = compose(more_itertools.consume, print_all, func)
|
||||||
return functools.wraps(func)(print_results)
|
return functools.wraps(func)(print_results)
|
||||||
|
|
||||||
|
|
||||||
|
@ -375,10 +379,12 @@ def pass_none(func):
|
||||||
text
|
text
|
||||||
>>> print_text(None)
|
>>> print_text(None)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(param, *args, **kwargs):
|
def wrapper(param, *args, **kwargs):
|
||||||
if param is not None:
|
if param is not None:
|
||||||
return func(param, *args, **kwargs)
|
return func(param, *args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -408,17 +414,9 @@ def assign_params(func, namespace):
|
||||||
>>> assign_params(Handler().meth, dict(arg='crystal', foo='clear'))()
|
>>> assign_params(Handler().meth, dict(arg='crystal', foo='clear'))()
|
||||||
crystal
|
crystal
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
sig = inspect.signature(func)
|
sig = inspect.signature(func)
|
||||||
params = sig.parameters.keys()
|
params = sig.parameters.keys()
|
||||||
except AttributeError:
|
call_ns = {k: namespace[k] for k in params if k in namespace}
|
||||||
spec = inspect.getargspec(func)
|
|
||||||
params = spec.args
|
|
||||||
call_ns = {
|
|
||||||
k: namespace[k]
|
|
||||||
for k in params
|
|
||||||
if k in namespace
|
|
||||||
}
|
|
||||||
return functools.partial(func, **call_ns)
|
return functools.partial(func, **call_ns)
|
||||||
|
|
||||||
|
|
||||||
|
@ -464,4 +462,45 @@ def save_method_args(method):
|
||||||
attr = args_and_kwargs(args, kwargs)
|
attr = args_and_kwargs(args, kwargs)
|
||||||
setattr(self, attr_name, attr)
|
setattr(self, attr_name, attr)
|
||||||
return method(self, *args, **kwargs)
|
return method(self, *args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def except_(*exceptions, replace=None, use=None):
|
||||||
|
"""
|
||||||
|
Replace the indicated exceptions, if raised, with the indicated
|
||||||
|
literal replacement or evaluated expression (if present).
|
||||||
|
|
||||||
|
>>> safe_int = except_(ValueError)(int)
|
||||||
|
>>> safe_int('five')
|
||||||
|
>>> safe_int('5')
|
||||||
|
5
|
||||||
|
|
||||||
|
Specify a literal replacement with ``replace``.
|
||||||
|
|
||||||
|
>>> safe_int_r = except_(ValueError, replace=0)(int)
|
||||||
|
>>> safe_int_r('five')
|
||||||
|
0
|
||||||
|
|
||||||
|
Provide an expression to ``use`` to pass through particular parameters.
|
||||||
|
|
||||||
|
>>> safe_int_pt = except_(ValueError, use='args[0]')(int)
|
||||||
|
>>> safe_int_pt('five')
|
||||||
|
'five'
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorate(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except exceptions:
|
||||||
|
try:
|
||||||
|
return eval(use)
|
||||||
|
except TypeError:
|
||||||
|
return replace
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return decorate
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue