summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2021-09-11 07:25:02 +0200
committerMichele Simionato <michele.simionato@gmail.com>2021-09-11 07:25:02 +0200
commita159961aa32b876d313b8db8f23a1dba0fca4438 (patch)
treefa8877e24f78ea3aac8386ba0c17501797ec92d2
parent7394c953f3c85ff542b8614c53c6e35207ce8a00 (diff)
downloadpython-decorator-git-a159961aa32b876d313b8db8f23a1dba0fca4438.tar.gz
Added decoratorx and bumped version to 5.1.0
-rw-r--r--CHANGES.md16
-rw-r--r--docs/documentation.md38
-rw-r--r--src/decorator.py17
-rw-r--r--src/tests/documentation.py34
4 files changed, 96 insertions, 9 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 21510d6..6ca893b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,11 +1,15 @@
HISTORY
--------
-## unreleased
+## 5.1.0 (2021-09-11)
-`decorator.decorator` was not passing the kwsyntax argument.
-Functions decorated with `decorator.contextmanager` were one-shot.
-This is now fixed, thanks to Alex Pizarro for the report.
+Added a function `decoratorx` using the `FunctionMaker` and thus
+preserving the signature of `__code__` objects. Then fixed three small bugs:
+- Sphinx was printing a few warnings when building the documentation, as
+ signaled by Tomasz Kłoczko
+- functions decorated with `decorator.contextmanager` were one-shot,
+ as discovered by Alex Pizarro.
+- `decorator.decorator` was not passing the kwsyntax argument.
## 5.0.9 (2021-05-16)
@@ -25,8 +29,8 @@ Christian Clauss.
## 5.0.6 (2021-04-08)
-The decorator module was not copying the __module__ attribute anymore. Thanks to
-Nikolay Markov for the notice.
+The decorator module was not copying the __module__ attribute anymore.
+Thanks to Nikolay Markov for the notice.
## 5.0.5 (2021-04-04)
diff --git a/docs/documentation.md b/docs/documentation.md
index bd2b4ad..d7f282d 100644
--- a/docs/documentation.md
+++ b/docs/documentation.md
@@ -3,9 +3,9 @@
|Author | Michele Simionato|
|---|---|
|E-mail | michele.simionato@gmail.com|
-|Version| 5.0.9 (2021-09-11)|
+|Version| 5.1.0 (2021-09-11)|
|Supports| Python 3.5, 3.6, 3.7, 3.8, 3.9|
-|Download page| http://pypi.python.org/pypi/decorator/5.0.9|
+|Download page| http://pypi.python.org/pypi/decorator/5.1.0|
|Installation| ``pip install decorator``|
|License | BSD license|
@@ -1523,6 +1523,40 @@ which I will never support in the decorator module - I suggest you
to look at the [wrapt](https://wrapt.readthedocs.io/en/latest/)
project by Graeme Dumpleton.
+Since version 5 the ``decorator`` module uses the ``inspect.Signature``
+object in the standard library. Unfortunaly, for legacy reasons, some
+applications introspect decorated functions by using low-level entities like
+the ``__code__`` object and not signature objects. An example will make
+the issue clear:
+
+```python
+>>> def f(a, b): pass
+>>> f_dec = decorator(_trace)(f)
+>>> f_dec.__code__.co_argcount
+0
+>>> f_dec.__code__.co_varnames
+('args', 'kw')
+
+```
+This is not what one would expect: the `argcount` should be 2 since
+the original functions has two arguments and the `varnames` should be
+`a` and `b`. The only way to fix the issue is to go back to an implementation
+of the decorator using ``exec``, which is provided for convenience since
+version 5.1:
+
+```python
+>>> from decorator import decoratorx
+>>> f_dec = decoratorx(_trace)(f)
+>>> f_dec.__code__.co_argcount
+2
+>>> f_dec.__code__.co_varnames
+('a', 'b')
+
+```
+Rather than using `decoratorx`, you should fix your introspection
+routines to use ``inspect.Signature`` without fiddling with the
+``__code__`` object.
+
There is a strange quirk when decorating functions with keyword
arguments, if one of the arguments has the same name used in the
caller function for the first argument. The quirk was reported by
diff --git a/src/decorator.py b/src/decorator.py
index 9435841..7980acf 100644
--- a/src/decorator.py
+++ b/src/decorator.py
@@ -40,7 +40,7 @@ import itertools
from contextlib import _GeneratorContextManager
from inspect import getfullargspec, iscoroutinefunction, isgeneratorfunction
-__version__ = '5.0.9'
+__version__ = '5.1.0'
DEF = re.compile(r'\s*def\s*([_\w][_\w\d]*)\s*\(')
POS = inspect.Parameter.POSITIONAL_OR_KEYWORD
@@ -259,6 +259,21 @@ def decorate(func, caller, extras=(), kwsyntax=False):
return fun
+def decoratorx(caller):
+ """
+ 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
diff --git a/src/tests/documentation.py b/src/tests/documentation.py
index 4b717ff..506733b 100644
--- a/src/tests/documentation.py
+++ b/src/tests/documentation.py
@@ -1202,6 +1202,40 @@ which I will never support in the decorator module - I suggest you
to look at the [wrapt](https://wrapt.readthedocs.io/en/latest/)
project by Graeme Dumpleton.
+Since version 5 the ``decorator`` module uses the ``inspect.Signature``
+object in the standard library. Unfortunaly, for legacy reasons, some
+applications introspect decorated functions by using low-level entities like
+the ``__code__`` object and not signature objects. An example will make
+the issue clear:
+
+```python
+>>> def f(a, b): pass
+>>> f_dec = decorator(_trace)(f)
+>>> f_dec.__code__.co_argcount
+0
+>>> f_dec.__code__.co_varnames
+('args', 'kw')
+
+```
+This is not what one would expect: the `argcount` should be 2 since
+the original functions has two arguments and the `varnames` should be
+`a` and `b`. The only way to fix the issue is to go back to an implementation
+of the decorator using ``exec``, which is provided for convenience since
+version 5.1:
+
+```python
+>>> from decorator import decoratorx
+>>> f_dec = decoratorx(_trace)(f)
+>>> f_dec.__code__.co_argcount
+2
+>>> f_dec.__code__.co_varnames
+('a', 'b')
+
+```
+Rather than using `decoratorx`, you should fix your introspection
+routines to use ``inspect.Signature`` without fiddling with the
+``__code__`` object.
+
There is a strange quirk when decorating functions with keyword
arguments, if one of the arguments has the same name used in the
caller function for the first argument. The quirk was reported by