23093759 Upgrade decorator to 4.0.10
authorRich Burridge <rich.burridge@oracle.com>
Tue, 20 Sep 2016 08:43:49 -0700
changeset 6934 e72eb275185d
parent 6933 e1fa2aa7bad7
child 6935 6b52769f860f
23093759 Upgrade decorator to 4.0.10
components/python/decorator/Makefile
components/python/decorator/decorator-PYVER.p5m
components/python/decorator/decorator.license
components/python/decorator/test/results-2.7-32.master
components/python/decorator/test/results-3.4-32.master
components/python/decorator/test/results-3.5-32.master
--- a/components/python/decorator/Makefile	Tue Sep 20 08:35:58 2016 -0700
+++ b/components/python/decorator/Makefile	Tue Sep 20 08:43:49 2016 -0700
@@ -20,21 +20,21 @@
 #
 
 #
-# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
 #
 include ../../../make-rules/shared-macros.mk
 
 COMPONENT_NAME=		decorator
-COMPONENT_VERSION=	3.4.0
+COMPONENT_VERSION=	4.0.10
 COMPONENT_SRC=		$(COMPONENT_NAME)-$(COMPONENT_VERSION)
 COMPONENT_ARCHIVE=	$(COMPONENT_SRC).tar.gz
 COMPONENT_ARCHIVE_HASH=	\
-    sha256:c20b404cbb7ee5cebd506688e0114e3cd76f5ce233805a51f36e1a7988d9d783
+    sha256:9c6e98edcb33499881b86ede07d9968c81ab7c769e28e9af24075f0a5379f070
 COMPONENT_ARCHIVE_URL=	$(call pypi_url)
 COMPONENT_PROJECT_URL=	http://pypi.python.org/pypi/decorator
 COMPONENT_BUGDB=	python-mod/decorator
 
-TPNO=			13154
+TPNO=			31612
 
 include $(WS_MAKE_RULES)/prep.mk
 include $(WS_MAKE_RULES)/setup.py.mk
@@ -42,13 +42,12 @@
 
 ASLR_MODE = $(ASLR_NOT_APPLICABLE)
 
-COMPONENT_TEST_ARGS.2.7=	documentation.py -v
-COMPONENT_TEST_ARGS.3.4=	documentation3.py -v
-COMPONENT_TEST_ARGS.3.5=	documentation3.py -v
-COMPONENT_TEST_ARGS=		$(COMPONENT_TEST_ARGS.$(PYTHON_VERSION))
-COMPONENT_TEST_DIR=		$(SOURCE_DIR)
+COMPONENT_TEST_ARGS=		test.py -v
+COMPONENT_TEST_DIR=		$(SOURCE_DIR)/src/tests
 
-# common targets
+COMPONENT_TEST_TRANSFORMS += \
+	'-e "s|\(Ran .* tests in\).*|\1|" '
+
 build:		$(BUILD_NO_ARCH)
 
 install:	$(INSTALL_NO_ARCH)
--- a/components/python/decorator/decorator-PYVER.p5m	Tue Sep 20 08:35:58 2016 -0700
+++ b/components/python/decorator/decorator-PYVER.p5m	Tue Sep 20 08:43:49 2016 -0700
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri \
@@ -42,6 +42,7 @@
 file path=usr/lib/python$(PYVER)/vendor-packages/decorator-$(COMPONENT_VERSION)-py$(PYVER).egg-info/SOURCES.txt
 file path=usr/lib/python$(PYVER)/vendor-packages/decorator-$(COMPONENT_VERSION)-py$(PYVER).egg-info/dependency_links.txt
 file path=usr/lib/python$(PYVER)/vendor-packages/decorator-$(COMPONENT_VERSION)-py$(PYVER).egg-info/not-zip-safe
+file path=usr/lib/python$(PYVER)/vendor-packages/decorator-$(COMPONENT_VERSION)-py$(PYVER).egg-info/pbr.json
 file path=usr/lib/python$(PYVER)/vendor-packages/decorator-$(COMPONENT_VERSION)-py$(PYVER).egg-info/top_level.txt
 file path=usr/lib/python$(PYVER)/vendor-packages/decorator.py
 #
--- a/components/python/decorator/decorator.license	Tue Sep 20 08:35:58 2016 -0700
+++ b/components/python/decorator/decorator.license	Tue Sep 20 08:43:49 2016 -0700
@@ -1,21 +1,26 @@
-Copyright (c) 2005-2012, Michele Simionato All rights reserved.
+Copyright (c) 2005-2015, Michele Simionato
+All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+modification, are permitted provided that the following conditions are
+met:
 
-    Redistributions of source code must retain the above copyright notice, this
-    list of conditions and the following disclaimer. Redistributions in
-    bytecode form must reproduce the above copyright notice, this list of
-    conditions and the following disclaimer in the documentation and/or other
-    materials provided with the distribution.
+  Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+  Redistributions in bytecode form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
--- a/components/python/decorator/test/results-2.7-32.master	Tue Sep 20 08:35:58 2016 -0700
+++ b/components/python/decorator/test/results-2.7-32.master	Tue Sep 20 08:43:49 2016 -0700
@@ -1,28 +1,21 @@
-Trying:
-    @memoize_uw
-    def f1(x):
-        time.sleep(1) # simulate some long computation
-        return x
-Expecting nothing
-ok
-Trying:
-    from inspect import getargspec 
+test (__main__.DocumentationTestCase) ... Trying:
+    from decorator import getargspec  # akin to inspect.getargspec
 Expecting nothing
 ok
 Trying:
-    print getargspec(f1) # I am using Python 2.6+ here
+    print(getargspec(f1))
 Expecting:
-    ArgSpec(args=[], varargs='args', keywords='kw', defaults=None)
+    ArgSpec(args=[], varargs='args', varkw='kw', defaults=None)
 ok
 Trying:
-    f1(0, 1)
+    f1(0, 1) # doctest: +IGNORE_EXCEPTION_DETAIL
 Expecting:
     Traceback (most recent call last):
        ...
-    TypeError: f1() takes exactly 1 argument (2 given)
+    TypeError: f1() takes exactly 1 positional argument (2 given)
 ok
 Trying:
-    from decorator import decorator
+    from decorator import decorate
 Expecting nothing
 ok
 Trying:
@@ -33,19 +26,19 @@
 Expecting nothing
 ok
 Trying:
-    print heavy_computation() # the first time it will take 2 seconds
+    print(heavy_computation()) # the first time it will take 2 seconds
 Expecting:
     done
 ok
 Trying:
