summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2012-04-23 16:49:01 +0200
committerMichele Simionato <michele.simionato@gmail.com>2012-04-23 16:49:01 +0200
commita826b9a2f7e40a7948da1b351d169fef87625bbc (patch)
treeab9083b81bb6ceee6cd6f32e26f3373d2a6ef0c8
parent713fb4b495355cbb09877e872c5655f7dc997cc3 (diff)
parentc9d029e4d9ba32b09462a635413fe4d80a06c9a1 (diff)
downloadmicheles-a826b9a2f7e40a7948da1b351d169fef87625bbc.tar.gz
Release 3.3.3
-rw-r--r--decorator/CHANGES.txt2
-rw-r--r--decorator/documentation3.py28
-rw-r--r--decorator/src/decorator.py34
3 files changed, 37 insertions, 27 deletions
diff --git a/decorator/CHANGES.txt b/decorator/CHANGES.txt
index cbc1913..a319a94 100644
--- a/decorator/CHANGES.txt
+++ b/decorator/CHANGES.txt
@@ -1,6 +1,8 @@
HISTORY
----------
+3.3.3 Fixed a bug with kwonlyargs for Python 3, submitted by Chris
+ Ellison (23/04/2012)
3.3.2 Fixed a bug with __kwdefaults__ for Python 3, submitted by Chris
Ellison (01/09/2011)
3.3.1 Fixed a doctest broken for Python 3.2, as noted by
diff --git a/decorator/documentation3.py b/decorator/documentation3.py
index 8524c24..07a4e40 100644
--- a/decorator/documentation3.py
+++ b/decorator/documentation3.py
@@ -269,8 +269,6 @@ utility ``inspect.getfullargspec``, new in Python 3:
>>> argspec.kwonlyargs
[]
>>> argspec.kwonlydefaults
- >>> sorted(argspec.annotations.items())
- [('args', 'varargs'), ('kw', 'kwargs'), ('x', 'the first argument'), ('y', 'default argument')]
You can also check that the ``__annotations__`` dictionary is preserved:
@@ -279,16 +277,9 @@ You can also check that the ``__annotations__`` dictionary is preserved:
>>> f.__annotations__ == f.__wrapped__.__annotations__
True
-The two dictionaries are different objects, though
-
-.. code-block:: python
-
- >>> id(f.__annotations__) != id(f.__wrapped__.__annotations__)
- True
-
-since internally the decorator module creates an entirely new dictionary
-(it is not simply attaching the ``__annotations__`` attribute to the new
-function).
+Depending on the version of the decorator module, the two dictionaries can
+be the same object or not: you cannot rely on object identity, but you can
+rely on the content being the same.
``decorator`` is a decorator
---------------------------------------------
@@ -691,7 +682,7 @@ would require to change the CPython implementation of functions and
add an hook to make it possible to change their signature directly.
That could happen in future versions of Python (see PEP 362_) and
then the decorator module would become obsolete. However, at present,
-even in Python 3.1 it is impossible to change the function signature
+even in Python 3.2 it is impossible to change the function signature
directly, therefore the ``decorator`` module is still useful.
Actually, this is one of the main reasons why I keep maintaining
the module and releasing new versions.
@@ -1063,5 +1054,16 @@ def test_kwonlydefaults():
{'kwonly': 2}
"""
+def test_kwonlyargs():
+ """
+ >>> @trace
+ ... def func(a, b, *args, y=2, z=3, **kwargs):
+ ... return y, z
+ ...
+ >>> func('a', 'b', 'c', 'd', 'e', y='y', z='z', cat='dog')
+ calling func with args ('a', 'b', 'c', 'd', 'e'), {'y': 'y', 'z': 'z', 'cat': 'dog'}
+ ('y', 'z')
+ """
+
if __name__ == '__main__':
import doctest; doctest.testmod()
diff --git a/decorator/src/decorator.py b/decorator/src/decorator.py
index e7b3369..3dbbdd4 100644
--- a/decorator/src/decorator.py
+++ b/decorator/src/decorator.py
@@ -32,7 +32,7 @@ Decorator module, see http://pypi.python.org/pypi/decorator
for the documentation.
"""
-__version__ = '3.3.2'
+__version__ = '3.3.3'
__all__ = ["decorator", "FunctionMaker", "partial"]
@@ -62,7 +62,6 @@ else:
inspect.getargspec(f)
self.kwonlyargs = []
self.kwonlydefaults = None
- self.annotations = getattr(f, '__annotations__', {})
def __iter__(self):
yield self.args
yield self.varargs
@@ -90,22 +89,28 @@ class FunctionMaker(object):
self.module = func.__module__
if inspect.isfunction(func):
argspec = getfullargspec(func)
+ self.annotations = getattr(func, '__annotations__', {})
for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',
- 'kwonlydefaults', 'annotations'):
+ 'kwonlydefaults'):
setattr(self, a, getattr(argspec, a))
for i, arg in enumerate(self.args):
setattr(self, 'arg%d' % i, arg)
- self.signature = inspect.formatargspec(
- formatvalue=lambda val: "", *argspec)[1:-1]
- allargs = list(self.args)
- if self.varargs:
- allargs.append('*' + self.varargs)
- if self.varkw:
- allargs.append('**' + self.varkw)
- try:
- self.shortsignature = ', '.join(allargs)
- except TypeError: # exotic signature, valid only in Python 2.X
- self.shortsignature = self.signature
+ if sys.version < '3': # easy way
+ self.shortsignature = self.signature = \
+ inspect.formatargspec(
+ formatvalue=lambda val: "", *argspec)[1:-1]
+ else: # Python 3 way
+ self.signature = self.shortsignature = ', '.join(self.args)
+ if self.varargs:
+ self.signature += ', *' + self.varargs
+ self.shortsignature += ', *' + self.varargs
+ if self.kwonlyargs:
+ for a in self.kwonlyargs:
+ self.signature += ', %s=None' % a
+ self.shortsignature += ', %s=%s' % (a, a)
+ if self.varkw:
+ self.signature += ', **' + self.varkw
+ self.shortsignature += ', **' + self.varkw
self.dict = func.__dict__.copy()
# func=None happens when decorating a caller
if name:
@@ -132,6 +137,7 @@ class FunctionMaker(object):
func.__dict__ = getattr(self, 'dict', {})
func.func_defaults = getattr(self, 'defaults', ())
func.__kwdefaults__ = getattr(self, 'kwonlydefaults', None)
+ func.__annotations__ = getattr(self, 'annotations', None)
callermodule = sys._getframe(3).f_globals.get('__name__', '?')
func.__module__ = getattr(self, 'module', callermodule)
func.__dict__.update(kw)