mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-08-19 04:49:36 -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 time
|
||||
import warnings
|
||||
import inspect
|
||||
import collections
|
||||
from itertools import count
|
||||
import types
|
||||
import itertools
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
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
|
||||
import more_itertools
|
||||
|
||||
|
||||
def compose(*funcs):
|
||||
|
@ -32,9 +13,8 @@ def compose(*funcs):
|
|||
Compose any number of unary functions into a single unary function.
|
||||
|
||||
>>> import textwrap
|
||||
>>> from six import text_type
|
||||
>>> stripped = text_type.strip(textwrap.dedent(compose.__doc__))
|
||||
>>> compose(text_type.strip, textwrap.dedent)(compose.__doc__) == stripped
|
||||
>>> stripped = str.strip(textwrap.dedent(compose.__doc__))
|
||||
>>> compose(str.strip, textwrap.dedent)(compose.__doc__) == stripped
|
||||
True
|
||||
|
||||
Compose also allows the innermost function to take arbitrary arguments.
|
||||
|
@ -47,6 +27,7 @@ def compose(*funcs):
|
|||
|
||||
def compose_two(f1, f2):
|
||||
return lambda *args, **kwargs: f1(f2(*args, **kwargs))
|
||||
|
||||
return functools.reduce(compose_two, funcs)
|
||||
|
||||
|
||||
|
@ -60,9 +41,11 @@ def method_caller(method_name, *args, **kwargs):
|
|||
>>> lower('MyString')
|
||||
'mystring'
|
||||
"""
|
||||
|
||||
def call_method(target):
|
||||
func = getattr(target, method_name)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return call_method
|
||||
|
||||
|
||||
|
@ -97,11 +80,13 @@ def once(func):
|
|||
>>> add_three(0)
|
||||
0
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
if not hasattr(wrapper, 'saved_result'):
|
||||
wrapper.saved_result = func(*args, **kwargs)
|
||||
return wrapper.saved_result
|
||||
|
||||
wrapper.reset = lambda: vars(wrapper).__delitem__('saved_result')
|
||||
return wrapper
|
||||
|
||||
|
@ -153,9 +138,14 @@ def method_cache(method, cache_wrapper=None):
|
|||
|
||||
>>> 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:
|
||||
|
||||
>>> cache = lru_cache(maxsize=2)
|
||||
>>> cache = functools.lru_cache(maxsize=2)
|
||||
>>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache)
|
||||
>>> a = MyClass()
|
||||
>>> 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/
|
||||
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):
|
||||
# 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)
|
||||
setattr(self, method.__name__, cached_method)
|
||||
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
|
||||
|
||||
|
||||
|
@ -200,7 +193,7 @@ def _special_method_cache(method, cache_wrapper):
|
|||
|
||||
def proxy(self, *args, **kwargs):
|
||||
if wrapper_name not in vars(self):
|
||||
bound = functools.partial(method, self)
|
||||
bound = types.MethodType(method, self)
|
||||
cache = cache_wrapper(bound)
|
||||
setattr(self, wrapper_name, cache)
|
||||
else:
|
||||
|
@ -221,8 +214,10 @@ def apply(transform):
|
|||
>>> list(get_numbers(4))
|
||||
[6, 5, 4]
|
||||
"""
|
||||
|
||||
def wrap(func):
|
||||
return compose(transform, func)
|
||||
|
||||
return wrap
|
||||
|
||||
|
||||
|
@ -239,13 +234,16 @@ def result_invoke(action):
|
|||
>>> x = add_two(2, 3)
|
||||
5
|
||||
"""
|
||||
|
||||
def wrap(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
result = func(*args, **kwargs)
|
||||
action(result)
|
||||
return result
|
||||
|
||||
return wrapper
|
||||
|
||||
return wrap
|
||||
|
||||
|
||||
|
@ -273,6 +271,7 @@ class Throttler:
|
|||
"""
|
||||
Rate-limit a function (or other callable)
|
||||
"""
|
||||
|
||||
def __init__(self, func, max_rate=float('Inf')):
|
||||
if isinstance(func, Throttler):
|
||||
func = func.func
|
||||
|
@ -304,9 +303,11 @@ def first_invoke(func1, func2):
|
|||
any parameters (for its side-effect) and then invoke func2
|
||||
with whatever parameters were passed, returning its result.
|
||||
"""
|
||||
|
||||
def wrapper(*args, **kwargs):
|
||||
func1()
|
||||
return func2(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
|
@ -317,7 +318,7 @@ def retry_call(func, cleanup=lambda: None, retries=0, trap=()):
|
|||
exception. On the final attempt, allow any exceptions
|
||||
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:
|
||||
try:
|
||||
return func()
|
||||
|
@ -341,12 +342,15 @@ def retry(*r_args, **r_kwargs):
|
|||
>>> my_func.__doc__
|
||||
'this is my funk'
|
||||
"""
|
||||
|
||||
def decorate(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*f_args, **f_kwargs):
|
||||
bound = functools.partial(func, *f_args, **f_kwargs)
|
||||
return retry_call(bound, *r_args, **r_kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorate
|
||||
|
||||
|
||||
|
@ -362,7 +366,7 @@ def print_yielded(func):
|
|||
None
|
||||
"""
|
||||
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)
|
||||
|
||||
|
||||
|
@ -375,10 +379,12 @@ def pass_none(func):
|
|||
text
|
||||
>>> print_text(None)
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(param, *args, **kwargs):
|
||||
if param is not None:
|
||||
return func(param, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
|
@ -408,17 +414,9 @@ def assign_params(func, namespace):
|
|||
>>> assign_params(Handler().meth, dict(arg='crystal', foo='clear'))()
|
||||
crystal
|
||||
"""
|
||||
try:
|
||||
sig = inspect.signature(func)
|
||||
params = sig.parameters.keys()
|
||||
except AttributeError:
|
||||
spec = inspect.getargspec(func)
|
||||
params = spec.args
|
||||
call_ns = {
|
||||
k: namespace[k]
|
||||
for k in params
|
||||
if k in namespace
|
||||
}
|
||||
call_ns = {k: namespace[k] for k in params if k in namespace}
|
||||
return functools.partial(func, **call_ns)
|
||||
|
||||
|
||||
|
@ -464,4 +462,45 @@ def save_method_args(method):
|
|||
attr = args_and_kwargs(args, kwargs)
|
||||
setattr(self, attr_name, attr)
|
||||
return method(self, *args, **kwargs)
|
||||
|
||||
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