diff options
| -rw-r--r-- | MANIFEST.in | 2 | ||||
| -rw-r--r-- | documentation.pdf | 2 | ||||
| -rw-r--r-- | documentation.py | 58 | ||||
| -rw-r--r-- | documentation3.pdf | 2 | ||||
| -rw-r--r-- | src/decorator.py | 39 | ||||
| -rw-r--r-- | test.py | 9 |
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) @@ -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() |