-    print heavy_computation() # the second time it will be instantaneous
+    print(heavy_computation()) # the second time it will be instantaneous
 Expecting:
     done
 ok
 Trying:
-    print getargspec(heavy_computation) 
+    print(getargspec(heavy_computation))
 Expecting:
-    ArgSpec(args=[], varargs=None, keywords=None, defaults=None)
+    ArgSpec(args=[], varargs=None, varkw=None, defaults=None)
 ok
 Trying:
     @trace
@@ -59,9 +52,9 @@
     calling f1 with args (0,), {}
 ok
 Trying:
-    print getargspec(f1) 
+    print(getargspec(f1))
 Expecting:
-    ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
+    ArgSpec(args=['x'], varargs=None, varkw=None, defaults=None)
 ok
 Trying:
     @trace
@@ -75,30 +68,24 @@
     calling f with args (0, 3, 2), {}
 ok
 Trying:
-    print getargspec(f) 
+    print(getargspec(f))
 Expecting:
-    ArgSpec(args=['x', 'y', 'z'], varargs='args', keywords='kw', defaults=(1, 2))
+    ArgSpec(args=['x', 'y', 'z'], varargs='args', varkw='kw', defaults=(1, 2))
 ok
 Trying:
-    @trace
-    def exotic_signature((x, y)=(1,2)): return x+y
+    from decorator import decorator
 Expecting nothing
 ok
 Trying:
-    print getargspec(exotic_signature)
+    print(decorator.__doc__)
 Expecting:
-    ArgSpec(args=[['x', 'y']], varargs=None, keywords=None, defaults=((1, 2),))
-ok
-Trying:
-    exotic_signature() 
-Expecting:
-    calling exotic_signature with args ((1, 2),), {}
-    3
+    decorator(caller) converts a caller function into a decorator
 ok
 Trying:
     @decorator
     def trace(f, *args, **kw):
-        print "calling %s with args %s, %s" % (f.func_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)
 Expecting nothing
 ok
@@ -125,16 +112,16 @@
 Expecting nothing
 ok
 Trying:
-    print read_data() # data is not available yet
+    print(read_data())  # data is not available yet
 Expecting:
     Please wait ...
 ok
 Trying:
-    time.sleep(1)  
+    time.sleep(1)
 Expecting nothing
 ok
 Trying:
-    print read_data() # data is not available yet
+    print(read_data())  # data is not available yet
 Expecting:
     Please wait ...
 ok
@@ -143,59 +130,38 @@
 Expecting nothing
 ok
 Trying:
-    print read_data() # data is not available yet
+    print(read_data())  # data is not available yet
 Expecting:
     Please wait ...
 ok
 Trying:
-    time.sleep(1.1) # after 3.1 seconds, data is available
+    time.sleep(1.1)  # after 3.1 seconds, data is available
 Expecting nothing
 ok
 Trying:
-    print read_data()
+    print(read_data())
 Expecting:
     some data
 ok
 Trying:
-    async = decorator(Async(threading.Thread))
-Expecting nothing
-ok
-Trying:
-    datalist = [] # for simplicity the written data are stored into a list.
-Expecting nothing
-ok
-Trying:
-    @async
-    def write(data):
-        # append data to the datalist by locking
-        with threading.Lock():
-            time.sleep(1) # emulate some long running operation
-            datalist.append(data)
-        # other operations not requiring a lock here
+    @decorator(Future)
+    def long_running(x):
+        time.sleep(.5)
+        return x
 Expecting nothing
 ok
 Trying:
-    write("data1") # doctest: +ELLIPSIS
-Expecting:
-    <Thread(write-1, started...)>
-ok
-Trying:
-    time.sleep(.1) # wait a bit, so we are sure data2 is written after data1
+    fut1 = long_running(1)
 Expecting nothing
 ok
 Trying:
-    write("data2") # doctest: +ELLIPSIS
-Expecting:
-    <Thread(write-2, started...)>
-ok
-Trying:
-    time.sleep(2) # wait for the writers to complete
+    fut2 = long_running(2)
 Expecting nothing
 ok
 Trying:
-    print datalist
+    fut1.result() + fut2.result()
 Expecting:
-    ['data1', 'data2']
+    3
 ok
 Trying:
     from contextlib import contextmanager
@@ -210,17 +176,8 @@
 Expecting nothing
 ok
 Trying:
-    ba = before_after('BEFORE', 'AFTER')
-Expecting nothing
-ok
-Trying:
-    type(ba)
-Expecting:
-    <class 'contextlib.GeneratorContextManager'>
-ok
-Trying:
-    with ba:
-        print 'hello'
+    with before_after('BEFORE', 'AFTER'):
+        print('hello')
 Expecting:
     BEFORE
     hello
@@ -228,7 +185,7 @@
 ok
 Trying:
     def f(*args, **kw): # a function with a generic signature
-        print args, kw
+        print(args, kw)
 Expecting nothing
 ok
 Trying:
@@ -246,80 +203,180 @@
 Expecting nothing
 ok
 Trying:
-    print f1.__source__
+    print(f1.__source__)
 Expecting:
     def f1(a, b):
         f(a, b)
     <BLANKLINE>
 ok
 Trying:
-    print inspect.getsource(example)
+    f1 = FunctionMaker.create(
+        'f1(a, b)', 'f(a, b)', dict(f=f), addsource=True, defaults=(None,))
+Expecting nothing
+ok
+Trying:
+    print(getargspec(f1))
+Expecting:
+    ArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(None,))
+ok
+Trying:
+    import inspect
+Expecting nothing
+ok
+Trying:
+    print(inspect.getsource(example))
 Expecting:
         def wrapper(*args, **kw):
             return func(*args, **kw)
     <BLANKLINE>
 ok
 Trying:
-    print inspect.getsource(factorial.__wrapped__)
+    print(inspect.getsource(factorial.__wrapped__))
 Expecting:
     @tail_recursive
     def factorial(n, acc=1):
         "The good old factorial"
-        if n == 0: return acc
+        if n == 0:
+            return acc
         return factorial(n-1, n*acc)
     <BLANKLINE>
 ok
 Trying:
-    print factorial(4) 
+    print(factorial(4))
 Expecting:
     24
 ok
 Trying:
