Hello community,

here is the log from the commit of package python3-decorator for 
openSUSE:Factory checked in at 2015-01-10 23:05:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-decorator (Old)
 and      /work/SRC/openSUSE:Factory/.python3-decorator.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python3-decorator"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-decorator/python3-decorator.changes      
2013-06-21 19:01:35.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python3-decorator.new/python3-decorator.changes 
2015-01-10 23:05:26.000000000 +0100
@@ -1,0 +2,13 @@
+Fri Jan  9 23:51:03 UTC 2015 - a...@gmx.de
+
+- specfile: update copyright year
+
+- update to version 3.4.0:
+  * Added the ability to use classes and generic callables as callers
+    and implemented a signature-preserving contexmanager
+    decorator.
+  * Fixed a bug with the signature f(**kw) in Python 3 and
+  * fixed a couple of doctests broken by Python 3.3, both issues
+    pointed out by Dominic Sacré (18/10/2012)
+
+-------------------------------------------------------------------

Old:
----
  decorator-3.3.3.tar.gz

New:
----
  decorator-3.4.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python3-decorator.spec ++++++
--- /var/tmp/diff_new_pack.lp9ve6/_old  2015-01-10 23:05:27.000000000 +0100
+++ /var/tmp/diff_new_pack.lp9ve6/_new  2015-01-10 23:05:27.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python3-decorator
 #
-# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           python3-decorator
-Version:        3.3.3
+Version:        3.4.0
 Release:        0
 Url:            http://pypi.python.org/pypi/decorator
 Summary:        Better living through Python with decorators

++++++ decorator-3.3.3.tar.gz -> decorator-3.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/decorator-3.3.3/PKG-INFO new/decorator-3.4.0/PKG-INFO
--- old/decorator-3.3.3/PKG-INFO        2012-04-23 16:52:05.000000000 +0200
+++ new/decorator-3.4.0/PKG-INFO        2012-10-18 10:53:16.000000000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 1.0
+Metadata-Version: 1.1
 Name: decorator
-Version: 3.3.3
+Version: 3.4.0
 Summary: Better living through Python with decorators
 Home-page: http://pypi.python.org/pypi/decorator
 Author: Michele Simionato
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/decorator-3.3.3/documentation.py 
new/decorator-3.4.0/documentation.py
--- old/decorator-3.3.3/documentation.py        2011-11-09 15:21:29.000000000 
+0100
+++ new/decorator-3.4.0/documentation.py        2012-10-18 10:48:36.000000000 
+0200
@@ -340,18 +340,16 @@
 implemented as a function returning a decorator.
 For more complex situations, it is more
 convenient to implement decorator factories as classes returning
-callable objects that can be used as signature-preserving
-decorators. The suggested pattern to do that is to introduce
-a helper method ``call(self, func, *args, **kw)`` and to call
-it in the ``__call__(self, func)`` method.
+callable objects that can be converted into decorators. 
 
-As an example, here I show a decorator
+As an example, here will I show a decorator
 which is able to convert a blocking function into an asynchronous
 function. The function, when called, 
 is executed in a separate thread. Moreover, it is possible to set
 three callbacks ``on_success``, ``on_failure`` and ``on_closing``,
-to specify how to manage the function call.
-The implementation is the following:
+to specify how to manage the function call (of course the code here
+is just an example, it is not a recommended way of doing multi-threaded
+programming). The implementation is the following:
 
 $$on_success
 $$on_failure
@@ -369,7 +367,7 @@
 
 .. code-block:: python
 
- >>> async = Async(threading.Thread)
+ >>> async = decorator(Async(threading.Thread))
 
  >>> datalist = [] # for simplicity the written data are stored into a list.
 
@@ -399,6 +397,71 @@
  >>> print datalist
  ['data1', 'data2']
 
