summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/decorator.py37
-rw-r--r--src/tests/documentation.py19
2 files changed, 33 insertions, 23 deletions
diff --git a/src/decorator.py b/src/decorator.py
index bab05b4..2dd91ec 100644
--- a/src/decorator.py
+++ b/src/decorator.py
@@ -32,7 +32,6 @@ Decorator module, see http://pypi.python.org/pypi/decorator
for the documentation.
"""
from __future__ import print_function
-from abc import ABCMeta
__version__ = '4.0.0'
@@ -40,9 +39,16 @@ import re
import sys
import inspect
import itertools
+import collections
if sys.version >= '3':
- from inspect import getfullargspec
+ # getargspec has been deprecated in Python 3.5
+ ArgSpec = collections.namedtuple(
+ 'ArgSpec', 'args varargs varkw defaults')
+
+ def getargspec(f):
+ spec = inspect.getfullargspec(f)
+ return ArgSpec(spec.args, spec.varargs, spec.varkw, spec.defaults)
def get_init(cls):
return cls.__init__
@@ -61,9 +67,12 @@ else:
yield self.varkw
yield self.defaults
+ getargspec = inspect.getargspec
+
def get_init(cls):
return cls.__init__.__func__
+
DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(')
@@ -85,7 +94,7 @@ class FunctionMaker(object):
self.doc = func.__doc__
self.module = func.__module__
if inspect.isfunction(func):
- argspec = getfullargspec(func)
+ argspec = inspect.getfullargspec(func)
self.annotations = getattr(func, '__annotations__', {})
for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',
'kwonlydefaults'):
@@ -223,7 +232,7 @@ def decorator(caller, _func=None):
callerfunc = get_init(caller)
doc = 'decorator(%s) converts functions/generators into ' \
'factories of %s objects' % (caller.__name__, caller.__name__)
- fun = getfullargspec(callerfunc).args[1] # second arg
+ fun = inspect.getfullargspec(callerfunc).args[1] # second arg
elif inspect.isfunction(caller):
if caller.__name__ == '<lambda>':
name = '_lambda_'
@@ -231,12 +240,12 @@ def decorator(caller, _func=None):
name = caller.__name__
callerfunc = caller
doc = caller.__doc__
- fun = getfullargspec(callerfunc).args[0] # first arg
+ fun = inspect.getfullargspec(callerfunc).args[0] # first arg
else: # assume caller is an object with a __call__ method
name = caller.__class__.__name__.lower()
callerfunc = caller.__call__.__func__
doc = caller.__call__.__doc__
- fun = getfullargspec(callerfunc).args[1] # second arg
+ fun = inspect.getfullargspec(callerfunc).args[1] # second arg
evaldict = callerfunc.__globals__.copy()
evaldict['_call_'] = caller
evaldict['_decorate_'] = decorate
@@ -262,7 +271,7 @@ class ContextManager(_GeneratorContextManager):
func, "with _self_: return _func_(%(shortsignature)s)",
dict(_self_=self, _func_=func), __wrapped__=func)
-init = getfullargspec(_GeneratorContextManager.__init__)
+init = inspect.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):
@@ -316,7 +325,7 @@ def dispatch_on(*dispatch_args):
"""Decorator turning a function into a generic function"""
# first check the dispatch arguments
- argset = set(getfullargspec(func).args)
+ argset = set(inspect.getfullargspec(func).args)
if not set(dispatch_args) <= argset:
raise NameError('Unknown dispatch arguments %s' % dispatch_str)
@@ -324,7 +333,7 @@ def dispatch_on(*dispatch_args):
def vancestors(*types):
"""
- Get a list of lists of virtual ancestors for the given types
+ Get a list of sets of virtual ancestors for the given types
"""
check(types)
ras = [[] for _ in range(len(dispatch_args))]
@@ -334,9 +343,9 @@ def dispatch_on(*dispatch_args):
append(type_, ra)
return [set(ra) for ra in ras]
- def mros(*types):
+ def vmros(*types):
"""
- Get a list of MROs, one for each type
+ Get a list of virtual MROs, one for each type
"""
check(types)
lists = []
@@ -358,7 +367,7 @@ def dispatch_on(*dispatch_args):
check(types)
def dec(f):
- n_args = len(getfullargspec(f).args)
+ n_args = len(inspect.getfullargspec(f).args)
if n_args < len(dispatch_args):
raise TypeError(
'%s has not enough arguments (got %d, expected %d)' %
@@ -376,7 +385,7 @@ def dispatch_on(*dispatch_args):
pass
else:
return f(*args, **kw)
- for types_ in itertools.product(*mros(*types)):
+ for types_ in itertools.product(*vmros(*types)):
f = typemap.get(types_)
if f is not None:
return f(*args, **kw)
@@ -387,7 +396,7 @@ def dispatch_on(*dispatch_args):
return FunctionMaker.create(
func, 'return _f_(%s, %%(shortsignature)s)' % dispatch_str,
dict(_f_=_dispatch), register=register, default=func,
- typemap=typemap, vancestors=vancestors, mros=mros,
+ typemap=typemap, vancestors=vancestors, vmros=vmros,
__wrapped__=func)
gen_func_dec.__name__ = 'dispatch_on' + dispatch_str
diff --git a/src/tests/documentation.py b/src/tests/documentation.py
index e0bc070..89dd6ec 100644
--- a/src/tests/documentation.py
+++ b/src/tests/documentation.py
@@ -166,9 +166,9 @@ keyword arguments:
.. code-block:: python
- >>> from inspect import getargspec
+ >>> from decorator import getargspec
>>> print(getargspec(f1))
- ArgSpec(args=[], varargs='args', keywords='kw', defaults=None)
+ ArgSpec(args=[], varargs='args', varkw='kw', defaults=None)
This means that introspection tools such as *pydoc* will give
wrong informations about the signature of ``f1``, unless you are
@@ -240,7 +240,7 @@ The signature of ``heavy_computation`` is the one you would expect:
.. code-block:: python
>>> print(getargspec(heavy_computation))
- ArgSpec(args=[], varargs=None, keywords=None, defaults=None)
+ ArgSpec(args=[], varargs=None, varkw=None, defaults=None)
A ``trace`` decorator
------------------------------------------------------
@@ -273,7 +273,7 @@ and it that it has the correct signature:
.. code-block:: python
>>> print(getargspec(f1))
- ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
+ ArgSpec(args=['x'], varargs=None, varkw=None, defaults=None)
The same decorator works with functions of any signature:
@@ -287,7 +287,7 @@ The same decorator works with functions of any signature:
calling f with args (0, 3, 2), {}
>>> print(getargspec(f))
- ArgSpec(args=['x', 'y', 'z'], varargs='args', keywords='kw', defaults=(1, 2))
+ ArgSpec(args=['x', 'y', 'z'], varargs='args', varkw='kw', defaults=(1, 2))
$FUNCTION_ANNOTATIONS
@@ -546,9 +546,8 @@ a tuple of defaults:
>>> f1 = FunctionMaker.create(
... 'f1(a, b)', 'f(a, b)', dict(f=f), addsource=True, defaults=(None,))
- >>> import inspect
- >>> print(inspect.getargspec(f1))
- ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=(None,))
+ >>> print(getargspec(f1))
+ ArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(None,))
Getting the source code
@@ -569,6 +568,7 @@ $$example
.. code-block:: python
+ >>> import inspect
>>> print(inspect.getsource(example))
def wrapper(*args, **kw):
return func(*args, **kw)
@@ -1045,7 +1045,8 @@ annotations. Here is an example:
... pass
In order to introspect functions with annotations, one needs the
-utility ``inspect.getfullargspec``, new in Python 3:
+utility ``inspect.getfullargspec``, new in Python 3 (and deprecated
+in favor of ``inspect.signature`` in Python 3.5):
.. code-block:: python