summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2020-03-16 06:43:47 +0100
committerMichele Simionato <michele.simionato@gmail.com>2020-03-16 06:43:47 +0100
commitca5bbdd2efa85cc1cc8859efb90a84306055271b (patch)
treef8a3506bff377b200d2b1633d536205b2e7626a5
parente6de7a108ad9837655c33f80723a9adcf07aa69f (diff)
downloadpython-decorator-git-ca5bbdd2efa85cc1cc8859efb90a84306055271b.tar.gz
Removed exec in decorator
-rw-r--r--src/decorator.py38
1 files changed, 21 insertions, 17 deletions
diff --git a/src/decorator.py b/src/decorator.py
index ce8644c..8a4b62d 100644
--- a/src/decorator.py
+++ b/src/decorator.py
@@ -75,6 +75,7 @@ except ImportError:
DEF = re.compile(r'\s*def\s*([_\w][_\w\d]*)\s*\(')
+POS = inspect.Parameter.POSITIONAL_OR_KEYWORD
# basic functionality
@@ -228,13 +229,6 @@ def decorate(func, caller, extras=()):
If the caller is a generator function, the resulting function
will be a generator function.
"""
- evaldict = dict(_call_=caller, _func_=func)
- es = ''
- for i, extra in enumerate(extras):
- ex = '_e%d_' % i
- evaldict[ex] = extra
- es += ex + ', '
-
if iscoroutinefunction(caller):
async def fun(*args, **kw):
return await caller(func, *(extras + args), **kw)
@@ -245,6 +239,7 @@ def decorate(func, caller, extras=()):
else:
def fun(*args, **kw):
return caller(func, *(extras + args), **kw)
+ fun.__name__ = func.__name__
fun.__signature__ = inspect.signature(func)
fun.__wrapped__ = func
if hasattr(func, '__qualname__'): # >= Python 3.3
@@ -260,7 +255,7 @@ def decorator(caller, _func=None):
# this is obsolete behavior; you should use decorate instead
return decorate(_func, caller)
# else return a decorator function
- defaultargs, defaults = '', ()
+ defaultargs = ''
if inspect.isclass(caller):
name = caller.__name__.lower()
doc = 'decorator(%s) converts functions/generators into ' \
@@ -276,18 +271,27 @@ def decorator(caller, _func=None):
defaultargs = ', '.join(caller.__code__.co_varnames[nargs-ndefs:nargs])
if defaultargs:
defaultargs += ','
- 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
+ sig = inspect.signature(caller)
+ dec_params = [p for p in sig.parameters.values() if p.kind is POS]
+
+ def dec(func=None, *args, **kw):
+ na = len(args) + 1
+ extras = args + tuple(kw.get(p.name, p.default)
+ for p in dec_params[na:])
+ if func is None:
+ return lambda func: decorate(func, caller, extras)
+ else:
+ return decorate(func, caller, extras)
+ dec.__signature__ = sig.replace(parameters=dec_params)
+ dec.__name__ = name
+ dec.__doc__ = doc
+ dec.__wrapped__ = caller
+ if hasattr(caller, '__qualname__'): # >= Python 3.3
+ dec.__qualname__ = caller.__qualname__
+ dec.__dict__.update(caller.__dict__)
return dec