+contextmanager
+-------------------------------------
+
+For a long time Python had in its standard library a ``contextmanager``
+decorator, able to convert generator functions into ``GeneratorContextManager``
+factories. For instance if you write
+
+.. code-block:: python
+
+ >>> from contextlib import contextmanager
+ >>> @contextmanager
+ ... def before_after(before, after):
+ ...     print(before)
+ ...     yield
+ ...     print(after)
+
+
+then ``before_after`` is a factory function returning
+``GeneratorContextManager`` objects which can be used with 
+the ``with`` statement:
+
+.. code-block:: python
+
+ >>> ba = before_after('BEFORE', 'AFTER')
+ >>> type(ba)
+ <class 'contextlib.GeneratorContextManager'>
+ >>> with ba:
+ ...     print 'hello'
+ BEFORE
+ hello
+ AFTER
+
+Basically, it is as if the content of the ``with`` block was executed
+in the place of the ``yield`` expression in the generator function.
+In Python 3.2 ``GeneratorContextManager`` 
+objects were enhanced with a ``__call__``
+method, so that they can be used as decorators as in this example:
+
+.. code-block:: python
+
+ >>> @ba # doctest: +SKIP
+ ... def hello():
+ ...     print 'hello'
+ ...
+ >>> hello() # doctest: +SKIP
+ BEFORE
+ hello
+ AFTER
+
+The ``ba`` decorator is basically inserting a ``with ba:`` 
+block inside the function.
+However there two issues: the first is that ``GeneratorContextManager`` 
+objects are callable only in Python 3.2, so the previous example will break
+in older versions of Python; the second is that 
+``GeneratorContextManager`` objects do not preserve the signature
+of the decorated functions: the decorated ``hello`` function here will have
+a generic signature ``hello(*args, **kwargs)`` but will break when
+called with more than zero arguments. For such reasons the decorator
+module, starting with release 3.4, offers a ``decorator.contextmanager``
+decorator that solves both problems and works even in Python 2.5.
+The usage is the same and factories decorated with ``decorator.contextmanager``
+will returns instances of ``ContextManager``, a subclass of 
+``contextlib.GeneratorContextManager`` with a ``__call__`` method
+acting as a signature-preserving decorator.
+
 The ``FunctionMaker`` class
 ---------------------------------------------------------------
 
@@ -862,29 +925,28 @@
     async_with_processes =  Async(multiprocessing.Process)
     """
 
-    def __init__(self, threadfactory):
-        self.threadfactory = threadfactory
-
-    def __call__(self, func, on_success=on_success,
+    def __init__(self, threadfactory, on_success=on_success,
                  on_failure=on_failure, on_closing=on_closing):
-        # every decorated function has its own independent thread counter
-        func.counter = itertools.count(1)
-        func.on_success = on_success
-        func.on_failure = on_failure
-        func.on_closing = on_closing
-        return decorator(self.call, func)
-
-    def call(self, func, *args, **kw):
+        self.threadfactory = threadfactory
+        self.on_success = on_success
+        self.on_failure = on_failure
+        self.on_closing = on_closing
+
+    def __call__(self, func, *args, **kw):
+        try:
+            counter = func.counter
+        except AttributeError: # instantiate the counter at the first call
+            counter = func.counter = itertools.count(1)
+        name = '%s-%s' % (func.__name__, counter.next())
         def func_wrapper():
             try:
                 result = func(*args, **kw)
             except:
-                func.on_failure(sys.exc_info())
+                self.on_failure(sys.exc_info())
             else:
-                return func.on_success(result)
+                return self.on_success(result)
             finally:
-                func.on_closing()
-        name = '%s-%s' % (func.__name__, func.counter.next())
+                self.on_closing()
         thread = self.threadfactory(None, func_wrapper, name)
         thread.start()
         return thread
@@ -1048,5 +1110,25 @@
     'The good old factorial'
     """
 
+@contextmanager
+def before_after(before, after):
+    print(before)
+    yield
+    print(after)
+
+ba = before_after('BEFORE', 'AFTER') # ContextManager instance
+
+@ba
+def hello(user):
+    """
+    >>> ba.__class__.__name__
+    'ContextManager'
+    >>> hello('michele')
+    BEFORE
+    hello michele
+    AFTER
+    """
+    print('hello %s' % user)
+
 if __name__ == '__main__':
     import doctest; doctest.testmod()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/decorator-3.3.3/documentation3.py 
new/decorator-3.4.0/documentation3.py
--- old/decorator-3.3.3/documentation3.py       2012-04-23 16:48:39.000000000 
+0200
+++ new/decorator-3.4.0/documentation3.py       2012-10-18 10:49:13.000000000 
+0200
@@ -130,7 +130,7 @@
 
 .. code-block:: python
 
- >>> f1(0, 1)
+ >>> f1(0, 1) # doctest: +IGNORE_EXCEPTION_DETAIL
  Traceback (most recent call last):
     ...
  TypeError: f1() takes exactly 1 positional argument (2 given)
@@ -302,7 +302,8 @@
 
  >>> @decorator
  ... def trace(f, *args, **kw):
- ...     print("calling %s with args %s, %s" % (f.__name__, args, kw))
+ ...     kwstr = ', '.join('%r: %r' % (k, kw[k]) for k in sorted(kw))
+ ...     print("calling %s with args %s, {%s}" % (f.__name__, args, kwstr))
  ...     return f(*args, **kw)
 
 and now ``trace`` will be a decorator. Actually ``trace`` is a ``partial``
@@ -370,18 +371,16 @@
 implemented as a function returning a decorator.
 For more complex situations, it is more
 convenient to implement decorator factories as classes returning
-callable objects that can be used as signature-preserving
-decorators. The suggested pattern to do that is to introduce
-a helper method ``call(self, func, *args, **kw)`` and to call
-it in the ``__call__(self, func)`` method.
+callable objects that can be converted into decorators. 
 
-As an example, here I show a decorator
+As an example, here will I show a decorator
 which is able to convert a blocking function into an asynchronous
 function. The function, when called, 
 is executed in a separate thread. Moreover, it is possible to set
 three callbacks ``on_success``, ``on_failure`` and ``on_closing``,
-to specify how to manage the function call.
-The implementation is the following:
+to specify how to manage the function call (of course the code here
+is just an example, it is not a recommended way of doing multi-threaded
+programming). The implementation is the following:
 
 $$on_success
 $$on_failure
@@ -399,7 +398,7 @@
 
 .. code-block:: python
 
- >>> async = Async(threading.Thread)
+ >>> async = decorator(Async(threading.Thread))
 
  >>> datalist = [] # for simplicity the written data are stored into a list.
 
@@ -429,6 +428,71 @@
  >>> print(datalist)
  ['data1', 'data2']
 
+contextmanager
+-------------------------------------
+
+For a long time Python had in its standard library a ``contextmanager``
+decorator, able to convert generator functions into 
``_GeneratorContextManager``
+factories. For instance if you write
+
+.. code-block:: python
+
+ >>> from contextlib import contextmanager
+ >>> @contextmanager
+ ... def before_after(before, after):
+ ...     print(before)
+ ...     yield
+ ...     print(after)
+
+
+then ``before_after`` is a factory function returning
+``_GeneratorContextManager`` objects which can be used with 
+the ``with`` statement:
+
+.. code-block:: python
+
+ >>> ba = before_after('BEFORE', 'AFTER')
+ >>> type(ba)
+ <class 'contextlib._GeneratorContextManager'>
+ >>> with ba:
+ ...     print('hello')
+ BEFORE
+ hello
+ AFTER
+
+Basically, it is as if the content of the ``with`` block was executed
+in the place of the ``yield`` expression in the generator function.
+In Python 3.2 ``_GeneratorContextManager`` 
+objects were enhanced with a ``__call__``
+method, so that they can be used as decorators as in this example:
+
+.. code-block:: python
+
+ >>> @ba # doctest: +SKIP
+ ... def hello():
+ ...     print('hello')
+ ...
+ >>> hello() # doctest: +SKIP
+ BEFORE
+ hello
+ AFTER
+
+The ``ba`` decorator is basically inserting a ``with ba:`` 
+block inside the function.
+However there two issues: the first is that ``_GeneratorContextManager`` 
+objects are callable only in Python 3.2, so the previous example will break
+in older versions of Python; the second is that 
+``_GeneratorContextManager`` objects do not preserve the signature
+of the decorated functions: the decorated ``hello`` function here will have
+a generic signature ``hello(*args, **kwargs)`` but will break when
+called with more than zero arguments. For such reasons the decorator
+module, starting with release 3.4, offers a ``decorator.contextmanager``
+decorator that solves both problems and works even in Python 2.5.
+The usage is the same and factories decorated with ``decorator.contextmanager``
+will returns instances of ``ContextManager``, a subclass of 
+``contextlib._GeneratorContextManager`` with a ``__call__`` method
+acting as a signature-preserving decorator.
+
 The ``FunctionMaker`` class
 ---------------------------------------------------------------
 
@@ -832,7 +896,8 @@
         dict(decorated=dec(func)), __wrapped__=func)
 
 def _trace(f, *args, **kw):
-    print("calling %s with args %s, %s" % (f.__name__, args, kw))
+    kwstr = ', '.join('%r: %r' % (k, kw[k]) for k in sorted(kw))
+    print("calling %s with args %s, {%s}" % (f.__name__, args, kwstr))
     return f(*args, **kw)
 
 def trace(f):
@@ -859,29 +924,28 @@
     async_with_processes =  Async(multiprocessing.Process)
     """
 
-    def __init__(self, threadfactory):
-        self.threadfactory = threadfactory
-
-    def __call__(self, func, on_success=on_success,
+    def __init__(self, threadfactory, on_success=on_success,
                  on_failure=on_failure, on_closing=on_closing):
-        # every decorated function has its own independent thread counter
-        func.counter = itertools.count(1)
-        func.on_success = on_success
-        func.on_failure = on_failure
-        func.on_closing = on_closing
-        return decorator(self.call, func)
-
-    def call(self, func, *args, **kw):
+        self.threadfactory = threadfactory
+        self.on_success = on_success
+        self.on_failure = on_failure
+        self.on_closing = on_closing
+
+    def __call__(self, func, *args, **kw):
+        try:
+            counter = func.counter
+        except AttributeError: # instantiate the counter at the first call
+            counter = func.counter = itertools.count(1)
+        name = '%s-%s' % (func.__name__, next(counter))
         def func_wrapper():
             try:
                 result = func(*args, **kw)
             except:
-                func.on_failure(sys.exc_info())
+                self.on_failure(sys.exc_info())
             else:
-                return func.on_success(result)
+                return self.on_success(result)
             finally:
-                func.on_closing()
-        name = '%s-%s' % (func.__name__, next(func.counter))
+                self.on_closing()
         thread = self.threadfactory(None, func_wrapper, name)
         thread.start()
         return thread
@@ -1039,7 +1103,7 @@
     >>> decorator(_memoize).__name__
     '_memoize'
 
-    Here is another bug of version 3.1.1 missing the docstring to avoid:
+    Here is another bug of version 3.1.1 missing the docstring:
 
     >>> factorial.__doc__
     'The good old factorial'
@@ -1061,9 +1125,46 @@
     ...     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'}
+    calling func with args ('a', 'b', 'c', 'd', 'e'), {'cat': 'dog', 'y': 'y', 
'z': 'z'}
     ('y', 'z')
     """
 
+def test_kwonly_no_args():
+    """# this was broken with decorator 3.3.3
+    >>> @trace
+    ... def f(**kw): pass
+    ...
+    >>> f()
+    calling f with args (), {}
+    """
+def test_kwonly_star_notation():
+    """
+    >>> @trace
+    ... def f(*, a=1, **kw): pass
+    ...
+    >>> inspect.getfullargspec(f)
+    FullArgSpec(args=[], varargs=None, varkw='kw', defaults=None, 
kwonlyargs=['a'], kwonlydefaults={'a': 1}, annotations={})
+    """
+
+@contextmanager
+def before_after(before, after):
+    print(before)
+    yield
+    print(after)
+
+ba = before_after('BEFORE', 'AFTER') # ContextManager instance
+
+@ba
+def hello(user):
+    """
+    >>> ba.__class__.__name__
+    'ContextManager'
+    >>> hello('michele')
+    BEFORE
+    hello michele
+    AFTER
+    """
+    print('hello %s' % user)
+
 if __name__ == '__main__':
     import doctest; doctest.testmod()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/decorator-3.3.3/setup.cfg 
new/decorator-3.4.0/setup.cfg
--- old/decorator-3.3.3/setup.cfg       2012-04-23 16:52:05.000000000 +0200
+++ new/decorator-3.4.0/setup.cfg       2012-10-18 10:53:16.000000000 +0200
@@ -1,5 +1,5 @@
 [egg_info]
 tag_build = 
-tag_date = 0
 tag_svn_revision = 0
+tag_date = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/decorator-3.3.3/src/decorator.egg-info/PKG-INFO 
new/decorator-3.4.0/src/decorator.egg-info/PKG-INFO
--- old/decorator-3.3.3/src/decorator.egg-info/PKG-INFO 2012-04-23 
16:52:03.000000000 +0200
+++ new/decorator-3.4.0/src/decorator.egg-info/PKG-INFO 2012-10-18 
10:52:49.000000000 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 1.0
+Metadata-Version: 1.1
 Name: decorator
-Version: 3.3.3
+Version: 3.4.0
 Summary: Better living through Python with decorators
 Home-page: http://pypi.python.org/pypi/decorator
 Author: Michele Simionato
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/decorator-3.3.3/src/decorator.py 
new/decorator-3.4.0/src/decorator.py
--- old/decorator-3.3.3/src/decorator.py        2012-04-23 16:48:39.000000000 
+0200
+++ new/decorator-3.4.0/src/decorator.py        2012-10-18 10:49:13.000000000 
+0200
@@ -32,28 +32,15 @@
 for the documentation.
 """
 
-__version__ = '3.3.3'
+__version__ = '3.4.0'
 
-__all__ = ["decorator", "FunctionMaker", "partial"]
+__all__ = ["decorator", "FunctionMaker", "contextmanager"]
 
 import sys, re, inspect
-
-try:
-    from functools import partial
-except ImportError: # for Python version < 2.5
-    class partial(object):
-        "A simple replacement of functools.partial"
-        def __init__(self, func, *args, **kw):
-            self.func = func
-            self.args = args                
-            self.keywords = kw
-        def __call__(self, *otherargs, **otherkw):
-            kw = self.keywords.copy()
-            kw.update(otherkw)
-            return self.func(*(self.args + otherargs), **kw)
-
 if sys.version >= '3':
     from inspect import getfullargspec
+    def get_init(cls):
+        return cls.__init__
 else:
     class getfullargspec(object):
         "A quick and dirty replacement for getfullargspec for Python 2.X"
@@ -67,6 +54,8 @@
             yield self.varargs
             yield self.varkw
             yield self.defaults
+    def get_init(cls):
+        return cls.__init__.im_func
 
 DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(')
 
@@ -100,17 +89,21 @@
                         inspect.formatargspec(
                         formatvalue=lambda val: "", *argspec)[1:-1]
                 else: # Python 3 way
-                    self.signature = self.shortsignature = ', '.join(self.args)
+                    allargs = list(self.args)
+                    allshortargs = list(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)
+                        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:
-                        self.signature += ', **' + self.varkw
-                        self.shortsignature += ', **' + 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:
@@ -206,15 +199,53 @@
             func, "return _call_(_func_, %(shortsignature)s)",
             evaldict, undecorated=func, __wrapped__=func)
     else: # returns a decorator
-        if isinstance(caller, partial):
-            return partial(decorator, caller)
-        # otherwise assume caller is a function
-        first = inspect.getargspec(caller)[0][0] # first arg
-        evaldict = caller.func_globals.copy()
+        if inspect.isclass(caller):
+            name = caller.__name__.lower()
+            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
+        elif inspect.isfunction(caller):
+            name = '_lambda_' if caller.__name__ == '<lambda>' \
+                else caller.__name__
+            callerfunc = caller
+            doc = caller.__doc__
+            fun = getfullargspec(callerfunc).args[0] # first arg
+        else: # assume caller is an object with a __call__ method
+            name = caller.__class__.__name__.lower()
+            callerfunc = caller.__call__.im_func
+            doc = caller.__call__.__doc__
+            fun = getfullargspec(callerfunc).args[1] # second arg
+        evaldict = callerfunc.func_globals.copy()
         evaldict['_call_'] = caller
         evaldict['decorator'] = decorator
         return FunctionMaker.create(
-            '%s(%s)' % (caller.__name__, first), 
-            'return decorator(_call_, %s)' % first,
+            '%s(%s)' % (name, fun), 
+            'return decorator(_call_, %s)' % fun,
             evaldict, undecorated=caller, __wrapped__=caller,
-            doc=caller.__doc__, module=caller.__module__)
+            doc=doc, module=caller.__module__)
+
+######################### contextmanager ########################
+
+def __call__(self, func):
+    'Context manager decorator'
+    return FunctionMaker.create(
+        func, "with _self_: return _func_(%(shortsignature)s)",
+        dict(_self_=self, _func_=func), __wrapped__=func)
+
+try: # Python >= 3.2
+
+    from contextlib import _GeneratorContextManager 
+    ContextManager = type(
+        'ContextManager', (_GeneratorContextManager,), dict(__call__=__call__))
+
+except ImportError: # Python >= 2.5
+
+    from contextlib import GeneratorContextManager
+    def __init__(self, f, *a, **k):
+        return GeneratorContextManager.__init__(self, f(*a, **k))
+    ContextManager = type(
+        'ContextManager', (GeneratorContextManager,), 
+        dict(__call__=__call__, __init__=__init__))
+    
+contextmanager = decorator(ContextManager)

-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to