+    writer = XMLWriter()
+Expecting nothing
+ok
+Trying:
+    writer.write(2.3)
+Expecting:
+    '<float>2.3</float>'
+ok
+Trying:
+    win(Paper(), Rock())
+Expecting:
+    1
+ok
+Trying:
+    win(Scissors(), Paper())
+Expecting:
+    1
+ok
+Trying:
+    win(Rock(), Scissors())
+Expecting:
+    1
+ok
+Trying:
+    win(Paper(), Paper())
+Expecting:
+    0
+ok
+Trying:
+    win(Rock(), Rock())
+Expecting:
+    0
+ok
+Trying:
+    win(Scissors(), Scissors())
+Expecting:
+    0
+ok
+Trying:
+    win(Rock(), Paper())
+Expecting:
+    -1
+ok
+Trying:
+    win(Paper(), Scissors())
+Expecting:
+    -1
+ok
+Trying:
+    win(Scissors(), Rock())
+Expecting:
+    -1
+ok
+Trying:
+    win(StrongRock(), Scissors())
+Expecting:
+    1
+ok
+Trying:
+    win.dispatch_info(StrongRock, Scissors)
+Expecting:
+    [('StrongRock', 'Scissors'), ('Rock', 'Scissors')]
+ok
+Trying:
+    issubclass(WithLength, collections.Sized)
+Expecting:
+    True
+ok
+Trying:
+    get_length(WithLength())
+Expecting:
+    0
+ok
+Trying:
+    _ = collections.Set.register(SomeSet)
+Expecting nothing
+ok
+Trying:
+    issubclass(SomeSet, collections.Set)
+Expecting:
+    True
+ok
+Trying:
+    get_length(SomeSet())  # NB: the implementation for Sized would give 0
+Expecting:
+    1
+ok
+Trying:
+    g, V = singledispatch_example2()
+Expecting nothing
+ok
+Trying:
+    g.dispatch_info(V)
+Expecting:
+    [('V',), ('Sized',), ('S',), ('Container',)]
+ok
+Trying:
     @trace
     def f():
         1/0
 Expecting nothing
 ok
 Trying:
-    f()
+    f() # doctest: +ELLIPSIS
 Expecting:
     Traceback (most recent call last):
       ...
          File "<string>", line 2, in f
-         File "<doctest __main__[18]>", line 4, in trace
+         File "<doctest __main__[22]>", line 4, in trace
            return f(*args, **kw)
-         File "<doctest __main__[47]>", line 3, in f
+         File "<doctest __main__[51]>", line 3, in f
            1/0
-    ZeroDivisionError: integer division or modulo by zero
+    ZeroDivisionError: ...
 ok
 Trying:
-    class C(object): 
-         @trace
-         def meth(self):
-             pass
+    @memoize
+    def getkeys(**kw):
+        return kw.keys()
 Expecting nothing
 ok
 Trying:
-    class C(object):
-         def meth(self):
-             pass
-Expecting nothing
-ok
-Trying:
-    trace(C.meth)
+    getkeys(func='a') # doctest: +ELLIPSIS
 Expecting:
     Traceback (most recent call last):
-      ...
-    TypeError: You are decorating a non function: <unbound method C.meth>
-ok
-Trying:
-    trace(C.meth.im_func) # doctest: +ELLIPSIS
-Expecting:
-    <function meth at 0x...>
+     ...
+    TypeError: _memoize() got multiple values for ... 'func'
 ok
 Trying:
     @trace
-    def f(_func_): print f
+    def f(_func_): print(f)
 Expecting:
     Traceback (most recent call last):
       ...
@@ -366,7 +423,7 @@
 Expecting nothing
 ok
 Trying:
-    a.insert() # err
+    a.insert() # doctest: +IGNORE_EXCEPTION_DETAIL
 Expecting:
     Traceback (most recent call last):
        ...
@@ -394,43 +451,84 @@
     hello michele
     AFTER
 ok
-31 items had no tests:
-    __main__.Action.delete
-    __main__.Action.insert
-    __main__.Action.view
-    __main__.Admin
-    __main__.Async
-    __main__.Async.__call__
-    __main__.Async.__init__
-    __main__.PermissionError
-    __main__.PowerUser
-    __main__.TailRecursive
-    __main__.TailRecursive.__call__
-    __main__.TailRecursive.__init__
-    __main__.User
-    __main__._memoize
-    __main__._trace
-    __main__.before_after
-    __main__.blocking
-    __main__.decorator_apply
-    __main__.example
-    __main__.fact
-    __main__.factorial
-    __main__.get_userclass
-    __main__.identity_dec
-    __main__.memoize
-    __main__.memoize_uw
-    __main__.on_closing
-    __main__.on_failure
-    __main__.on_success
-    __main__.restricted
-    __main__.tail_recursive
-    __main__.trace
+52 items had no tests:
+    documentation.Action.delete
+    documentation.Action.insert
+    documentation.Action.view
+    documentation.Admin
+    documentation.C
+    documentation.Future
+    documentation.Future.__init__
+    documentation.Future.result
+    documentation.Paper
+    documentation.PermissionError
+    documentation.PowerUser
+    documentation.Rock
+    documentation.Scissors
+    documentation.SomeSet
+    documentation.SomeSet.__len__
+    documentation.StrongRock
+    documentation.TailRecursive
+    documentation.TailRecursive.__call__
+    documentation.TailRecursive.__init__
+    documentation.User
+    documentation.WithLength
+    documentation.WithLength.__len__
+    documentation.XMLWriter
+    documentation.XMLWriter.__init__
+    documentation.XMLWriter.write
+    documentation._memoize
+    documentation._trace
+    documentation.before_after
+    documentation.blocking
+    documentation.decorator_apply
+    documentation.example
+    documentation.f1
+    documentation.fact
+    documentation.factorial
+    documentation.get_length
+    documentation.get_length_set
+    documentation.get_length_sized
+    documentation.get_userclass
+    documentation.identity_dec
+    documentation.memoize
+    documentation.memoize_uw
+    documentation.restricted
+    documentation.singledispatch_example1
+    documentation.singledispatch_example2
+    documentation.tail_recursive
+    documentation.trace
+    documentation.win
+    documentation.winPaperScissors
+    documentation.winRockPaper
+    documentation.winRockScissors
+    documentation.winStrongRockPaper
+    documentation.writefloat
 4 items passed all tests:
