mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2025-08-19 12:59:36 -07:00
Updated decorator to 4.4.2
This commit is contained in:
parent
fb6011f88d
commit
5e3641ac23
1 changed files with 120 additions and 117 deletions
|
@ -1,6 +1,6 @@
|
||||||
# ######################### LICENSE ############################ #
|
# ######################### LICENSE ############################ #
|
||||||
|
|
||||||
# Copyright (c) 2005-2021, Michele Simionato
|
# Copyright (c) 2005-2018, Michele Simionato
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -28,26 +28,55 @@
|
||||||
# DAMAGE.
|
# DAMAGE.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Decorator module, see
|
Decorator module, see http://pypi.python.org/pypi/decorator
|
||||||
https://github.com/micheles/decorator/blob/master/docs/documentation.md
|
|
||||||
for the documentation.
|
for the documentation.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
import operator
|
import operator
|
||||||
import itertools
|
import itertools
|
||||||
from contextlib import _GeneratorContextManager
|
import collections
|
||||||
from inspect import getfullargspec, iscoroutinefunction, isgeneratorfunction
|
|
||||||
|
__version__ = '4.4.2'
|
||||||
|
|
||||||
|
if sys.version_info >= (3,):
|
||||||
|
from inspect import getfullargspec
|
||||||
|
|
||||||
|
def get_init(cls):
|
||||||
|
return cls.__init__
|
||||||
|
else:
|
||||||
|
FullArgSpec = collections.namedtuple(
|
||||||
|
'FullArgSpec', 'args varargs varkw defaults '
|
||||||
|
'kwonlyargs kwonlydefaults annotations')
|
||||||
|
|
||||||
|
def getfullargspec(f):
|
||||||
|
"A quick and dirty replacement for getfullargspec for Python 2.X"
|
||||||
|
return FullArgSpec._make(inspect.getargspec(f) + ([], None, {}))
|
||||||
|
|
||||||
|
def get_init(cls):
|
||||||
|
return cls.__init__.__func__
|
||||||
|
|
||||||
|
try:
|
||||||
|
iscoroutinefunction = inspect.iscoroutinefunction
|
||||||
|
except AttributeError:
|
||||||
|
# let's assume there are no coroutine functions in old Python
|
||||||
|
def iscoroutinefunction(f):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
from inspect import isgeneratorfunction
|
||||||
|
except ImportError:
|
||||||
|
# assume no generator function in old Python versions
|
||||||
|
def isgeneratorfunction(caller):
|
||||||
|
return False
|
||||||
|
|
||||||
__version__ = '5.1.1'
|
|
||||||
|
|
||||||
DEF = re.compile(r'\s*def\s*([_\w][_\w\d]*)\s*\(')
|
DEF = re.compile(r'\s*def\s*([_\w][_\w\d]*)\s*\(')
|
||||||
POS = inspect.Parameter.POSITIONAL_OR_KEYWORD
|
|
||||||
EMPTY = inspect.Parameter.empty
|
|
||||||
|
|
||||||
|
|
||||||
# this is not used anymore in the core, but kept for backward compatibility
|
# basic functionality
|
||||||
class FunctionMaker(object):
|
class FunctionMaker(object):
|
||||||
"""
|
"""
|
||||||
An object with the ability to create functions with a given signature.
|
An object with the ability to create functions with a given signature.
|
||||||
|
@ -71,7 +100,7 @@ class FunctionMaker(object):
|
||||||
self.name = '_lambda_'
|
self.name = '_lambda_'
|
||||||
self.doc = func.__doc__
|
self.doc = func.__doc__
|
||||||
self.module = func.__module__
|
self.module = func.__module__
|
||||||
if inspect.isroutine(func):
|
if inspect.isfunction(func):
|
||||||
argspec = getfullargspec(func)
|
argspec = getfullargspec(func)
|
||||||
self.annotations = getattr(func, '__annotations__', {})
|
self.annotations = getattr(func, '__annotations__', {})
|
||||||
for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',
|
for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',
|
||||||
|
@ -114,9 +143,7 @@ class FunctionMaker(object):
|
||||||
raise TypeError('You are decorating a non function: %s' % func)
|
raise TypeError('You are decorating a non function: %s' % func)
|
||||||
|
|
||||||
def update(self, func, **kw):
|
def update(self, func, **kw):
|
||||||
"""
|
"Update the signature of func with the data in self"
|
||||||
Update the signature of func with the data in self
|
|
||||||
"""
|
|
||||||
func.__name__ = self.name
|
func.__name__ = self.name
|
||||||
func.__doc__ = getattr(self, 'doc', None)
|
func.__doc__ = getattr(self, 'doc', None)
|
||||||
func.__dict__ = getattr(self, 'dict', {})
|
func.__dict__ = getattr(self, 'dict', {})
|
||||||
|
@ -133,9 +160,7 @@ class FunctionMaker(object):
|
||||||
func.__dict__.update(kw)
|
func.__dict__.update(kw)
|
||||||
|
|
||||||
def make(self, src_templ, evaldict=None, addsource=False, **attrs):
|
def make(self, src_templ, evaldict=None, addsource=False, **attrs):
|
||||||
"""
|
"Make a new function from a given template and update the signature"
|
||||||
Make a new function from a given template and update the signature
|
|
||||||
"""
|
|
||||||
src = src_templ % vars(self) # expand name and signature
|
src = src_templ % vars(self) # expand name and signature
|
||||||
evaldict = evaldict or {}
|
evaldict = evaldict or {}
|
||||||
mo = DEF.search(src)
|
mo = DEF.search(src)
|
||||||
|
@ -196,128 +221,106 @@ class FunctionMaker(object):
|
||||||
return self.make(body, evaldict, addsource, **attrs)
|
return self.make(body, evaldict, addsource, **attrs)
|
||||||
|
|
||||||
|
|
||||||
def fix(args, kwargs, sig):
|
def decorate(func, caller, extras=()):
|
||||||
"""
|
"""
|
||||||
Fix args and kwargs to be consistent with the signature
|
decorate(func, caller) decorates a function using a caller.
|
||||||
|
If the caller is a generator function, the resulting function
|
||||||
|
will be a generator function.
|
||||||
"""
|
"""
|
||||||
ba = sig.bind(*args, **kwargs)
|
evaldict = dict(_call_=caller, _func_=func)
|
||||||
ba.apply_defaults() # needed for test_dan_schult
|
es = ''
|
||||||
return ba.args, ba.kwargs
|
for i, extra in enumerate(extras):
|
||||||
|
ex = '_e%d_' % i
|
||||||
|
evaldict[ex] = extra
|
||||||
|
es += ex + ', '
|
||||||
|
|
||||||
|
if '3.5' <= sys.version < '3.6':
|
||||||
def decorate(func, caller, extras=(), kwsyntax=False):
|
# with Python 3.5 isgeneratorfunction returns True for all coroutines
|
||||||
"""
|
# however we know that it is NOT possible to have a generator
|
||||||
Decorates a function/generator/coroutine using a caller.
|
# coroutine in python 3.5: PEP525 was not there yet
|
||||||
If kwsyntax is True calling the decorated functions with keyword
|
generatorcaller = isgeneratorfunction(
|
||||||
syntax will pass the named arguments inside the ``kw`` dictionary,
|
caller) and not iscoroutinefunction(caller)
|
||||||
even if such argument are positional, similarly to what functools.wraps
|
|
||||||
does. By default kwsyntax is False and the the arguments are untouched.
|
|
||||||
"""
|
|
||||||
sig = inspect.signature(func)
|
|
||||||
if iscoroutinefunction(caller):
|
|
||||||
async def fun(*args, **kw):
|
|
||||||
if not kwsyntax:
|
|
||||||
args, kw = fix(args, kw, sig)
|
|
||||||
return await caller(func, *(extras + args), **kw)
|
|
||||||
elif isgeneratorfunction(caller):
|
|
||||||
def fun(*args, **kw):
|
|
||||||
if not kwsyntax:
|
|
||||||
args, kw = fix(args, kw, sig)
|
|
||||||
for res in caller(func, *(extras + args), **kw):
|
|
||||||
yield res
|
|
||||||
else:
|
else:
|
||||||
def fun(*args, **kw):
|
generatorcaller = isgeneratorfunction(caller)
|
||||||
if not kwsyntax:
|
if generatorcaller:
|
||||||
args, kw = fix(args, kw, sig)
|
fun = FunctionMaker.create(
|
||||||
return caller(func, *(extras + args), **kw)
|
func, "for res in _call_(_func_, %s%%(shortsignature)s):\n"
|
||||||
fun.__name__ = func.__name__
|
" yield res" % es, evaldict, __wrapped__=func)
|
||||||
fun.__doc__ = func.__doc__
|
else:
|
||||||
fun.__wrapped__ = func
|
fun = FunctionMaker.create(
|
||||||
fun.__signature__ = sig
|
func, "return _call_(_func_, %s%%(shortsignature)s)" % es,
|
||||||
|
evaldict, __wrapped__=func)
|
||||||
|
if hasattr(func, '__qualname__'):
|
||||||
fun.__qualname__ = func.__qualname__
|
fun.__qualname__ = func.__qualname__
|
||||||
# builtin functions like defaultdict.__setitem__ lack many attributes
|
|
||||||
try:
|
|
||||||
fun.__defaults__ = func.__defaults__
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
fun.__kwdefaults__ = func.__kwdefaults__
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
fun.__annotations__ = func.__annotations__
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
fun.__module__ = func.__module__
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
fun.__dict__.update(func.__dict__)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
return fun
|
return fun
|
||||||
|
|
||||||
|
|
||||||
def decoratorx(caller):
|
def decorator(caller, _func=None):
|
||||||
"""
|
"""decorator(caller) converts a caller function into a decorator"""
|
||||||
A version of "decorator" implemented via "exec" and not via the
|
|
||||||
Signature object. Use this if you are want to preserve the `.__code__`
|
|
||||||
object properties (https://github.com/micheles/decorator/issues/129).
|
|
||||||
"""
|
|
||||||
def dec(func):
|
|
||||||
return FunctionMaker.create(
|
|
||||||
func,
|
|
||||||
"return _call_(_func_, %(shortsignature)s)",
|
|
||||||
dict(_call_=caller, _func_=func),
|
|
||||||
__wrapped__=func, __qualname__=func.__qualname__)
|
|
||||||
return dec
|
|
||||||
|
|
||||||
|
|
||||||
def decorator(caller, _func=None, kwsyntax=False):
|
|
||||||
"""
|
|
||||||
decorator(caller) converts a caller function into a decorator
|
|
||||||
"""
|
|
||||||
if _func is not None: # return a decorated function
|
if _func is not None: # return a decorated function
|
||||||
# this is obsolete behavior; you should use decorate instead
|
# this is obsolete behavior; you should use decorate instead
|
||||||
return decorate(_func, caller, (), kwsyntax)
|
return decorate(_func, caller)
|
||||||
# else return a decorator function
|
# else return a decorator function
|
||||||
sig = inspect.signature(caller)
|
defaultargs, defaults = '', ()
|
||||||
dec_params = [p for p in sig.parameters.values() if p.kind is POS]
|
if inspect.isclass(caller):
|
||||||
|
name = caller.__name__.lower()
|
||||||
def dec(func=None, *args, **kw):
|
doc = 'decorator(%s) converts functions/generators into ' \
|
||||||
na = len(args) + 1
|
'factories of %s objects' % (caller.__name__, caller.__name__)
|
||||||
extras = args + tuple(kw.get(p.name, p.default)
|
elif inspect.isfunction(caller):
|
||||||
for p in dec_params[na:]
|
if caller.__name__ == '<lambda>':
|
||||||
if p.default is not EMPTY)
|
name = '_lambda_'
|
||||||
if func is None:
|
|
||||||
return lambda func: decorate(func, caller, extras, kwsyntax)
|
|
||||||
else:
|
else:
|
||||||
return decorate(func, caller, extras, kwsyntax)
|
name = caller.__name__
|
||||||
dec.__signature__ = sig.replace(parameters=dec_params)
|
doc = caller.__doc__
|
||||||
dec.__name__ = caller.__name__
|
nargs = caller.__code__.co_argcount
|
||||||
dec.__doc__ = caller.__doc__
|
ndefs = len(caller.__defaults__ or ())
|
||||||
dec.__wrapped__ = caller
|
defaultargs = ', '.join(caller.__code__.co_varnames[nargs-ndefs:nargs])
|
||||||
dec.__qualname__ = caller.__qualname__
|
if defaultargs:
|
||||||
dec.__kwdefaults__ = getattr(caller, '__kwdefaults__', None)
|
defaultargs += ','
|
||||||
dec.__dict__.update(caller.__dict__)
|
defaults = caller.__defaults__
|
||||||
|
else: # assume caller is an object with a __call__ method
|
||||||
|
name = caller.__class__.__name__.lower()
|
||||||
|
doc = caller.__call__.__doc__
|
||||||
|
evaldict = dict(_call=caller, _decorate_=decorate)
|
||||||
|
dec = FunctionMaker.create(
|
||||||
|
'%s(func, %s)' % (name, defaultargs),
|
||||||
|
'if func is None: return lambda func: _decorate_(func, _call, (%s))\n'
|
||||||
|
'return _decorate_(func, _call, (%s))' % (defaultargs, defaultargs),
|
||||||
|
evaldict, doc=doc, module=caller.__module__, __wrapped__=caller)
|
||||||
|
if defaults:
|
||||||
|
dec.__defaults__ = (None,) + defaults
|
||||||
return dec
|
return dec
|
||||||
|
|
||||||
|
|
||||||
# ####################### contextmanager ####################### #
|
# ####################### contextmanager ####################### #
|
||||||
|
|
||||||
|
try: # Python >= 3.2
|
||||||
|
from contextlib import _GeneratorContextManager
|
||||||
|
except ImportError: # Python >= 2.5
|
||||||
|
from contextlib import GeneratorContextManager as _GeneratorContextManager
|
||||||
|
|
||||||
|
|
||||||
class ContextManager(_GeneratorContextManager):
|
class ContextManager(_GeneratorContextManager):
|
||||||
def __init__(self, g, *a, **k):
|
|
||||||
_GeneratorContextManager.__init__(self, g, a, k)
|
|
||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
def caller(f, *a, **k):
|
"""Context manager decorator"""
|
||||||
with self.__class__(self.func, *self.args, **self.kwds):
|
return FunctionMaker.create(
|
||||||
return f(*a, **k)
|
func, "with _self_: return _func_(%(shortsignature)s)",
|
||||||
return decorate(func, caller)
|
dict(_self_=self, _func_=func), __wrapped__=func)
|
||||||
|
|
||||||
|
|
||||||
|
init = getfullargspec(_GeneratorContextManager.__init__)
|
||||||
|
n_args = len(init.args)
|
||||||
|
if n_args == 2 and not init.varargs: # (self, genobj) Python 2.7
|
||||||
|
def __init__(self, g, *a, **k):
|
||||||
|
return _GeneratorContextManager.__init__(self, g(*a, **k))
|
||||||
|
ContextManager.__init__ = __init__
|
||||||
|
elif n_args == 2 and init.varargs: # (self, gen, *a, **k) Python 3.4
|
||||||
|
pass
|
||||||
|
elif n_args == 4: # (self, gen, args, kwds) Python 3.5
|
||||||
|
def __init__(self, g, *a, **k):
|
||||||
|
return _GeneratorContextManager.__init__(self, g, a, k)
|
||||||
|
ContextManager.__init__ = __init__
|
||||||
|
|
||||||
_contextmanager = decorator(ContextManager)
|
_contextmanager = decorator(ContextManager)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue