summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MANIFEST.in2
-rw-r--r--documentation.pdf2
-rw-r--r--documentation.py58
-rw-r--r--documentation3.pdf2
-rw-r--r--src/decorator.py39
-rw-r--r--test.py9
6 files changed, 51 insertions, 61 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index 52e7659..e69de29 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +0,0 @@
-include documentation.py documentation3.py
-exclude Makefile
diff --git a/documentation.pdf b/documentation.pdf
index c57f0ac..611972e 100644
--- a/documentation.pdf
+++ b/documentation.pdf
@@ -1,5 +1,5 @@
%PDF-1.4
-%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
+%���� ReportLab Generated PDF document http://www.reportlab.com
% 'BasicFonts': class PDFDictionary
1 0 obj
% The standard fonts dictionary
diff --git a/documentation.py b/documentation.py
index 3d5a5c0..17de544 100644
--- a/documentation.py
+++ b/documentation.py
@@ -462,6 +462,10 @@ will returns instances of ``ContextManager``, a subclass of
``contextlib.GeneratorContextManager`` with a ``__call__`` method
acting as a signature-preserving decorator.
+**Disclaimer**: the ``contextmanager`` decorator is an *experimental* feature:
+it may go away in future versions of the decorator module. Use it at your
+own risk.
+
The ``FunctionMaker`` class
---------------------------------------------------------------
@@ -775,9 +779,9 @@ you will get a ``NameError``:
Finally, the implementation is such that the decorated function
attribute ``.func_globals`` is a *copy* of the original function
-attribute. Moreover the decorated function contains
-a *copy* of the original function dictionary
-(``vars(decorated_f) is not vars(f)``):
+attribute. On the other hand the function attribute dictionary
+of the decorated function is just a reference to the
+original function dictionary, i.e. ``vars(decorated_f) is vars(f)``:
.. code-block:: python
@@ -790,45 +794,22 @@ a *copy* of the original function dictionary
>>> traced_f.attr1
'something'
>>> traced_f.attr2 = "something different" # setting attr
- >>> f.attr2 # the original attribute did not change
- 'something else'
+ >>> f.attr2 # the original attribute did change
+ 'something different'
Compatibility notes
---------------------------------------------------------------
-Version 3.3 is the first version of the ``decorator`` module to fully
-support Python 3, including `function annotations`_. Version 3.2 was the
-first version to support Python 3 via the ``2to3`` conversion tool
-invoked in the build process by the distribute_ project, the Python
-3-compatible replacement of easy_install. The hard work (for me) has
-been converting the documentation and the doctests. This has been
-possible only after that docutils_ and pygments_ have been ported to
-Python 3.
-
-Version 3 of the ``decorator`` module do not contain any backward
-incompatible change, apart from the removal of the functions
-``get_info`` and ``new_wrapper``, which have been deprecated for
-years. ``get_info`` has been removed since it was little used and
-since it had to be changed anyway to work with Python 3.0;
-``new_wrapper`` has been removed since it was useless: its major use
-case (converting signature changing decorators to signature preserving
-decorators) has been subsumed by ``decorator_apply``, whereas the other use
-case can be managed with the ``FunctionMaker``.
-
-There are a few changes in the documentation: I removed the
-``decorator_factory`` example, which was confusing some of my users,
-and I removed the part about exotic signatures in the Python 3
-documentation, since Python 3 does not support them.
-
-Finally ``decorator`` cannot be used as a class decorator and the
-`functionality introduced in version 2.3`_ has been removed. That
-means that in order to define decorator factories with classes you
-need to define the ``__call__`` method explicitly (no magic anymore).
-All these changes should not cause any trouble, since they were
-all rarely used features. Should you have any trouble, you can always
-downgrade to the 2.3 version.
-
-The examples shown here have been tested with Python 2.6. Python 2.4
+This version fully supports Python 3, including `function
+annotations`_. Moreover it is the first version to support
+generic callers, i.e. callable objects with the right
+signature, not necessarily functions. ``contextmanager``
+will not work in Python 2.4. The decorated function
+dictionary is now the same of the original function
+dictionary, wheread in past versions they were
+different objects.
+
+The examples shown here have been tested with Python 2.7 and 3.3. Python 2.4
is also supported - of course the examples requiring the ``with``
statement will not work there. Python 2.5 works fine, but if you
run the examples in the interactive interpreter
@@ -838,7 +819,6 @@ tuple. That means that running the file
``documentation.py`` under Python 2.5 will print a few errors, but
they are not serious.
-.. _functionality introduced in version 2.3: http://www.phyast.pitt.edu/~micheles/python/documentation.html#class-decorators-and-decorator-factories
.. _function annotations: http://www.python.org/dev/peps/pep-3107/
.. _distribute: http://packages.python.org/distribute/
.. _docutils: http://docutils.sourceforge.net/
diff --git a/documentation3.pdf b/documentation3.pdf
index cdf4f35..ffdcc6c 100644
--- a/documentation3.pdf
+++ b/documentation3.pdf
@@ -1,5 +1,5 @@
%PDF-1.4
-%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
+%���� ReportLab Generated PDF document http://www.reportlab.com
% 'BasicFonts': class PDFDictionary
1 0 obj
% The standard fonts dictionary
diff --git a/src/decorator.py b/src/decorator.py
index e003914..e1187bd 100644
--- a/src/decorator.py
+++ b/src/decorator.py
@@ -32,7 +32,7 @@ Decorator module, see http://pypi.python.org/pypi/decorator
for the documentation.
"""
-__version__ = '3.4.0'
+__version__ = '3.4.1'
__all__ = ["decorator", "FunctionMaker", "contextmanager"]
@@ -104,7 +104,7 @@ class FunctionMaker(object):
allshortargs.append('**' + self.varkw)
self.signature = ', '.join(allargs)
self.shortsignature = ', '.join(allshortargs)
- self.dict = func.__dict__.copy()
+ self.dict = func.__dict__
# func=None happens when decorating a caller
if name:
self.name = name
@@ -197,7 +197,7 @@ def decorator(caller, func=None):
evaldict['_func_'] = func
return FunctionMaker.create(
func, "return _call_(_func_, %(shortsignature)s)",
- evaldict, undecorated=func, __wrapped__=func)
+ evaldict, __wrapped__=func)
else: # returns a decorator
if inspect.isclass(caller):
name = caller.__name__.lower()
@@ -206,8 +206,10 @@ def decorator(caller, func=None):
'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__
+ if caller.__name__ == '<lambda>':
+ name = '_lambda_'
+ else:
+ name = caller.__name__
callerfunc = caller
doc = caller.__doc__
fun = getfullargspec(callerfunc).args[0] # first arg
@@ -222,8 +224,7 @@ def decorator(caller, func=None):
return FunctionMaker.create(
'%s(%s)' % (name, fun),
'return decorator(_call_, %s)' % fun,
- evaldict, undecorated=caller, __wrapped__=caller,
- doc=doc, module=caller.__module__)
+ evaldict, call=caller, doc=doc, module=caller.__module__)
######################### contextmanager ########################
@@ -236,16 +237,22 @@ def __call__(self, func):
try: # Python >= 3.2
from contextlib import _GeneratorContextManager
- ContextManager = type(
- 'ContextManager', (_GeneratorContextManager,), dict(__call__=__call__))
+ class ContextManager(_GeneratorContextManager):
+ __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__))
-
+ try:
+ from contextlib import GeneratorContextManager
+ except ImportError: # Python 2.4
+ class ContextManager(object):
+ def __init__(self, g, *a, **k):
+ raise RuntimeError(
+ 'You cannot used contextmanager in Python 2.4!')
+ else:
+ class ContextManager(GeneratorContextManager):
+ def __init__(self, g, *a, **k):
+ return GeneratorContextManager.__init__(self, g(*a, **k))
+ __call__ = __call__
+
contextmanager = decorator(ContextManager)
diff --git a/test.py b/test.py
index 455fa1c..460c36a 100644
--- a/test.py
+++ b/test.py
@@ -1,5 +1,5 @@
"""
-Some simple tests executable with nose or py.test
+Some simple tests
"""
import os
@@ -15,7 +15,7 @@ def f1():
"f1"
def getfname(func):
- fname = os.path.basename(func.func_globals['__file__'])
+ fname = os.path.basename(func.__globals__['__file__'])
return os.path.splitext(fname)[0] + '.py'
def test0():
@@ -27,3 +27,8 @@ def test1():
this = getfname(f1)
assert this == 'test.py', this
print(f1.__doc__)
+
+if __name__ == '__main__':
+ for name, test in list(globals().items()):
+ if name.startswith('test'):
+ test()