-  65 tests in __main__
-   3 tests in __main__.Action
-   2 tests in __main__.a_test_for_pylons
-   2 tests in __main__.hello
-72 tests in 35 items.
-72 passed and 0 failed.
+  78 tests in documentation
+   3 tests in documentation.Action
+   2 tests in documentation.a_test_for_pylons
+   2 tests in documentation.hello
+85 teok
+test_singledispatch1 (__main__.DocumentationTestCase) ... ok
+test_singledispatch2 (__main__.DocumentationTestCase) ... ok
+test_no_first_arg (__main__.ExtraTestCase) ... ok
+test_qualname (__main__.ExtraTestCase) ... ok
+test_signature (__main__.ExtraTestCase) ... ok
+test_unique_filenames (__main__.ExtraTestCase) ... ok
+test_c_classes (__main__.TestSingleDispatch) ... ok
+test_mro (__main__.TestSingleDispatch) ... ok
+test_mro_conflicts (__main__.TestSingleDispatch) ... ok
+test_register_abc (__main__.TestSingleDispatch) ... ok
+test_register_decorator (__main__.TestSingleDispatch) ... ok
+test_register_error (__main__.TestSingleDispatch) ... ok
+test_simple_overloads (__main__.TestSingleDispatch) ... ok
+test_wrapping_attributes (__main__.TestSingleDispatch) ... ok
+
+----------------------------------------------------------------------
+Ran 15 tests in
+
+OK
+sts in 56 items.
+85 passed and 0 failed.
 Test passed.
--- a/components/python/decorator/test/results-3.4-32.master	Tue Sep 20 08:35:58 2016 -0700
+++ b/components/python/decorator/test/results-3.4-32.master	Tue Sep 20 08:43:49 2016 -0700
@@ -1,18 +1,31 @@
+test (__main__.DocumentationTestCase) ... ok
+test_singledispatch1 (__main__.DocumentationTestCase) ... ok
+test_singledispatch2 (__main__.DocumentationTestCase) ... ok
+test_no_first_arg (__main__.ExtraTestCase) ... ok
+test_qualname (__main__.ExtraTestCase) ... ok
+test_signature (__main__.ExtraTestCase) ... ok
+test_unique_filenames (__main__.ExtraTestCase) ... ok
+test_c_classes (__main__.TestSingleDispatch) ... ok
+test_mro (__main__.TestSingleDispatch) ... ok
+test_mro_conflicts (__main__.TestSingleDispatch) ... ok
+test_register_abc (__main__.TestSingleDispatch) ... ok
+test_register_decorator (__main__.TestSingleDispatch) ... ok
+test_register_error (__main__.TestSingleDispatch) ... ok
+test_simple_overloads (__main__.TestSingleDispatch) ... ok
+test_wrapping_attributes (__main__.TestSingleDispatch) ... ok
+
+----------------------------------------------------------------------
+Ran 15 tests in
+
+OK
 Trying:
-    @memoize_uw
-    def f1(x):
-        time.sleep(1) # simulate some long computation
-        return x
-Expecting nothing
-ok
-Trying:
-    from inspect import getargspec 
+    from decorator import getargspec  # akin to inspect.getargspec
 Expecting nothing
 ok
 Trying:
     print(getargspec(f1))
 Expecting:
-    ArgSpec(args=[], varargs='args', keywords='kw', defaults=None)
+    ArgSpec(args=[], varargs='args', varkw='kw', defaults=None)
 ok
 Trying:
     f1(0, 1) # doctest: +IGNORE_EXCEPTION_DETAIL
@@ -22,7 +35,7 @@
     TypeError: f1() takes exactly 1 positional argument (2 given)
 ok
 Trying:
-    from decorator import decorator
+    from decorator import decorate
 Expecting nothing
 ok
 Trying:
@@ -43,9 +56,9 @@
     done
 ok
 Trying:
-    print(getargspec(heavy_computation)) 
+    print(getargspec(heavy_computation))
 Expecting:
-    ArgSpec(args=[], varargs=None, keywords=None, defaults=None)
+    ArgSpec(args=[], varargs=None, varkw=None, defaults=None)
 ok
 Trying:
     @trace
@@ -59,9 +72,9 @@
     calling f1 with args (0,), {}
 ok
 Trying:
-    print(getargspec(f1)) 
+    print(getargspec(f1))
 Expecting:
-    ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
+    ArgSpec(args=['x'], varargs=None, varkw=None, defaults=None)
 ok
 Trying:
     @trace
@@ -75,9 +88,9 @@
     calling f with args (0, 3, 2), {}
 ok
 Trying:
-    print(getargspec(f)) 
+    print(getargspec(f))
 Expecting:
-    ArgSpec(args=['x', 'y', 'z'], varargs='args', keywords='kw', defaults=(1, 2))
+    ArgSpec(args=['x', 'y', 'z'], varargs='args', varkw='kw', defaults=(1, 2))
 ok
 Trying:
     @trace
@@ -87,7 +100,7 @@
 Expecting nothing
 ok
 Trying:
-    from inspect import getfullargspec 
+    from inspect import getfullargspec
 Expecting nothing
 ok
 Trying:
@@ -124,11 +137,20 @@
 Expecting nothing
 ok
 Trying:
-    f.__annotations__ == f.__wrapped__.__annotations__
+    f.__annotations__ is f.__wrapped__.__annotations__
 Expecting:
     True
 ok
 Trying:
+    from decorator import decorator
+Expecting nothing
+ok
+Trying:
+    print(decorator.__doc__)
+Expecting:
+    decorator(caller) converts a caller function into a decorator
+ok
+Trying:
     @decorator
     def trace(f, *args, **kw):
         kwstr = ', '.join('%r: %r' % (k, kw[k]) for k in sorted(kw))
@@ -159,16 +181,7 @@
 Expecting nothing
 ok
 Trying:
-    print(read_data()) # data is not available yet
-Expecting:
-    Please wait ...
-ok
-Trying:
-    time.sleep(1)  
-Expecting nothing
-ok
-Trying:
-    print(read_data()) # data is not available yet
+    print(read_data())  # data is not available yet
 Expecting:
     Please wait ...
 ok
@@ -177,12 +190,21 @@
 Expecting nothing
 ok
 Trying:
-    print(read_data()) # data is not available yet
+    print(read_data())  # data is not available yet
 Expecting:
     Please wait ...
 ok
 Trying:
-    time.sleep(1.1) # after 3.1 seconds, data is available
+    time.sleep(1)
+Expecting nothing
+ok
+Trying:
+    print(read_data())  # data is not available yet
+Expecting:
+    Please wait ...
+ok
+Trying:
+    time.sleep(1.1)  # after 3.1 seconds, data is available
 Expecting nothing
 ok
 Trying:
