##// END OF EJS Templates
update copyright to 2011/20xx-2011...
update copyright to 2011/20xx-2011 Closes #1033 (rebased to prevent recursive merge). Closes #2. 459 *.py files in : 39 empty files 176 files without copyright 36 have copyright but don't cite the dev team 208 have copyright and cite the dev team ----------------------------------------- 0 not up to date (cite dev team but not right year) FYI, list of files that don't have copyright (and are not empty..) [ 'IPython/config/profile/cluster/ipython_config.py', 'IPython/config/profile/math/ipython_config.py', 'IPython/config/profile/pylab/ipython_config.py', 'IPython/config/profile/pysh/ipython_config.py', 'IPython/config/profile/python3/ipython_config.py', 'IPython/config/profile/sympy/ipython_config.py', 'IPython/core/shadowns.py', 'IPython/core/tests/refbug.py', 'IPython/core/tests/simpleerr.py', 'IPython/core/tests/tclass.py', 'IPython/core/tests/test_application.py', 'IPython/core/tests/test_autocall.py', 'IPython/core/tests/test_completer.py', 'IPython/core/tests/test_fakemodule.py', 'IPython/core/tests/test_formatters.py', 'IPython/core/tests/test_handlers.py', 'IPython/core/tests/test_history.py', 'IPython/core/tests/test_imports.py', 'IPython/core/tests/test_iplib.py', 'IPython/core/tests/test_logger.py', 'IPython/core/tests/test_magic.py', 'IPython/core/tests/test_plugin.py', 'IPython/core/tests/test_prefilter.py', 'IPython/core/tests/test_profile.py', 'IPython/core/tests/test_run.py', 'IPython/core/tests/test_splitinput.py', 'IPython/deathrow/astyle.py', 'IPython/deathrow/dtutils.py', 'IPython/deathrow/Gnuplot2.py', 'IPython/deathrow/GnuplotInteractive.py', 'IPython/deathrow/GnuplotRuntime.py', 'IPython/deathrow/gui/wx/ipshell_nonblocking.py', 'IPython/deathrow/gui/wx/ipython_history.py', 'IPython/deathrow/gui/wx/thread_ex.py', 'IPython/deathrow/ibrowse.py', 'IPython/deathrow/igrid.py', 'IPython/deathrow/ipipe.py', 'IPython/deathrow/ipy_defaults.py', 'IPython/deathrow/ipy_kitcfg.py', 'IPython/deathrow/ipy_legacy.py', 'IPython/deathrow/ipy_p4.py', 'IPython/deathrow/ipy_profile_none.py', 'IPython/deathrow/ipy_profile_numpy.py', 'IPython/deathrow/ipy_profile_scipy.py', 'IPython/deathrow/ipy_profile_sh.py', 'IPython/deathrow/ipy_traits_completer.py', 'IPython/deathrow/ipy_vimserver.py', 'IPython/deathrow/numeric_formats.py', 'IPython/deathrow/oldfrontend/process/__init__.py', 'IPython/deathrow/oldfrontend/wx/ipythonx.py', 'IPython/deathrow/scitedirector.py', 'IPython/deathrow/tests/test_prefilter.py', 'IPython/deathrow/twshell.py', 'IPython/extensions/__init__.py', 'IPython/extensions/autoreload.py', 'IPython/extensions/storemagic.py', 'IPython/extensions/tests/test_autoreload.py', 'IPython/external/__init__.py', 'IPython/external/argparse/__init__.py', 'IPython/external/decorator/__init__.py', 'IPython/external/decorators/__init__.py', 'IPython/external/decorators/_decorators.py', 'IPython/external/decorators/_numpy_testing_noseclasses.py', 'IPython/external/decorators/_numpy_testing_utils.py', 'IPython/external/guid/__init__.py', 'IPython/external/Itpl/__init__.py', 'IPython/external/mglob/__init__.py', 'IPython/external/mglob/_mglob.py', 'IPython/external/path/__init__.py', 'IPython/external/path/_path.py', 'IPython/external/pexpect/__init__.py', 'IPython/external/pyparsing/__init__.py', 'IPython/external/qt.py', 'IPython/external/qt_for_kernel.py', 'IPython/external/simplegeneric/__init__.py', 'IPython/external/simplegeneric/_simplegeneric.py', 'IPython/frontend/html/notebook/__init__.py', 'IPython/frontend/html/notebook/tests/test_kernelsession.py', 'IPython/frontend/qt/base_frontend_mixin.py', 'IPython/frontend/qt/console/ansi_code_processor.py', 'IPython/frontend/qt/console/bracket_matcher.py', 'IPython/frontend/qt/console/call_tip_widget.py', 'IPython/frontend/qt/console/completion_lexer.py', 'IPython/frontend/qt/console/completion_widget.py', 'IPython/frontend/qt/console/console_widget.py', 'IPython/frontend/qt/console/history_console_widget.py', 'IPython/frontend/qt/console/ipython_widget.py', 'IPython/frontend/qt/console/kill_ring.py', 'IPython/frontend/qt/console/mainwindow.py', 'IPython/frontend/qt/console/pygments_highlighter.py', 'IPython/frontend/qt/console/qtconsoleapp.py', 'IPython/frontend/qt/console/rich_ipython_widget.py', 'IPython/frontend/qt/console/styles.py', 'IPython/frontend/qt/console/tests/test_ansi_code_processor.py', 'IPython/frontend/qt/console/tests/test_completion_lexer.py', 'IPython/frontend/qt/console/tests/test_kill_ring.py', 'IPython/frontend/qt/kernelmanager.py', 'IPython/frontend/qt/rich_text.py', 'IPython/frontend/qt/svg.py', 'IPython/frontend/qt/util.py', 'IPython/kernel/__init__.py', 'IPython/lib/clipboard.py', 'IPython/lib/display.py', 'IPython/lib/irunner.py', 'IPython/lib/security.py', 'IPython/lib/tests/test_imports.py', 'IPython/lib/tests/test_irunner.py', 'IPython/lib/tests/test_irunner_pylab_magic.py', 'IPython/lib/tests/test_security.py', 'IPython/nbformat/v1/tests/nbexamples.py', 'IPython/nbformat/v1/tests/test_json.py', 'IPython/nbformat/v1/tests/test_nbbase.py', 'IPython/nbformat/v2/tests/nbexamples.py', 'IPython/nbformat/v2/tests/test_json.py', 'IPython/nbformat/v2/tests/test_nbbase.py', 'IPython/nbformat/v2/tests/test_nbpy.py', 'IPython/quarantine/clearcmd.py', 'IPython/quarantine/envpersist.py', 'IPython/quarantine/ext_rescapture.py', 'IPython/quarantine/ipy_app_completers.py', 'IPython/quarantine/ipy_completers.py', 'IPython/quarantine/ipy_editors.py', 'IPython/quarantine/ipy_exportdb.py', 'IPython/quarantine/ipy_extutil.py', 'IPython/quarantine/ipy_fsops.py', 'IPython/quarantine/ipy_gnuglobal.py', 'IPython/quarantine/ipy_jot.py', 'IPython/quarantine/ipy_lookfor.py', 'IPython/quarantine/ipy_profile_doctest.py', 'IPython/quarantine/ipy_pydb.py', 'IPython/quarantine/ipy_rehashdir.py', 'IPython/quarantine/ipy_render.py', 'IPython/quarantine/ipy_server.py', 'IPython/quarantine/ipy_signals.py', 'IPython/quarantine/ipy_synchronize_with.py', 'IPython/quarantine/ipy_system_conf.py', 'IPython/quarantine/ipy_which.py', 'IPython/quarantine/ipy_winpdb.py', 'IPython/quarantine/ipy_workdir.py', 'IPython/quarantine/jobctrl.py', 'IPython/quarantine/ledit.py', 'IPython/quarantine/win32clip.py', 'IPython/testing/mkdoctests.py', 'IPython/testing/plugin/dtexample.py', 'IPython/testing/plugin/ipdoctest.py', 'IPython/testing/plugin/iptest.py', 'IPython/testing/plugin/setup.py', 'IPython/testing/plugin/show_refs.py', 'IPython/testing/plugin/simple.py', 'IPython/testing/plugin/simplevars.py', 'IPython/testing/plugin/test_ipdoctest.py', 'IPython/testing/plugin/test_refs.py', 'IPython/testing/skipdoctest.py', 'IPython/testing/tests/test_decorators.py', 'IPython/utils/autoattr.py', 'IPython/utils/nested_context.py', 'IPython/utils/pickleshare.py', 'IPython/utils/py3compat.py', 'IPython/utils/PyColorize.py', 'IPython/utils/rlineimpl.py', 'IPython/utils/strdispatch.py', 'IPython/utils/tempdir.py', 'IPython/utils/tests/test_imports.py', 'IPython/utils/tests/test_wildcard.py', 'IPython/utils/upgradedir.py', 'IPython/zmq/completer.py', 'IPython/zmq/displayhook.py', 'IPython/zmq/entry_point.py', 'IPython/zmq/frontend.py', 'IPython/zmq/iostream.py', 'IPython/zmq/ipkernel.py', 'IPython/zmq/log.py', 'IPython/zmq/parentpoller.py', 'IPython/zmq/pykernel.py', 'IPython/zmq/pylab/backend_inline.py', 'IPython/zmq/zmqshell.py' ]

