diff options
| author | Michele Simionato <michele.simionato@gmail.com> | 2015-03-16 11:13:06 +0100 |
|---|---|---|
| committer | Michele Simionato <michele.simionato@gmail.com> | 2015-03-16 11:13:06 +0100 |
| commit | 5d0a05302b850386b2b71ff281c58db333ac7e78 (patch) | |
| tree | e8ccc92a2336ee1a5bed53a503776888a3929e91 /src | |
| parent | 3e2bd43069fa1837d77f8ab2079044a44aaedd66 (diff) | |
| download | python-decorator-git-5d0a05302b850386b2b71ff281c58db333ac7e78.tar.gz | |
Initial changes for decorator 3.4.1
Diffstat (limited to 'src')
| -rw-r--r-- | src/decorator.py | 88 |
1 files changed, 49 insertions, 39 deletions
diff --git a/src/decorator.py b/src/decorator.py index e1187bd..07d99cb 100644 --- a/src/decorator.py +++ b/src/decorator.py @@ -1,4 +1,4 @@ -########################## LICENCE ############################### +# ######################### LICENCE ############################ # # Copyright (c) 2005-2012, Michele Simionato # All rights reserved. @@ -7,12 +7,12 @@ # modification, are permitted provided that the following conditions are # met: -# Redistributions of source code must retain the above copyright +# 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. +# distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -36,9 +36,13 @@ __version__ = '3.4.1' __all__ = ["decorator", "FunctionMaker", "contextmanager"] -import sys, re, inspect +import re +import sys +import inspect + if sys.version >= '3': from inspect import getfullargspec + def get_init(cls): return cls.__init__ else: @@ -49,16 +53,19 @@ else: inspect.getargspec(f) self.kwonlyargs = [] self.kwonlydefaults = None + def __iter__(self): yield self.args 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*\(') + # basic functionality class FunctionMaker(object): """ @@ -72,8 +79,8 @@ class FunctionMaker(object): if func: # func can be a class or a callable, but not an instance method self.name = func.__name__ - if self.name == '<lambda>': # small hack for lambda functions - self.name = '_lambda_' + if self.name == '<lambda>': # small hack for lambda functions + self.name = '_lambda_' self.doc = func.__doc__ self.module = func.__module__ if inspect.isfunction(func): @@ -84,18 +91,18 @@ class FunctionMaker(object): setattr(self, a, getattr(argspec, a)) for i, arg in enumerate(self.args): setattr(self, 'arg%d' % i, arg) - if sys.version < '3': # easy way - self.shortsignature = self.signature = \ + if sys.version < '3': # easy way + self.shortsignature = self.signature = ( inspect.formatargspec( - formatvalue=lambda val: "", *argspec)[1:-1] - else: # Python 3 way + formatvalue=lambda val: "", *argspec)[1:-1]) + else: # Python 3 way allargs = list(self.args) allshortargs = list(self.args) if self.varargs: allargs.append('*' + self.varargs) allshortargs.append('*' + self.varargs) elif self.kwonlyargs: - allargs.append('*') # single star syntax + allargs.append('*') # single star syntax for a in self.kwonlyargs: allargs.append('%s=None' % a) allshortargs.append('%s=%s' % (a, a)) @@ -137,19 +144,19 @@ class FunctionMaker(object): def make(self, src_templ, evaldict=None, addsource=False, **attrs): "Make a new function from a given template and update the signature" - src = src_templ % vars(self) # expand name and signature + src = src_templ % vars(self) # expand name and signature evaldict = evaldict or {} mo = DEF.match(src) if mo is None: raise SyntaxError('not a valid function template\n%s' % src) - name = mo.group(1) # extract the function name - names = set([name] + [arg.strip(' *') for arg in - self.shortsignature.split(',')]) + name = mo.group(1) # extract the function name + names = set([name] + [arg.strip(' *') for arg in + self.shortsignature.split(',')]) for n in names: if n in ('_func_', '_call_'): raise NameError('%s is overridden in\n%s' % (n, src)) - if not src.endswith('\n'): # add a newline just for safety - src += '\n' # this is needed in old versions of Python + if not src.endswith('\n'): # add a newline just for safety + src += '\n' # this is needed in old versions of Python try: code = compile(src, '<string>', 'single') # print >> sys.stderr, 'Compiling %s' % src @@ -169,42 +176,43 @@ class FunctionMaker(object): doc=None, module=None, addsource=True, **attrs): """ Create a function from the strings name, signature and body. - evaldict is the evaluation dictionary. If addsource is true an attribute - __source__ is added to the result. The attributes attrs are added, - if any. + evaldict is the evaluation dictionary. If addsource is true an + attribute __source__ is added to the result. The attributes attrs + are added, if any. """ - if isinstance(obj, str): # "name(signature)" + if isinstance(obj, str): # "name(signature)" name, rest = obj.strip().split('(', 1) - signature = rest[:-1] #strip a right parens + signature = rest[:-1] # strip a right parens func = None - else: # a function + else: # a function name = None signature = None func = obj self = cls(func, name, signature, defaults, doc, module) ibody = '\n'.join(' ' + line for line in body.splitlines()) - return self.make('def %(name)s(%(signature)s):\n' + ibody, - evaldict, addsource, **attrs) - + return self.make('def %(name)s(%(signature)s):\n' + ibody, + evaldict, addsource, **attrs) + + def decorator(caller, func=None): """ decorator(caller) converts a caller function into a decorator; decorator(caller, func) decorates a function using a caller. """ - if func is not None: # returns a decorated function + if func is not None: # returns a decorated function evaldict = func.func_globals.copy() evaldict['_call_'] = caller evaldict['_func_'] = func return FunctionMaker.create( func, "return _call_(_func_, %(shortsignature)s)", evaldict, __wrapped__=func) - else: # returns a decorator + else: # returns a decorator 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 + fun = getfullargspec(callerfunc).args[1] # second arg elif inspect.isfunction(caller): if caller.__name__ == '<lambda>': name = '_lambda_' @@ -212,21 +220,22 @@ def decorator(caller, func=None): name = caller.__name__ callerfunc = caller doc = caller.__doc__ - fun = getfullargspec(callerfunc).args[0] # first arg - else: # assume caller is an object with a __call__ method + 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 + fun = getfullargspec(callerfunc).args[1] # second arg evaldict = callerfunc.func_globals.copy() evaldict['_call_'] = caller evaldict['decorator'] = decorator return FunctionMaker.create( - '%s(%s)' % (name, fun), + '%s(%s)' % (name, fun), 'return decorator(_call_, %s)' % fun, evaldict, call=caller, doc=doc, module=caller.__module__) -######################### contextmanager ######################## + +# ####################### contextmanager ####################### # def __call__(self, func): 'Context manager decorator' @@ -234,17 +243,18 @@ def __call__(self, func): func, "with _self_: return _func_(%(shortsignature)s)", dict(_self_=self, _func_=func), __wrapped__=func) -try: # Python >= 3.2 +try: # Python >= 3.2 + + from contextlib import _GeneratorContextManager - from contextlib import _GeneratorContextManager class ContextManager(_GeneratorContextManager): - __call__=__call__ + __call__ = __call__ -except ImportError: # Python >= 2.5 +except ImportError: # Python >= 2.5 try: from contextlib import GeneratorContextManager - except ImportError: # Python 2.4 + except ImportError: # Python 2.4 class ContextManager(object): def __init__(self, g, *a, **k): raise RuntimeError( |