@@ -191,45 +213,24 @@
     some data
 ok
 Trying:
-    async = decorator(Async(threading.Thread))
-Expecting nothing
-ok
-Trying:
-    datalist = [] # for simplicity the written data are stored into a list.
-Expecting nothing
-ok
-Trying:
-    @async
-    def write(data):
-        # append data to the datalist by locking
-        with threading.Lock():
-            time.sleep(1) # emulate some long running operation
-            datalist.append(data)
-        # other operations not requiring a lock here
+    @decorator(Future)
+    def long_running(x):
+        time.sleep(.5)
+        return x
 Expecting nothing
 ok
 Trying:
-    write("data1") # doctest: +ELLIPSIS
-Expecting:
-    <Thread(write-1, started...)>
-ok
-Trying:
-    time.sleep(.1) # wait a bit, so we are sure data2 is written after data1
+    fut1 = long_running(1)
 Expecting nothing
 ok
 Trying:
-    write("data2") # doctest: +ELLIPSIS
-Expecting:
-    <Thread(write-2, started...)>
-ok
-Trying:
-    time.sleep(2) # wait for the writers to complete
+    fut2 = long_running(2)
 Expecting nothing
 ok
 Trying:
-    print(datalist)
+    fut1.result() + fut2.result()
 Expecting:
-    ['data1', 'data2']
+    3
 ok
 Trying:
     from contextlib import contextmanager
@@ -244,16 +245,7 @@
 Expecting nothing
 ok
 Trying:
-    ba = before_after('BEFORE', 'AFTER')
-Expecting nothing
-ok
-Trying:
-    type(ba)
-Expecting:
-    <class 'contextlib._GeneratorContextManager'>
-ok
-Trying:
-    with ba:
+    with before_after('BEFORE', 'AFTER'):
         print('hello')
 Expecting:
     BEFORE
@@ -287,6 +279,20 @@
     <BLANKLINE>
 ok
 Trying:
+    f1 = FunctionMaker.create(
+        'f1(a, b)', 'f(a, b)', dict(f=f), addsource=True, defaults=(None,))
+Expecting nothing
+ok
+Trying:
+    print(getargspec(f1))
+Expecting:
+    ArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(None,))
+ok
+Trying:
+    import inspect
+Expecting nothing
+ok
+Trying:
     print(inspect.getsource(example))
 Expecting:
         def wrapper(*args, **kw):
@@ -299,7 +305,8 @@
     @tail_recursive
     def factorial(n, acc=1):
         "The good old factorial"
-        if n == 0: return acc
+        if n == 0:
+            return acc
         return factorial(n-1, n*acc)
     <BLANKLINE>
 ok
@@ -309,6 +316,103 @@
     24
 ok
 Trying:
+    writer = XMLWriter()
+Expecting nothing
+ok
+Trying:
+    writer.write(2.3)
+Expecting:
+    '<float>2.3</float>'
+ok
+Trying:
+    win(Paper(), Rock())
+Expecting:
+    1
+ok
+Trying:
+    win(Scissors(), Paper())
+Expecting:
+    1
+ok
+Trying:
+    win(Rock(), Scissors())
+Expecting:
+    1
+ok
+Trying:
+    win(Paper(), Paper())
+Expecting:
+    0
+ok
+Trying:
+    win(Rock(), Rock())
+Expecting:
+    0
+ok
+Trying:
+    win(Scissors(), Scissors())
+Expecting:
+    0
+ok
+Trying:
+    win(Rock(), Paper())
+Expecting:
+    -1
+ok
+Trying:
+    win(Paper(), Scissors())
+Expecting:
+    -1
+ok
+Trying:
+    win(Scissors(), Rock())
+Expecting:
+    -1
+ok
+Trying:
+    win(StrongRock(), Scissors())
+Expecting:
+    1
+ok
+Trying:
+    win.dispatch_info(StrongRock, Scissors)
+Expecting:
+    [('StrongRock', 'Scissors'), ('Rock', 'Scissors')]
+ok
+Trying:
+    issubclass(WithLength, collections.Sized)
+Expecting:
+    True
+ok
+Trying:
+    get_length(WithLength())
+Expecting:
+    0
+ok
+Trying:
+    _ = collections.Set.register(SomeSet)
+Expecting nothing
+ok
+Trying:
+    issubclass(SomeSet, collections.Set)
+Expecting:
+    True
+ok
+Trying:
+    get_length(SomeSet())  # NB: the implementation for Sized would give 0
+Expecting:
+    1
+ok
+Trying:
+    g, V = singledispatch_example2()
+Expecting nothing
+ok
+Trying:
+    g.dispatch_info(V)
+Expecting:
+    [('V',), ('Sized',), ('S',), ('Container',)]
+ok
+Trying:
     @trace
     def f():
         1/0
@@ -327,6 +431,19 @@
     ZeroDivisionError: ...
 ok
 Trying:
+    @memoize
+    def getkeys(**kw):
+        return kw.keys()
+Expecting nothing
+ok
+Trying:
+    getkeys(func='a') # doctest: +ELLIPSIS
+Expecting:
+    Traceback (most recent call last):
+     ...
+    TypeError: _memoize() got multiple values for ... 'func'
+ok
+Trying:
     @trace
     def f(_func_): print(f)
 Expecting:
@@ -375,7 +492,7 @@
 Expecting nothing
 ok
 Trying:
-    a.insert() # err
+    a.insert() # doctest: +IGNORE_EXCEPTION_DETAIL
 Expecting:
     Traceback (most recent call last):
        ...
@@ -419,6 +536,10 @@
 Expecting nothing
 ok
 Trying:
+    import inspect
+Expecting nothing
+ok
+Trying:
     inspect.getfullargspec(f)
 Expecting:
     FullArgSpec(args=[], varargs=None, varkw='kw', defaults=None, kwonlyargs=['a'], kwonlydefaults={'a': 1}, annotations={})
@@ -441,51 +562,72 @@
 Expecting nothing
 ok
 Trying:
-    f.__kwdefaults__ 
+    f.__kwdefaults__
 Expecting:
     {'kwonly': 2}
 ok