File last commit:

r4872:34c10438
r5390:c82649ea
Show More
_decorator.py
254 lines | 9.9 KiB | text/x-python | PythonLexer
########################## LICENCE ###############################
##
## Copyright (c) 2005, Michele Simionato
## All rights reserved.
##
## 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.
"""
__all__ = ["decorator", "FunctionMaker", "partial",
"deprecated", "getinfo", "new_wrapper"]
import os, sys, re, inspect, string, warnings
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)
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):
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 = inspect.getargspec(func)
self.args, self.varargs, self.keywords, self.defaults = argspec
for i, arg in enumerate(self.args):
setattr(self, 'arg%d' % i, arg)
self.signature = inspect.formatargspec(
formatvalue=lambda val: "", *argspec)[1:-1]
self.dict = func.__dict__.copy()
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', ())
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
reserved_names = set([name] + [
arg.strip(' *') for arg in self.signature.split(',')])
for n, v in evaldict.iteritems():
if n in reserved_names:
raise NameError('%s is overridden in\n%s' % (n, src))
if not src.endswith('\n'): # add a newline just for safety
src += '\n'
try:
code = compile(src, '<string>', 'single')
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
fun = cls(func, name, signature, defaults, doc, module)
ibody = '\n'.join(' ' + line for line in body.splitlines())
return fun.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
return FunctionMaker.create(
func, "return _call_(_func_, %(signature)s)",
dict(_call_=caller, _func_=func), undecorated=func)
else: # returns a decorator
if isinstance(caller, partial):
return partial(decorator, caller)
# otherwise assume caller is a function
f = inspect.getargspec(caller)[0][0] # first arg
return FunctionMaker.create(
'%s(%s)' % (caller.__name__, f),
'return decorator(_call_, %s)' % f,
dict(_call_=caller, decorator=decorator), undecorated=caller,
doc=caller.__doc__, module=caller.__module__)
###################### deprecated functionality #########################
@decorator
def deprecated(func, *args, **kw):
"A decorator for deprecated functions"
warnings.warn(
('Calling the deprecated function %r\n'
'Downgrade to decorator 2.3 if you want to use this functionality')
% func.__name__, DeprecationWarning, stacklevel=3)
return func(*args, **kw)
@deprecated
def getinfo(func):
"""
Returns an info dictionary containing:
- name (the name of the function : str)
- argnames (the names of the arguments : list)
- defaults (the values of the default arguments : tuple)
- signature (the signature : str)
- doc (the docstring : str)
- module (the module name : str)
- dict (the function __dict__ : str)
>>> def f(self, x=1, y=2, *args, **kw): pass
>>> info = getinfo(f)
>>> info["name"]
'f'
>>> info["argnames"]
['self', 'x', 'y', 'args', 'kw']
>>> info["defaults"]
(1, 2)
>>> info["signature"]
'self, x, y, *args, **kw'
"""
assert inspect.ismethod(func) or inspect.isfunction(func)
regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
argnames = list(regargs)
if varargs:
argnames.append(varargs)
if varkwargs:
argnames.append(varkwargs)
signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults,
formatvalue=lambda value: "")[1:-1]
return dict(name=func.__name__, argnames=argnames, signature=signature,
defaults = func.func_defaults, doc=func.__doc__,
module=func.__module__, dict=func.__dict__,
globals=func.func_globals, closure=func.func_closure)
@deprecated
def update_wrapper(wrapper, model, infodict=None):
"A replacement for functools.update_wrapper"
infodict = infodict or getinfo(model)
wrapper.__name__ = infodict['name']
wrapper.__doc__ = infodict['doc']
wrapper.__module__ = infodict['module']
wrapper.__dict__.update(infodict['dict'])
wrapper.func_defaults = infodict['defaults']
wrapper.undecorated = model
return wrapper
@deprecated
def new_wrapper(wrapper, model):
"""
An improvement over functools.update_wrapper. The wrapper is a generic
callable object. It works by generating a copy of the wrapper with the
right signature and by updating the copy, not the original.
Moreovoer, 'model' can be a dictionary with keys 'name', 'doc', 'module',
'dict', 'defaults'.
"""
if isinstance(model, dict):
infodict = model
else: # assume model is a function
infodict = getinfo(model)
assert not '_wrapper_' in infodict["argnames"], (
'"_wrapper_" is a reserved argument name!')
src = "lambda %(signature)s: _wrapper_(%(signature)s)" % infodict
funcopy = eval(src, dict(_wrapper_=wrapper))
return update_wrapper(funcopy, model, infodict)