summaryrefslogtreecommitdiff
path: root/decorator/src/decorator.py
diff options
context:
space:
mode:
Diffstat (limited to 'decorator/src/decorator.py')
-rw-r--r--decorator/src/decorator.py99
1 files changed, 65 insertions, 34 deletions
diff --git a/decorator/src/decorator.py b/decorator/src/decorator.py
index 3dbbdd4..e003914 100644
--- a/decorator/src/decorator.py
+++ b/decorator/src/decorator.py
@@ -32,28 +32,15 @@ Decorator module, see http://pypi.python.org/pypi/decorator
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 @@ else:
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 @@ class FunctionMaker(object):
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 @@ def decorator(caller, func=None):
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)