-31 items had no tests:
-    __main__.Action.delete
-    __main__.Action.insert
-    __main__.Action.view
-    __main__.Admin
-    __main__.Async
-    __main__.Async.__call__
-    __main__.Async.__init__
-    __main__.PermissionError
-    __main__.PowerUser
-    __main__.TailRecursive
-    __main__.TailRecursive.__call__
-    __main__.TailRecursive.__init__
-    __main__.User
-    __main__._memoize
-    __main__._trace
-    __main__.before_after
-    __main__.blocking
-    __main__.decorator_apply
-    __main__.example
-    __main__.fact
-    __main__.factorial
-    __main__.get_userclass
-    __main__.identity_dec
-    __main__.memoize
-    __main__.memoize_uw
-    __main__.on_closing
-    __main__.on_failure
-    __main__.on_success
-    __main__.restricted
-    __main__.tail_recursive
-    __main__.trace
+52 items had no tests:
+    documentation.Action.delete
+    documentation.Action.insert
+    documentation.Action.view
+    documentation.Admin
+    documentation.C
+    documentation.Future
+    documentation.Future.__init__
+    documentation.Future.result
+    documentation.Paper
+    documentation.PermissionError
+    documentation.PowerUser
+    documentation.Rock
+    documentation.Scissors
+    documentation.SomeSet
+    documentation.SomeSet.__len__
+    documentation.StrongRock
+    documentation.TailRecursive
+    documentation.TailRecursive.__call__
+    documentation.TailRecursive.__init__
+    documentation.User
+    documentation.WithLength
+    documentation.WithLength.__len__
+    documentation.XMLWriter
+    documentation.XMLWriter.__init__
+    documentation.XMLWriter.write
+    documentation._memoize
+    documentation._trace
+    documentation.before_after
+    documentation.blocking
+    documentation.decorator_apply
+    documentation.example
+    documentation.f1
+    documentation.fact
+    documentation.factorial
+    documentation.get_length
+    documentation.get_length_set
+    documentation.get_length_sized
+    documentation.get_userclass
+    documentation.identity_dec
+    documentation.memoize
+    documentation.memoize_uw
+    documentation.restricted
+    documentation.singledispatch_example1
+    documentation.singledispatch_example2
+    documentation.tail_recursive
+    documentation.trace
+    documentation.win
+    documentation.winPaperScissors
+    documentation.winRockPaper
+    documentation.winRockScissors
+    documentation.winStrongRockPaper
+    documentation.writefloat
 8 items passed all tests:
-  68 tests in __main__
-   3 tests in __main__.Action
-   2 tests in __main__.a_test_for_pylons
-   2 tests in __main__.hello
-   2 tests in __main__.test_kwonly_no_args
-   2 tests in __main__.test_kwonly_star_notation
-   2 tests in __main__.test_kwonlyargs
-   2 tests in __main__.test_kwonlydefaults
-83 tests in 39 items.
-83 passed and 0 failed.
+  88 tests in documentation
+   3 tests in documentation.Action
+   2 tests in documentation.a_test_for_pylons
+   2 tests in documentation.hello
+   2 tests in documentation.test_kwonly_no_args
+   3 tests in documentation.test_kwonly_star_notation
+   2 tests in documentation.test_kwonlyargs
+   2 tests in documentation.test_kwonlydefaults
+104 tests in 60 items.
+104 passed and 0 failed.
 Test passed.
