Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-decorator for openSUSE:Factory checked in at 2021-10-20 20:23:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-decorator (Old) and /work/SRC/openSUSE:Factory/.python-decorator.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-decorator" Wed Oct 20 20:23:30 2021 rev:24 rq:925751 version:5.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-decorator/python-decorator.changes 2021-08-11 11:47:01.369760525 +0200 +++ /work/SRC/openSUSE:Factory/.python-decorator.new.1890/python-decorator.changes 2021-10-20 20:24:17.169378144 +0200 @@ -1,0 +2,12 @@ +Sat Oct 16 20:56:50 UTC 2021 - Dirk M??ller <dmuel...@suse.com> + +- update to 5.1.0: + * Added a function `decoratorx` using the `FunctionMaker` and thus + preserving the signature of `__code__` objects. + * Sphinx was printing a few warnings when building the documentation + * functions decorated with `decorator.contextmanager` were one-shot, + as discovered by Alex Pizarro. + * `decorator.decorator` was not passing the kwsyntax argument. +- drop kwsyntax.patch (usptream) + +------------------------------------------------------------------- Old: ---- decorator-5.0.9.tar.gz kwsyntax.patch New: ---- decorator-5.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-decorator.spec ++++++ --- /var/tmp/diff_new_pack.fKFNRr/_old 2021-10-20 20:24:17.621378423 +0200 +++ /var/tmp/diff_new_pack.fKFNRr/_new 2021-10-20 20:24:17.629378428 +0200 @@ -21,15 +21,13 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %global skip_python2 1 Name: python-decorator -Version: 5.0.9 +Version: 5.1.0 Release: 0 Summary: Decorators for Humans License: BSD-2-Clause Group: Development/Languages/Python URL: https://github.com/micheles/decorator Source: https://files.pythonhosted.org/packages/source/d/decorator/decorator-%{version}.tar.gz -# PATCH-FIX-UPSTREAM https://github.com/micheles/decorator/commit/817d070db3c9cc5900d118837c533c039982b050 Fixed decorator.decorator not passing kwsyntax -Patch0: kwsyntax.patch BuildRequires: %{python_module setuptools} BuildRequires: dos2unix BuildRequires: fdupes ++++++ decorator-5.0.9.tar.gz -> decorator-5.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-5.0.9/CHANGES.md new/decorator-5.1.0/CHANGES.md --- old/decorator-5.0.9/CHANGES.md 2021-05-16 06:06:15.000000000 +0200 +++ new/decorator-5.1.0/CHANGES.md 2021-09-11 07:21:30.000000000 +0200 @@ -1,7 +1,15 @@ HISTORY -------- -## unreleased +## 5.1.0 (2021-09-11) + +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) @@ -21,8 +29,8 @@ ## 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-5.0.9/PKG-INFO new/decorator-5.1.0/PKG-INFO --- old/decorator-5.0.9/PKG-INFO 2021-05-16 06:08:31.094942800 +0200 +++ new/decorator-5.1.0/PKG-INFO 2021-09-11 07:30:13.176995000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: decorator -Version: 5.0.9 +Version: 5.1.0 Summary: Decorators for Humans Home-page: https://github.com/micheles/decorator Author: Michele Simionato diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-5.0.9/src/decorator.egg-info/PKG-INFO new/decorator-5.1.0/src/decorator.egg-info/PKG-INFO --- old/decorator-5.0.9/src/decorator.egg-info/PKG-INFO 2021-05-16 06:08:30.000000000 +0200 +++ new/decorator-5.1.0/src/decorator.egg-info/PKG-INFO 2021-09-11 07:30:12.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: decorator -Version: 5.0.9 +Version: 5.1.0 Summary: Decorators for Humans Home-page: https://github.com/micheles/decorator Author: Michele Simionato diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-5.0.9/src/decorator.py new/decorator-5.1.0/src/decorator.py --- old/decorator-5.0.9/src/decorator.py 2021-05-16 06:05:29.000000000 +0200 +++ new/decorator-5.1.0/src/decorator.py 2021-09-11 07:19:46.000000000 +0200 @@ -40,7 +40,7 @@ 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,13 +259,28 @@ 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 """ if _func is not None: # return a decorated function # this is obsolete behavior; you should use decorate instead - return decorate(_func, caller) + return decorate(_func, caller, (), kwsyntax) # else return a decorator function sig = inspect.signature(caller) dec_params = [p for p in sig.parameters.values() if p.kind is POS] @@ -294,11 +309,11 @@ class ContextManager(_GeneratorContextManager): def __init__(self, g, *a, **k): - return _GeneratorContextManager.__init__(self, g, a, k) + _GeneratorContextManager.__init__(self, g, a, k) def __call__(self, func): def caller(f, *a, **k): - with self: + with self._recreate_cm(): return f(*a, **k) return decorate(func, caller) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-5.0.9/src/tests/documentation.py new/decorator-5.1.0/src/tests/documentation.py --- old/decorator-5.0.9/src/tests/documentation.py 2021-04-11 07:52:37.000000000 +0200 +++ new/decorator-5.1.0/src/tests/documentation.py 2021-09-11 07:28:23.000000000 +0200 @@ -1,4 +1,3 @@ -import sys import inspect import threading import time @@ -9,8 +8,7 @@ from decorator import (decorator, decorate, FunctionMaker, dispatch_on, __version__) -doc = r"""Decorators for Humans ----------------------------------- +doc = r"""# Decorators for Humans |Author | Michele Simionato| |---|---| @@ -21,8 +19,7 @@ |Installation| ``pip install decorator``| |License | BSD license| -Introduction ------------------------------------------ +## Introduction The ``decorator`` module is over ten years old, but still alive and kicking. It is used by several frameworks (IPython, scipy, authkit, @@ -33,8 +30,7 @@ versions back to 2.6; versions 3.X are able to support even Python 2.5 and 2.4. -What's New in version 5 ------------------------ +## What's New in version 5 Version 5 of the decorator module features a major simplification of the code base made possible by dropping support for Python releases @@ -46,8 +42,7 @@ now possible to mimic the behavior of decorators defined with ``functool.wraps``: see the section about the ``kwsyntax`` flag below. -What's New in version 4 ------------------------ +## What's New in version 4 - **New documentation** There is now a single manual for all Python versions, so I took the @@ -86,8 +81,7 @@ From version 4.2 there is facility to define factories of decorators in a simple way, a feature requested by the users since a long time. -Usefulness of decorators ------------------------------------------------- +## Usefulness of decorators Python decorators are an interesting example of why syntactic sugar matters. In principle, their introduction in Python 2.4 changed @@ -117,8 +111,7 @@ discussed here in the ``documentation.py`` file, which contains the documentation you are reading in the form of doctests. -Definitions ------------------------------------- +## Definitions Technically speaking, any Python object which can be called with one argument can be used as a decorator. However, this definition is somewhat too large @@ -147,8 +140,7 @@ can accept functions with any signature. A simple example will clarify the issue. -Statement of the problem ------------------------------- +## Statement of the problem A very common use case for decorators is the memoization of functions. A ``memoize`` decorator works by caching @@ -212,8 +204,7 @@ Notice that ``pydoc`` will give the right signature, but only in Python versions greater than 3.5. -The solution ------------------------------------------ +## The solution The solution is to provide a generic factory of generators, which hides the complexity of making signature-preserving decorators @@ -270,8 +261,7 @@ ``` -A ``trace`` decorator ------------------------------------------------------- +## A ``trace`` decorator Here is an example of how to define a simple ``trace`` decorator, which prints a message whenever the traced function is called: @@ -320,10 +310,61 @@ ``` -$FUNCTION_ANNOTATIONS +## Function annotations -``decorator.decorator`` ---------------------------------------------- +Python 3 introduced the concept of [function annotations]( +http://www.python.org/dev/peps/pep-3107/): the ability +to annotate the signature of a function with additional information, +stored in a dictionary named ``__annotations__``. The ``decorator`` module +(starting from release 3.3) will understand and preserve these annotations. + +Here is an example: + +```python +>>> @trace +... def f(x: 'the first argument', y: 'default argument'=1, z=2, +... *args: 'varargs', **kw: 'kwargs'): +... pass + +``` + +In order to introspect functions with annotations, one needs +``inspect.getfullargspec`` (introduced in Python 3, then +deprecated in Python 3.5, then undeprecated in Python 3.6): + +```python +>>> from inspect import getfullargspec +>>> argspec = getfullargspec(f) +>>> argspec.args +['x', 'y', 'z'] +>>> argspec.varargs +'args' +>>> argspec.varkw +'kw' +>>> argspec.defaults +(1, 2) +>>> argspec.kwonlyargs +[] +>>> argspec.kwonlydefaults + +``` + +You can check that the ``__annotations__`` dictionary is preserved: + +```python +>>> f.__annotations__ is f.__wrapped__.__annotations__ +True + +``` + +Here ``f.__wrapped__`` is the original undecorated function. +This attribute exists for consistency with the behavior of +``functools.update_wrapper``. + +Another attribute copied from the original function is ``__qualname__``, +the qualified name. This attribute was introduced in Python 3.3. + +## ``decorator.decorator`` It can become tedious to write a caller function (like the above ``_trace`` example) and then a trivial wrapper @@ -373,8 +414,7 @@ ``` -Mimicking the behavior of functools.wrap ----------------------------------------- +## Mimicking the behavior of functools.wrap Often people are confused by the decorator module since, contrarily to ``functools.wraps`` in the standard library, it tries very hard @@ -433,8 +473,7 @@ ``` -Decorator factories -------------------------------------------- +## Decorator factories The `decorator` function can also be used to define factories of decorators, i.e. functions returning decorators. In general you can just write something @@ -524,8 +563,7 @@ Be careful! -``decorator(cls)`` --------------------------------------------- +## ``decorator(cls)`` The ``decorator`` facility can also produce a decorator starting from a class with the signature of a caller. In such a case the @@ -561,8 +599,7 @@ ``` -contextmanager -------------------------------------- +## contextmanager Python's standard library has the ``contextmanager`` decorator, which converts a generator function into a ``GeneratorContextManager`` @@ -599,11 +636,11 @@ ```python >>> ba = before_after('BEFORE', 'AFTER') >>> ->>> @ba # doctest: +SKIP +>>> @ba ... def hello(): ... print('hello') ... ->>> hello() # doctest: +SKIP +>>> hello() BEFORE hello AFTER @@ -627,8 +664,7 @@ an improved ``__call__`` method, which acts as a signature-preserving decorator. -The ``FunctionMaker`` class ---------------------------------------------------------------- +## The ``FunctionMaker`` class The ``decorator`` module also provides a ``FunctionMaker`` class, which is able to generate on-the-fly functions @@ -718,8 +754,7 @@ ``` -Getting the source code ---------------------------------------------------- +## Getting the source code Internally, ``FunctionMaker.create`` uses ``exec`` to generate the decorated function. Therefore ``inspect.getsource`` will not work for @@ -742,8 +777,7 @@ ``` -Dealing with third-party decorators ------------------------------------------------------------------ +## Dealing with third-party decorators Sometimes on the net you find some cool decorator that you would like to include in your code. However, more often than not, the cool @@ -807,8 +841,7 @@ - returns a value without making a recursive call; or, - returns directly the result of a recursive call. -Python 3.5 coroutines ------------------------ +## Python 3.5 coroutines I am personally not using Python 3.5 coroutines yet. However, some users requested support for coroutines and since version 4.1 the @@ -878,8 +911,7 @@ the caller in ``coro_to_func`` is a regular function and converts coroutines -> functions. -Multiple dispatch -------------------------------------------- +## Multiple dispatch There has been talk of implementing multiple dispatch functions (i.e. "generic functions") in Python for over ten years. Last year, @@ -1016,8 +1048,7 @@ [MRO](http://www.python.org/2.3/mro.html) for short) of ``StrongRock`` and ``Scissors``, respectively. -Generic functions and virtual ancestors -------------------------------------------------- +## Generic functions and virtual ancestors In Python, generic functions are complicated by the existence of "virtual ancestors": superclasses which are not in the class hierarchy. @@ -1161,8 +1192,7 @@ Finally, let me notice that the decorator module implementation does not use any cache, whereas the ``singledispatch`` implementation does. -Caveats and limitations -------------------------------------------- +## Caveats and limitations In the present implementation, decorators generated by ``decorator`` can only be used on user-defined Python functions, methods or coroutines. @@ -1172,6 +1202,40 @@ 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. Unfortunately, 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 @@ -1276,8 +1340,7 @@ *could* be negligible. As always, the only way to know if there is a penalty in your specific use case is to measure it. -LICENSE (2-clause BSD) ---------------------------------------------- +## LICENSE (2-clause BSD) Copyright (c) 2005-2020, Michele Simionato All rights reserved. @@ -1311,68 +1374,9 @@ you are unhappy with it, send me a patch! """ -function_annotations = """Function annotations ---------------------------------------------- - -Python 3 introduced the concept of [function annotations]( -http://www.python.org/dev/peps/pep-3107/): the ability -to annotate the signature of a function with additional information, -stored in a dictionary named ``__annotations__``. The ``decorator`` module -(starting from release 3.3) will understand and preserve these annotations. - -Here is an example: - -```python ->>> @trace -... def f(x: 'the first argument', y: 'default argument'=1, z=2, -... *args: 'varargs', **kw: 'kwargs'): -... pass - -``` - -In order to introspect functions with annotations, one needs -``inspect.getfullargspec`` (introduced in Python 3, then -deprecated in Python 3.5, then undeprecated in Python 3.6): - -```python ->>> from inspect import getfullargspec ->>> argspec = getfullargspec(f) ->>> argspec.args -['x', 'y', 'z'] ->>> argspec.varargs -'args' ->>> argspec.varkw -'kw' ->>> argspec.defaults -(1, 2) ->>> argspec.kwonlyargs -[] ->>> argspec.kwonlydefaults - -``` - -You can check that the ``__annotations__`` dictionary is preserved: - -```python ->>> f.__annotations__ is f.__wrapped__.__annotations__ -True - -``` - -Here ``f.__wrapped__`` is the original undecorated function. -This attribute exists for consistency with the behavior of -``functools.update_wrapper``. - -Another attribute copied from the original function is ``__qualname__``, -the qualified name. This attribute was introduced in Python 3.3. -""" -if sys.version_info < (3,): - function_annotations = '' - today = time.strftime('%Y-%m-%d') -__doc__ = (doc.replace('$VERSION', __version__).replace('$DATE', today) - .replace('$FUNCTION_ANNOTATIONS', function_annotations)) +__doc__ = doc.replace('$VERSION', __version__).replace('$DATE', today) def decorator_apply(dec, func):