summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/decorator.egg-info/PKG-INFO100
-rw-r--r--src/decorator.egg-info/SOURCES.txt11
-rw-r--r--src/decorator.egg-info/dependency_links.txt1
-rw-r--r--src/decorator.egg-info/not-zip-safe1
-rw-r--r--src/decorator.egg-info/top_level.txt1
-rw-r--r--src/decorator.py251
6 files changed, 365 insertions, 0 deletions
diff --git a/src/decorator.egg-info/PKG-INFO b/src/decorator.egg-info/PKG-INFO
new file mode 100644
index 0000000..8491af5
--- /dev/null
+++ b/src/decorator.egg-info/PKG-INFO
@@ -0,0 +1,100 @@
+Metadata-Version: 1.1
+Name: decorator
+Version: 3.4.0
+Summary: Better living through Python with decorators
+Home-page: http://pypi.python.org/pypi/decorator
+Author: Michele Simionato
+Author-email: michele.simionato@gmail.com
+License: BSD License
+Description: Decorator module
+ =================
+
+
+ :Author: Michele Simionato
+ :E-mail: michele.simionato@gmail.com
+ :Requires: Python 2.4+
+ :Download page: http://pypi.python.org/pypi/decorator
+ :Installation: ``easy_install decorator``
+ :License: BSD license
+
+ Installation
+ -------------
+
+ If you are lazy, just perform
+
+ $ easy_install decorator
+
+ which will install just the module on your system. Notice that
+ Python 3 requires the easy_install version of the distribute_ project.
+
+ If you prefer to install the full distribution from source, including
+ the documentation, download the tarball_, unpack it and run
+
+ $ python setup.py install
+
+ in the main directory, possibly as superuser.
+
+ .. _tarball: http://pypi.python.org/pypi/decorator
+ .. _distribute: http://packages.python.org/distribute/
+
+ Testing
+ --------
+
+ For Python 2.5, 2.6, 2.7 run
+
+ $ python documentation.py
+
+ for Python 3.X run
+
+ $ python documentation3.py
+
+ You will see a few innocuous errors with Python 2.5, because some
+ inner details such as the introduction of the ArgSpec namedtuple and
+ Thread.__repr__ changed. You may safely ignore them.
+
+ You cannot run the tests in Python 2.4, since there is a test using
+ the with statement, but the decorator module is expected to work
+ anyway (it has been used in production with Python 2.4 for years). My
+ plan is to keep supporting all Python versions >= 2.4 in the core
+ module, but I will keep the documentation and the tests updated only
+ for the latest Python versions in both the 2.X and 3.X branches.
+
+ Finally, notice that you may run into trouble if in your system there
+ is an older version of the decorator module; in such a case remove the
+ old version.
+
+ Documentation
+ --------------
+
+ There are various versions of the documentation:
+
+ - `HTML version (Python 2)`_
+ - `PDF version (Python 2)`_
+
+ - `HTML version (Python 3)`_
+ - `PDF version (Python 3)`_
+
+ .. _HTML version (Python 2): http://micheles.googlecode.com/hg/decorator/documentation.html
+ .. _PDF version (Python 2): http://micheles.googlecode.com/hg/decorator/documentation.pdf
+ .. _HTML version (Python 3): http://micheles.googlecode.com/hg/decorator/documentation3.html
+ .. _PDF version (Python 3): http://micheles.googlecode.com/hg/decorator/documentation3.pdf
+
+ Repository
+ ---------------
+
+ The project is hosted on GoogleCode as a Mercurial repository. You
+ can look at the source here:
+
+ http://code.google.com/p/micheles/source/browse/#hg%2Fdecorator
+
+Keywords: decorators generic utility
+Platform: All
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Utilities
diff --git a/src/decorator.egg-info/SOURCES.txt b/src/decorator.egg-info/SOURCES.txt
new file mode 100644
index 0000000..4b7a116
--- /dev/null
+++ b/src/decorator.egg-info/SOURCES.txt
@@ -0,0 +1,11 @@
+MANIFEST.in
+README.txt
+documentation.py
+documentation3.py
+setup.py
+src/decorator.py
+src/decorator.egg-info/PKG-INFO
+src/decorator.egg-info/SOURCES.txt
+src/decorator.egg-info/dependency_links.txt
+src/decorator.egg-info/not-zip-safe
+src/decorator.egg-info/top_level.txt \ No newline at end of file
diff --git a/src/decorator.egg-info/dependency_links.txt b/src/decorator.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/decorator.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/src/decorator.egg-info/not-zip-safe b/src/decorator.egg-info/not-zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/decorator.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
diff --git a/src/decorator.egg-info/top_level.txt b/src/decorator.egg-info/top_level.txt
new file mode 100644
index 0000000..3fe18a4
--- /dev/null
+++ b/src/decorator.egg-info/top_level.txt
@@ -0,0 +1 @@
+decorator
diff --git a/src/decorator.py b/src/decorator.py
new file mode 100644
index 0000000..e003914
--- /dev/null
+++ b/src/decorator.py
@@ -0,0 +1,251 @@
+########################## LICENCE ###############################
+
+# Copyright (c) 2005-2012, 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:
+
+# 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.
+
+"""
+Decorator module, see http://pypi.python.org/pypi/decorator
+for the documentation.
+"""
+
+__version__ = '3.4.0'
+
+__all__ = ["decorator", "FunctionMaker", "contextmanager"]
+
+import sys, re, inspect
+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"
+ def __init__(self, f):
+ self.args, self.varargs, self.varkw, self.defaults = \
+ 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):
+ """
+ An object with the ability to create functions with a given signature.
+ It has attributes name, doc, module, signature, defaults, dict and
+ methods update and make.
+ """
+ def __init__(self, func=None, name=None, signature=None,
+ defaults=None, doc=None, module=None, funcdict=None):
+ self.shortsignature = signature
+ 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_'
+ self.doc = func.__doc__
+ self.module = func.__module__
+ if inspect.isfunction(func):
+ argspec = getfullargspec(func)
+ self.annotations = getattr(func, '__annotations__', {})
+ for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',
+ 'kwonlydefaults'):
+ 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 = \
+ inspect.formatargspec(
+ 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
+ for a in self.kwonlyargs:
+ allargs.append('%s=None' % a)
+ allshortargs.append('%s=%s' % (a, a))
+ if 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:
+ self.name = name
+ if signature is not None:
+ self.signature = signature
+ if defaults:
+ self.defaults = defaults
+ if doc:
+ self.doc = doc
+ if module:
+ self.module = module
+ if funcdict:
+ self.dict = funcdict
+ # check existence required attributes
+ assert hasattr(self, 'name')
+ if not hasattr(self, 'signature'):
+ raise TypeError('You are decorating a non function: %s' % func)
+
+ def update(self, func, **kw):
+ "Update the signature of func with the data in self"
+ func.__name__ = self.name
+ func.__doc__ = getattr(self, 'doc', None)
+ func.__dict__ = getattr(self, 'dict', {})
+ func.func_defaults = getattr(self, 'defaults', ())
+ func.__kwdefaults__ = getattr(self, 'kwonlydefaults', None)
+ func.__annotations__ = getattr(self, 'annotations', None)
+ callermodule = sys._getframe(3).f_globals.get('__name__', '?')
+ func.__module__ = getattr(self, 'module', callermodule)
+ func.__dict__.update(kw)
+
+ 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
+ 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(',')])
+ 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
+ try:
+ code = compile(src, '<string>', 'single')
+ # print >> sys.stderr, 'Compiling %s' % src
+ exec code in evaldict
+ except:
+ print >> sys.stderr, 'Error in generated code:'
+ print >> sys.stderr, src
+ raise
+ func = evaldict[name]
+ if addsource:
+ attrs['__source__'] = src
+ self.update(func, **attrs)
+ return func
+
+ @classmethod
+ def create(cls, obj, body, evaldict, defaults=None,
+ 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.
+ """
+ if isinstance(obj, str): # "name(signature)"
+ name, rest = obj.strip().split('(', 1)
+ signature = rest[:-1] #strip a right parens
+ func = None
+ 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)
+
+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
+ evaldict = func.func_globals.copy()
+ evaldict['_call_'] = caller
+ evaldict['_func_'] = func
+ return FunctionMaker.create(
+ func, "return _call_(_func_, %(shortsignature)s)",
+ evaldict, undecorated=func, __wrapped__=func)
+ 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
+ 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)' % (name, fun),
+ 'return decorator(_call_, %s)' % fun,
+ evaldict, undecorated=caller, __wrapped__=caller,
+ 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)