--- a/components/python/decorator/test/results-3.5-32.master	Tue Sep 20 08:35:58 2016 -0700
+++ b/components/python/decorator/test/results-3.5-32.master	Tue Sep 20 08:43:49 2016 -0700
@@ -1,7 +1,633 @@
-Traceback (most recent call last):
-  File "documentation3.py", line 1155, in <module>
-    ba = before_after('BEFORE', 'AFTER') # ContextManager instance
-  File "<string>", line 2, in before_after
-  File "/usr/lib/python3.5/contextlib.py", line 38, in __init__
-    self.gen = func(*args, **kwds)
-TypeError: before_after() argument after ** must be a mapping, not str
+test (__main__.DocumentationTestCase) ... ok
+test_singledispatch1 (__main__.DocumentationTestCase) ... ok
+test_singledispatch2 (__main__.DocumentationTestCase) ... ok
+test_no_first_arg (__main__.ExtraTestCase) ... ok
+test_qualname (__main__.ExtraTestCase) ... ok
+test_signature (__main__.ExtraTestCase) ... ok
+test_unique_filenames (__main__.ExtraTestCase) ... ok
+test_c_classes (__main__.TestSingleDispatch) ... ok
+test_mro (__main__.TestSingleDispatch) ... ok
+test_mro_conflicts (__main__.TestSingleDispatch) ... ok
+test_register_abc (__main__.TestSingleDispatch) ... ok
+test_register_decorator (__main__.TestSingleDispatch) ... ok
+test_register_error (__main__.TestSingleDispatch) ... ok
+test_simple_overloads (__main__.TestSingleDispatch) ... ok
+test_wrapping_attributes (__main__.TestSingleDispatch) ... ok
+
+----------------------------------------------------------------------
+Ran 15 tests in
+
+OK
+Trying:
+    from decorator import getargspec  # akin to inspect.getargspec
+Expecting nothing
+ok
+Trying:
+    print(getargspec(f1))
+Expecting:
+    ArgSpec(args=[], varargs='args', varkw='kw', defaults=None)
+ok
+Trying:
+    f1(0, 1) # doctest: +IGNORE_EXCEPTION_DETAIL
+Expecting:
+    Traceback (most recent call last):
+       ...
+    TypeError: f1() takes exactly 1 positional argument (2 given)
+ok
+Trying:
+    from decorator import decorate
+Expecting nothing
+ok
+Trying:
+    @memoize
+    def heavy_computation():
+        time.sleep(2)
+        return "done"
+Expecting nothing
+ok
+Trying:
+    print(heavy_computation()) # the first time it will take 2 seconds
+Expecting:
+    done
+ok
+Trying:
+    print(heavy_computation()) # the second time it will be instantaneous
+Expecting:
+    done
+ok
+Trying:
+    print(getargspec(heavy_computation))
+Expecting:
+    ArgSpec(args=[], varargs=None, varkw=None, defaults=None)
+ok
+Trying:
+    @trace
+    def f1(x):
+        pass
+Expecting nothing
+ok
+Trying:
+    f1(0)
+Expecting:
+    calling f1 with args (0,), {}
+ok
+Trying:
+    print(getargspec(f1))
+Expecting:
+    ArgSpec(args=['x'], varargs=None, varkw=None, defaults=None)
+ok
+Trying:
+    @trace
+    def f(x, y=1, z=2, *args, **kw):
+        pass
+Expecting nothing
+ok
+Trying:
+    f(0, 3)
+Expecting:
+    calling f with args (0, 3, 2), {}
+ok
+Trying:
+    print(getargspec(f))
+Expecting:
+    ArgSpec(args=['x', 'y', 'z'], varargs='args', varkw='kw', defaults=(1, 2))
+ok
+Trying:
+    @trace
+    def f(x: 'the first argument', y: 'default argument'=1, z=2,
+          *args: 'varargs', **kw: 'kwargs'):
+        pass
+Expecting nothing
+ok
+Trying:
+    from inspect import getfullargspec
+Expecting nothing
+ok
+Trying:
+    argspec = getfullargspec(f)
+Expecting nothing
+ok
+Trying:
+    argspec.args
+Expecting:
+    ['x', 'y', 'z']
+ok
+Trying:
+    argspec.varargs
+Expecting:
+    'args'
+ok
+Trying:
+    argspec.varkw
+Expecting:
+    'kw'
+ok
+Trying:
+    argspec.defaults
+Expecting:
+    (1, 2)
+ok
+Trying:
+    argspec.kwonlyargs
+Expecting:
+    []
+ok
+Trying:
+    argspec.kwonlydefaults
+Expecting nothing
+ok
+Trying:
+    f.__annotations__ is f.__wrapped__.__annotations__
+Expecting:
+    True
+ok
+Trying:
+    from decorator import decorator
+Expecting nothing
+ok
+Trying:
+    print(decorator.__doc__)
+Expecting:
+    decorator(caller) converts a caller function into a decorator
+ok
+Trying:
+    @decorator
+    def trace(f, *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)
+Expecting nothing
+ok
+Trying:
+    trace # doctest: +ELLIPSIS
+Expecting:
+    <function trace at 0x...>
+ok
+Trying:
+    @trace
+    def func(): pass
+Expecting nothing
+ok
+Trying:
+    func()
+Expecting:
+    calling func with args (), {}
+ok
+Trying:
+    @blocking("Please wait ...")
+    def read_data():
+        time.sleep(3) # simulate a blocking resource
+        return "some data"
+Expecting nothing
+ok
+Trying:
+    print(read_data())  # data is not available yet
+Expecting:
+    Please wait ...
+ok
+Trying:
+    time.sleep(1)
+Expecting nothing
+ok
+Trying:
+    print(read_data())  # data is not available yet
+Expecting:
+    Please wait ...
+ok
+Trying:
+    time.sleep(1)
+Expecting nothing
+ok
+Trying:
+    print(read_data())  # data is not available yet
+Expecting:
+    Please wait ...
+ok
+Trying:
+    time.sleep(1.1)  # after 3.1 seconds, data is available
+Expecting nothing
+ok
+Trying:
+    print(read_data())
+Expecting:
+    some data
+ok
+Trying:
+    @decorator(Future)
+    def long_running(x):
+        time.sleep(.5)
+        return x
+Expecting nothing
+ok
+Trying:
+    fut1 = long_running(1)
+Expecting nothing
+ok
+Trying:
+    fut2 = long_running(2)
+Expecting nothing
+ok
+Trying:
+    fut1.result() + fut2.result()
+Expecting:
+    3
+ok
+Trying:
+    from contextlib import contextmanager
+Expecting nothing
+ok
+Trying:
+    @contextmanager
+    def before_after(before, after):
+        print(before)
+        yield
+        print(after)
+Expecting nothing
+ok
+Trying:
+    with before_after('BEFORE', 'AFTER'):
+        print('hello')
+Expecting:
+    BEFORE
+    hello
+    AFTER
+ok
+Trying:
+    def f(*args, **kw): # a function with a generic signature
+        print(args, kw)
+Expecting nothing
+ok
+Trying:
+    f1 = FunctionMaker.create('f1(a, b)', 'f(a, b)', dict(f=f))
+Expecting nothing
+ok
+Trying:
+    f1(1,2)
+Expecting:
+    (1, 2) {}
+ok
+Trying:
+    f1 = FunctionMaker.create(
+        'f1(a, b)', 'f(a, b)', dict(f=f), addsource=True)
+Expecting nothing
+ok
+Trying:
+    print(f1.__source__)
+Expecting:
+    def f1(a, b):
+        f(a, b)
+    <BLANKLINE>
+ok
+Trying:
+    f1 = FunctionMaker.create(
+        'f1(a, b)', 'f(a, b)', dict(f=f), addsource=True, defaults=(None,))
+Expecting nothing
+ok
+Trying:
+    print(getargspec(f1))
+Expecting:
+    ArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(None,))
+ok
+Trying:
+    import inspect
+Expecting nothing
+ok
+Trying:
+    print(inspect.getsource(example))
+Expecting:
+        def wrapper(*args, **kw):
+            return func(*args, **kw)
+    <BLANKLINE>
+ok
+Trying:
+    print(inspect.getsource(factorial.__wrapped__))
+Expecting:
+    @tail_recursive
+    def factorial(n, acc=1):
+        "The good old factorial"
+        if n == 0:
+            return acc
+        return factorial(n-1, n*acc)
+    <BLANKLINE>
+ok
+Trying:
+    print(factorial(4))
+Expecting:
+    24
+ok
+Trying:
+    writer = XMLWriter()
+Expecting nothing
+ok
+Trying:
+    writer.write(2.3)
+Expecting:
+    '<float>2.3</float>'
+ok
+Trying:
+    win(Paper(), Rock())
+Expecting:
+    1
+ok
+Trying:
+    win(Scissors(), Paper())
+Expecting:
+    1
+ok
+Trying:
+    win(Rock(), Scissors())
+Expecting:
+    1
+ok
+Trying:
+    win(Paper(), Paper())
+Expecting:
+    0
+ok
+Trying:
+    win(Rock(), Rock())
+Expecting:
+    0
+ok
+Trying:
+    win(Scissors(), Scissors())
+Expecting:
+    0
+ok
+Trying:
+    win(Rock(), Paper())
+Expecting:
+    -1
+ok
+Trying:
+    win(Paper(), Scissors())
+Expecting:
+    -1
+ok
+Trying:
+    win(Scissors(), Rock())
+Expecting:
+    -1
+ok
+Trying:
+    win(StrongRock(), Scissors())
+Expecting:
+    1
+ok
+Trying:
+    win.dispatch_info(StrongRock, Scissors)
+Expecting:
+    [('StrongRock', 'Scissors'), ('Rock', 'Scissors')]
+ok
+Trying:
+    issubclass(WithLength, collections.Sized)
+Expecting:
+    True
+ok
+Trying:
+    get_length(WithLength())
+Expecting:
+    0
+ok
+Trying:
+    _ = collections.Set.register(SomeSet)
+Expecting nothing
+ok
+Trying:
+    issubclass(SomeSet, collections.Set)
+Expecting:
+    True
+ok
+Trying:
+    get_length(SomeSet())  # NB: the implementation for Sized would give 0
+Expecting:
+    1
+ok
+Trying:
+    g, V = singledispatch_example2()
+Expecting nothing
+ok
+Trying:
+    g.dispatch_info(V)
+Expecting:
+    [('V',), ('Sized',), ('S',), ('Container',)]
+ok
+Trying:
+    @trace
+    def f():
+        1/0
+Expecting nothing
+ok
+Trying:
+    f() # doctest: +ELLIPSIS
+Expecting:
+    Traceback (most recent call last):
+      ...
+         File "<string>", line 2, in f
+         File "<doctest __main__[22]>", line 4, in trace
+           return f(*args, **kw)
+         File "<doctest __main__[51]>", line 3, in f
+           1/0
+    ZeroDivisionError: ...
+ok
+Trying:
+    @memoize
+    def getkeys(**kw):
+        return kw.keys()
+Expecting nothing
+ok
+Trying:
+    getkeys(func='a') # doctest: +ELLIPSIS
+Expecting:
+    Traceback (most recent call last):
+     ...
+    TypeError: _memoize() got multiple values for ... 'func'
+ok
+Trying:
+    @trace
+    def f(_func_): print(f)
+Expecting:
+    Traceback (most recent call last):
+      ...
+    NameError: _func_ is overridden in
+    def f(_func_):
+        return _call_(_func_, _func_)
+ok
+Trying:
+    def f(): pass # the original function
+Expecting nothing
+ok
+Trying:
+    f.attr1 = "something" # setting an attribute
+Expecting nothing
+ok
+Trying:
+    f.attr2 = "something else" # setting another attribute
+Expecting nothing
+ok
+Trying:
+    traced_f = trace(f) # the decorated function
+Expecting nothing
+ok
+Trying:
+    traced_f.attr1
+Expecting:
+    'something'
+ok
+Trying:
+    traced_f.attr2 = "something different" # setting attr
+Expecting nothing
+ok
+Trying:
+    f.attr2 # the original attribute did not change
+Expecting:
+    'something else'
+ok
+Trying:
+    a = Action()
+Expecting nothing
+ok
+Trying:
+    a.view() # ok
+Expecting nothing
+ok
+Trying:
+    a.insert() # doctest: +IGNORE_EXCEPTION_DETAIL
+Expecting:
+    Traceback (most recent call last):
+       ...
+    PermissionError: User does not have the permission to run insert!
+ok
+Trying:
+    decorator(_memoize).__name__
+Expecting:
+    '_memoize'
+ok
+Trying:
+    factorial.__doc__
+Expecting:
+    'The good old factorial'
+ok
+Trying:
+    ba.__class__.__name__
+Expecting:
+    'ContextManager'
+ok
+Trying:
+    hello('michele')
+Expecting:
+    BEFORE
+    hello michele
+    AFTER
+ok
+Trying:
+    @trace
+    def f(**kw): pass
+Expecting nothing
+ok
+Trying:
+    f()
+Expecting:
+    calling f with args (), {}
+ok
+Trying:
+    @trace
+    def f(*, a=1, **kw): pass
+Expecting nothing
+ok
+Trying:
+    import inspect
+Expecting nothing
+ok
+Trying:
+    inspect.getfullargspec(f)
+Expecting:
+    FullArgSpec(args=[], varargs=None, varkw='kw', defaults=None, kwonlyargs=['a'], kwonlydefaults={'a': 1}, annotations={})
+ok
+Trying:
+    @trace
+    def func(a, b, *args, y=2, z=3, **kwargs):
+        return y, z
+Expecting nothing
+ok
+Trying:
+    func('a', 'b', 'c', 'd', 'e', y='y', z='z', cat='dog')
+Expecting:
+    calling func with args ('a', 'b', 'c', 'd', 'e'), {'cat': 'dog', 'y': 'y', 'z': 'z'}
+    ('y', 'z')
+ok
+Trying:
+    @trace
+    def f(arg, defarg=1, *args, kwonly=2): pass
+Expecting nothing
+ok
+Trying:
+    f.__kwdefaults__
+Expecting:
+    {'kwonly': 2}
+ok
+52 items had no tests:
+    documentation.Action.delete
+    documentation.Action.insert
+    documentation.Action.view
+    documentation.Admin
+    documentation.C
+    documentation.Future
+    documentation.Future.__init__
+    documentation.Future.result
+    documentation.Paper
+    documentation.PermissionError
+    documentation.PowerUser
+    documentation.Rock
+    documentation.Scissors
+    documentation.SomeSet
+    documentation.SomeSet.__len__
+    documentation.StrongRock
+    documentation.TailRecursive
+    documentation.TailRecursive.__call__
+    documentation.TailRecursive.__init__
+    documentation.User
+    documentation.WithLength
+    documentation.WithLength.__len__
+    documentation.XMLWriter
+    documentation.XMLWriter.__init__
+    documentation.XMLWriter.write
+    documentation._memoize
+    documentation._trace
+    documentation.before_after
+    documentation.blocking
+    documentation.decorator_apply
+    documentation.example
+    documentation.f1
+    documentation.fact
+    documentation.factorial
+    documentation.get_length
+    documentation.get_length_set
+    documentation.get_length_sized
+    documentation.get_userclass
+    documentation.identity_dec
+    documentation.memoize
+    documentation.memoize_uw
+    documentation.restricted
+    documentation.singledispatch_example1
+    documentation.singledispatch_example2
+    documentation.tail_recursive
+    documentation.trace
+    documentation.win
+    documentation.winPaperScissors
+    documentation.winRockPaper
+    documentation.winRockScissors
+    documentation.winStrongRockPaper
+    documentation.writefloat
+8 items passed all tests:
+  88 tests in documentation
+   3 tests in documentation.Action
+   2 tests in documentation.a_test_for_pylons
+   2 tests in documentation.hello
+   2 tests in documentation.test_kwonly_no_args
+   3 tests in documentation.test_kwonly_star_notation
+   2 tests in documentation.test_kwonlyargs
+   2 tests in documentation.test_kwonlydefaults
+104 tests in 60 items.
+104 passed and 0 failed.
+Test passed.