Hello community, here is the log from the commit of package python-decorator for openSUSE:Factory checked in at 2018-01-19 11:47:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-decorator (Old) and /work/SRC/openSUSE:Factory/.python-decorator.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-decorator" Fri Jan 19 11:47:23 2018 rev:16 rq:566562 version:4.2.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-decorator/python-decorator.changes 2017-08-14 12:37:43.867286425 +0200 +++ /work/SRC/openSUSE:Factory/.python-decorator.new/python-decorator.changes 2018-01-19 11:47:23.212118022 +0100 @@ -1,0 +2,15 @@ +Wed Jan 17 04:02:48 UTC 2018 - [email protected] + +- specfile: + - updated copyright year + +- updated to version 4.2.1: + * Fixed a regression breaking IPython reported by + https://github.com/spapini . + +- changes from version 4.2.0 : + * Added a facility to define families of decorators (aka decorators + with arguments) as requested by several users. Accepted a pylint + patch by David Allouche. + +------------------------------------------------------------------- Old: ---- decorator-4.1.2.tar.gz New: ---- decorator-4.2.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-decorator.spec ++++++ --- /var/tmp/diff_new_pack.zQSyxx/_old 2018-01-19 11:47:23.724093880 +0100 +++ /var/tmp/diff_new_pack.zQSyxx/_new 2018-01-19 11:47:23.728093692 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-decorator # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,9 +16,12 @@ # +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-decorator -Version: 4.1.2 +Version: 4.2.1 Release: 0 Url: http://pypi.python.org/pypi/decorator Summary: Better living through Python with decorators ++++++ decorator-4.1.2.tar.gz -> decorator-4.2.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/CHANGES.md new/decorator-4.2.1/CHANGES.md --- old/decorator-4.1.2/CHANGES.md 2017-07-23 17:25:15.000000000 +0200 +++ new/decorator-4.2.1/CHANGES.md 2018-01-14 11:01:55.000000000 +0100 @@ -3,17 +3,27 @@ ## Unreleased +## 4.2.1 (2018-01-14) + +Fixed a regression breaking IPython and discovered by https://github.com/spapini + +## 4.2.0 (2018-01-14) + +Added a facility to define families of decorators (aka decorators with +arguments) as requested by several users. Accepted a pylint patch by +David Allouche. + ## 4.1.2 (2017-07-23) Made it possible to define decorators converting coroutines into regular functions, as requested by Itaï Ben Yaacov. -## 4.1.1 (2017-06-16) +## 4.1.1 (2017-07-16) Changed the documentation build system to sphinx and uploaded the docs on readthedocs.org. -## 4.1.0 (2017-06-15) +## 4.1.0 (2017-07-15) Support for Python 3.5 coroutines defined with `async def`, thanks to Victor-Nicolae Savu who raised the issue of `iscoroutinefunction` not diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/PKG-INFO new/decorator-4.2.1/PKG-INFO --- old/decorator-4.1.2/PKG-INFO 2017-07-23 17:25:19.000000000 +0200 +++ new/decorator-4.2.1/PKG-INFO 2018-01-14 11:12:16.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: decorator -Version: 4.1.2 +Version: 4.2.1 Summary: Better living through Python with decorators Home-page: https://github.com/micheles/decorator Author: Michele Simionato @@ -61,8 +61,8 @@ Documentation --------------- - The documentation has been moved to http://decorator.readthedocs.io/en/stable/ - You can download a PDF version of it from http://media.readthedocs.org/pdf/decorator/stable/decorator.pdf + The documentation has been moved to http://decorator.readthedocs.io/en/latest/ + You can download a PDF version of it from http://media.readthedocs.org/pdf/decorator/latest/decorator.pdf Keywords: decorators generic utility Platform: All @@ -72,6 +72,15 @@ Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Utilities diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/docs/README.rst new/decorator-4.2.1/docs/README.rst --- old/decorator-4.1.2/docs/README.rst 2017-07-17 06:04:57.000000000 +0200 +++ new/decorator-4.2.1/docs/README.rst 2018-01-14 10:40:35.000000000 +0100 @@ -53,5 +53,5 @@ Documentation --------------- -The documentation has been moved to http://decorator.readthedocs.io/en/stable/ -You can download a PDF version of it from http://media.readthedocs.org/pdf/decorator/stable/decorator.pdf +The documentation has been moved to http://decorator.readthedocs.io/en/latest/ +You can download a PDF version of it from http://media.readthedocs.org/pdf/decorator/latest/decorator.pdf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/setup.py new/decorator-4.2.1/setup.py --- old/decorator-4.1.2/setup.py 2015-07-28 05:50:27.000000000 +0200 +++ new/decorator-4.2.1/setup.py 2018-01-14 10:38:21.000000000 +0100 @@ -24,7 +24,16 @@ 'Natural Language :: English', 'Operating System :: OS Independent', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: Implementation :: CPython', 'Topic :: Software Development :: Libraries', 'Topic :: Utilities'], test_suite='tests', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/src/decorator.egg-info/PKG-INFO new/decorator-4.2.1/src/decorator.egg-info/PKG-INFO --- old/decorator-4.1.2/src/decorator.egg-info/PKG-INFO 2017-07-23 17:25:19.000000000 +0200 +++ new/decorator-4.2.1/src/decorator.egg-info/PKG-INFO 2018-01-14 11:12:16.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: decorator -Version: 4.1.2 +Version: 4.2.1 Summary: Better living through Python with decorators Home-page: https://github.com/micheles/decorator Author: Michele Simionato @@ -61,8 +61,8 @@ Documentation --------------- - The documentation has been moved to http://decorator.readthedocs.io/en/stable/ - You can download a PDF version of it from http://media.readthedocs.org/pdf/decorator/stable/decorator.pdf + The documentation has been moved to http://decorator.readthedocs.io/en/latest/ + You can download a PDF version of it from http://media.readthedocs.org/pdf/decorator/latest/decorator.pdf Keywords: decorators generic utility Platform: All @@ -72,6 +72,15 @@ Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Utilities diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/src/decorator.py new/decorator-4.2.1/src/decorator.py --- old/decorator-4.1.2/src/decorator.py 2017-07-23 17:25:15.000000000 +0200 +++ new/decorator-4.2.1/src/decorator.py 2018-01-14 11:00:21.000000000 +0100 @@ -1,6 +1,6 @@ # ######################### LICENSE ############################ # -# Copyright (c) 2005-2017, Michele Simionato +# Copyright (c) 2005-2018, Michele Simionato # All rights reserved. # Redistribution and use in source and binary forms, with or without @@ -40,7 +40,7 @@ import itertools import collections -__version__ = '4.1.2' +__version__ = '4.2.1' if sys.version >= '3': from inspect import getfullargspec @@ -112,26 +112,21 @@ setattr(self, a, getattr(argspec, a)) for i, arg in enumerate(self.args): setattr(self, 'arg%d' % i, arg) - if sys.version < '3': # easy way - self.shortsignature = self.signature = ( - inspect.formatargspec( - formatvalue=lambda val: "", *argspec[:-2])[1:-1]) - else: # Python 3 way - allargs = list(self.args) - allshortargs = list(self.args) - if self.varargs: - allargs.append('*' + self.varargs) - allshortargs.append('*' + self.varargs) - elif self.kwonlyargs: - allargs.append('*') # single star syntax - for a in self.kwonlyargs: - allargs.append('%s=None' % a) - allshortargs.append('%s=%s' % (a, a)) - if self.varkw: - allargs.append('**' + self.varkw) - allshortargs.append('**' + self.varkw) - self.signature = ', '.join(allargs) - self.shortsignature = ', '.join(allshortargs) + allargs = list(self.args) + allshortargs = list(self.args) + if self.varargs: + allargs.append('*' + self.varargs) + allshortargs.append('*' + self.varargs) + elif self.kwonlyargs: + allargs.append('*') # single star syntax + for a in self.kwonlyargs: + allargs.append('%s=None' % a) + allshortargs.append('%s=%s' % (a, a)) + if self.varkw: + allargs.append('**' + self.varkw) + allshortargs.append('**' + self.varkw) + self.signature = ', '.join(allargs) + self.shortsignature = ', '.join(allshortargs) self.dict = func.__dict__.copy() # func=None happens when decorating a caller if name: @@ -230,13 +225,18 @@ return self.make(body, evaldict, addsource, **attrs) -def decorate(func, caller): +def decorate(func, caller, extras=()): """ decorate(func, caller) decorates a function using a caller. """ evaldict = dict(_call_=caller, _func_=func) + es = '' + for i, extra in enumerate(extras): + ex = '_e%d_' % i + evaldict[ex] = extra + es += ex + ', ' fun = FunctionMaker.create( - func, "return _call_(_func_, %(shortsignature)s)", + func, "return _call_(_func_, %s%%(shortsignature)s)" % es, evaldict, __wrapped__=func) if hasattr(func, '__qualname__'): fun.__qualname__ = func.__qualname__ @@ -249,6 +249,7 @@ # this is obsolete behavior; you should use decorate instead return decorate(_func, caller) # else return a decorator function + defaultargs, defaults = '', () if inspect.isclass(caller): name = caller.__name__.lower() doc = 'decorator(%s) converts functions/generators into ' \ @@ -259,15 +260,24 @@ else: name = caller.__name__ doc = caller.__doc__ + nargs = caller.__code__.co_argcount + ndefs = len(caller.__defaults__ or ()) + 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) - return FunctionMaker.create( - '%s(func)' % name, 'return _decorate_(func, _call)', - evaldict, doc=doc, module=caller.__module__, - __wrapped__=caller) - + 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 + return dec # ####################### contextmanager ####################### # @@ -298,7 +308,12 @@ return _GeneratorContextManager.__init__(self, g, a, k) ContextManager.__init__ = __init__ -contextmanager = decorator(ContextManager) +_contextmanager = decorator(ContextManager) + + +def contextmanager(func): + # Enable Pylint config: contextmanager-decorators=decorator.contextmanager + return _contextmanager(func) # ############################ dispatch_on ############################ # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/src/tests/documentation.py new/decorator-4.2.1/src/tests/documentation.py --- old/decorator-4.1.2/src/tests/documentation.py 2017-07-23 17:25:15.000000000 +0200 +++ new/decorator-4.2.1/src/tests/documentation.py 2018-01-14 10:38:21.000000000 +0100 @@ -29,7 +29,7 @@ separate docs for Python 2 and Python 3 effectively stopped any development on the module for several years. Moreover, it is now trivial to distribute the module as an universal wheel_ since 2to3 is no more -required. Since Python 2.5 has been released 9 years ago, I felt that +required. Since Python 2.5 has been released ages ago (in 2006), I felt that it was reasonable to drop the support for it. If you need to support ancient versions of Python, stick with the decorator module version 3.4.2. The current version supports all Python releases from 2.6 up to 3.6. @@ -41,9 +41,9 @@ - **New documentation** There is now a single manual for all Python versions, so I took the - opportunity to overhaul the documentation. So, even if you are - a long-time user, you may want to revisit the docs, since several - examples have been improved. + opportunity to overhaul the documentation and to move it to readthedocs.org. + Even if you are a long-time user, you may want to revisit the docs, since + several examples have been improved. - **Packaging improvements** The code is now also available in wheel format. Integration with @@ -63,17 +63,19 @@ in Python 3.4), but the implementation is much simpler. Moreover, all decorators involved preserve the signature of the decorated functions. For now, this exists mostly to demonstrate - the power of the module. In the future it could be enhanced/optimized; - however, its API could change. (Such is the fate of - experimental features!) In any case, it is very short and compact - (less then 100 lines), so you can extract it for your own use. - Take it as food for thought. + the power of the module. In the future it could be enhanced/optimized. + In any case, it is very short and compact (less then 100 lines), so you + can extract it for your own use. Take it as food for thought. - **Python 3.5 coroutines** From version 4.1 it is possible to decorate coroutines, i.e. functions defined with the `async def` syntax, and to maintain the `inspect.iscoroutinefunction` check working for the decorated function. +- **Decorator factories** + 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 ------------------------------------------------ @@ -358,14 +360,50 @@ >>> func() calling func with args (), {} +The `decorator` function can also be used to define factories of decorators, +i.e. functions returning decorators. In general you can just write something +like this: + +.. code-block:: python + + def decfactory(param1, param2, ...): + def caller(f, *args, **kw): + return somefunc(f, param1, param2, .., *args, **kw) + return decorator(caller) + +This is fully general but requires an additional level of nesting. For this +reasone since version 4.2 there is a facility to build +decorator factories by using a single caller with default arguments i.e. +writing something like this: + +.. code-block:: python + + def caller(f, param1=default1, param2=default2, ..., *args, **kw): + return somefunc(f, param1, param2, *args, **kw) + decfactory = decorator(caller) + +Notice that this simplified approach *only works with default arguments*, +i.e. `param1`, `param2` etc must have known defaults. Thanks to this +restriction, there exists an unique default decorator, i.e. the member +of the family which uses the default values for all parameters. Such +decorator can be written as `decfactory()` with no parameters specified; +moreover, as a shortcut, it is also possible to elide the parenthesis, +a feature much requested by the users. For years I have been opposite +to this feature request, since having expliciti parenthesis to me is more clear +and less magic; however once this feature entered in decorators of +the Python standard library (I am referring to the `dataclass` decorator +https://www.python.org/dev/peps/pep-0557/) I finally gave up. + +The example below will show how it works in practice. + ``blocking`` ------------------------------------------- Sometimes one has to deal with blocking resources, such as ``stdin``. Sometimes it is better to receive a "busy" message than just blocking everything. -This can be accomplished with a suitable family of decorators, -where the parameter is the busy message: +This can be accomplished with a suitable family of decorators (decorator +factory), parameterize by a string, the busy message: $$blocking @@ -375,7 +413,7 @@ .. code-block:: python - >>> @blocking("Please wait ...") + >>> @blocking(msg="Please wait ...") ... def read_data(): ... time.sleep(3) # simulate a blocking resource ... return "some data" @@ -812,7 +850,7 @@ $$writefloat -Now XMLWriter can serialize floats: +Now ``XMLWriter`` can serialize floats: .. code-block:: python @@ -834,11 +872,11 @@ the implementation. The idea is to define a generic function (``win(a, b)``) of two arguments corresponding to the *moves* of the first and second players. The *moves* are instances of the classes -Rock, Paper, and Scissors. +Rock, Paper, and Scissors: -Paper wins over Rock; -Scissors wins over Paper; and -Rock wins over Scissors. +- Paper wins over Rock +- Scissors wins over Paper +- Rock wins over Scissors The function will return +1 for a win, -1 for a loss, and 0 for parity. There are 9 combinations, but combinations with the same ordinal @@ -1431,20 +1469,19 @@ return decorate(f, _memoize) -def blocking(not_avail): - def _blocking(f, *args, **kw): - if not hasattr(f, "thread"): # no thread running - def set_result(): - f.result = f(*args, **kw) - f.thread = threading.Thread(None, set_result) - f.thread.start() - return not_avail - elif f.thread.isAlive(): - return not_avail - else: # the thread is ended, return the stored result - del f.thread - return f.result - return decorator(_blocking) +@decorator +def blocking(f, msg='blocking', *args, **kw): + if not hasattr(f, "thread"): # no thread running + def set_result(): + f.result = f(*args, **kw) + f.thread = threading.Thread(None, set_result) + f.thread.start() + return msg + elif f.thread.isAlive(): + return msg + else: # the thread is ended, return the stored result + del f.thread + return f.result class User(object): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/decorator-4.1.2/src/tests/test.py new/decorator-4.2.1/src/tests/test.py --- old/decorator-4.1.2/src/tests/test.py 2017-07-23 17:25:15.000000000 +0200 +++ new/decorator-4.2.1/src/tests/test.py 2018-01-14 10:52:32.000000000 +0100 @@ -119,6 +119,12 @@ # there is no confusion when passing args as a keyword argument self.assertEqual(func(args='a'), {'args': 'a'}) + def test_decorator_factory(self): + # similar to what IPython is doing in traitlets.config.application + @decorator + def catch_config_error(method, app, *args, **kwargs): + return method(app) + catch_config_error(lambda app: None) # ################### test dispatch_on ############################# # # adapted from test_functools in Python 3.5
