diff options
author | Michael E Brown <mebrown@michaels-house.net> | 2007-12-01 13:08:23 -0600 |
---|---|---|
committer | Michael E Brown <mebrown@michaels-house.net> | 2007-12-01 13:08:23 -0600 |
commit | 6c521c9c0cfab397ee0aa9764adce737e39415b4 (patch) | |
tree | a969ce2f5a66a53cdf4bf046ac51bd860b7e5e11 | |
parent | 0a52ee48213f254c99b4a435f63692d2d58b3d48 (diff) | |
download | mock-6c521c9c0cfab397ee0aa9764adce737e39415b4.tar.gz mock-6c521c9c0cfab397ee0aa9764adce737e39415b4.tar.xz mock-6c521c9c0cfab397ee0aa9764adce737e39415b4.zip |
use python-decoratortools instead of shipping our own decorator.py
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | Makefile.in | 1 | ||||
-rw-r--r-- | mock.spec.in | 2 | ||||
-rwxr-xr-x | py/mock/decorator.py | 124 | ||||
-rwxr-xr-x | py/mock/trace_decorator.py | 73 |
5 files changed, 37 insertions, 164 deletions
diff --git a/Makefile.am b/Makefile.am index 9680c1e..1532a97 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,7 +53,6 @@ pkgpython_PYTHON = \ py/mock/exception.py \ py/mock/util.py \ py/mock/backend.py \ - py/mock/decorator.py \ py/mock/trace_decorator.py \ py/mock/uid.py diff --git a/Makefile.in b/Makefile.in index 7520db0..70febdb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -280,7 +280,6 @@ pkgpython_PYTHON = \ py/mock/exception.py \ py/mock/util.py \ py/mock/backend.py \ - py/mock/decorator.py \ py/mock/trace_decorator.py \ py/mock/uid.py diff --git a/mock.spec.in b/mock.spec.in index 6e92564..a0bde12 100644 --- a/mock.spec.in +++ b/mock.spec.in @@ -17,7 +17,7 @@ Group: Development/Tools Source: http://fedoraproject.org/projects/mock/releases/%{name}-%{version}.tar.gz URL: http://fedoraproject.org/wiki/Projects/Mock BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -Requires: python >= 2.4, yum >= 2.4, tar, gzip, python-ctypes +Requires: python >= 2.4, yum >= 2.4, tar, gzip, python-ctypes, python-decoratortools Requires(pre): shadow-utils BuildRequires: python-devel diff --git a/py/mock/decorator.py b/py/mock/decorator.py deleted file mode 100755 index 4958a52..0000000 --- a/py/mock/decorator.py +++ /dev/null @@ -1,124 +0,0 @@ -## The basic trick is to generate the source code for the decorated function -## with the right signature and to evaluate it. -## Uncomment the statement 'print >> sys.stderr, func_src' in _decorate -## to understand what is going on. - -__all__ = ["decorator", "update_wrapper", "getinfo"] - -import inspect, sys - -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) - -def update_wrapper(wrapper, wrapped, create=False): - """ - An improvement over functools.update_wrapper. By default it works the - same, but if the 'create' flag is set, generates a copy of the wrapper - with the right signature and update the copy, not the original. - Moreovoer, 'wrapped' can be a dictionary with keys 'name', 'doc', 'module', - 'dict', 'defaults'. - """ - if isinstance(wrapped, dict): - infodict = wrapped - else: # assume wrapped is a function - infodict = getinfo(wrapped) - assert not '_wrapper_' in infodict["argnames"], \ - '"_wrapper_" is a reserved argument name!' - if create: # create a brand new wrapper with the right signature - src = "lambda %(signature)s: _wrapper_(%(signature)s)" % infodict - # import sys; print >> sys.stderr, src # for debugging purposes - wrapper = eval(src, dict(_wrapper_=wrapper)) - try: - wrapper.__name__ = infodict['name'] - except: # Python version < 2.4 - pass - wrapper.__doc__ = infodict['doc'] - wrapper.__module__ = infodict['module'] - wrapper.__dict__.update(infodict['dict']) - wrapper.func_defaults = infodict['defaults'] - return wrapper - -# the real meat is here -def _decorator(caller, func): - infodict = getinfo(func) - argnames = infodict['argnames'] - assert not ('_call_' in argnames or '_func_' in argnames), \ - 'You cannot use _call_ or _func_ as argument names!' - src = "lambda %(signature)s: _call_(_func_, %(signature)s)" % infodict - dec_func = eval(src, dict(_func_=func, _call_=caller)) - return update_wrapper(dec_func, func) - -def decorator(caller, func=None): - """ - General purpose decorator factory: takes a caller function as - input and returns a decorator with the same attributes. - A caller function is any function like this:: - - def caller(func, *args, **kw): - # do something - return func(*args, **kw) - - Here is an example of usage: - - >>> @decorator - ... def chatty(f, *args, **kw): - ... print "Calling %r" % f.__name__ - ... return f(*args, **kw) - - >>> chatty.__name__ - 'chatty' - - >>> @chatty - ... def f(): pass - ... - >>> f() - Calling 'f' - - For sake of convenience, the decorator factory can also be called with - two arguments. In this casem ``decorator(caller, func)`` is just a - shortcut for ``decorator(caller)(func)``. - """ - if func is None: # return a decorator function - return update_wrapper(lambda f : _decorator(caller, f), caller) - else: # return a decorated function - return _decorator(caller, func) - -if __name__ == "__main__": - import doctest; doctest.testmod() diff --git a/py/mock/trace_decorator.py b/py/mock/trace_decorator.py index 3db2360..5529628 100755 --- a/py/mock/trace_decorator.py +++ b/py/mock/trace_decorator.py @@ -6,8 +6,7 @@ import logging import os import sys - -from decorator import decorator +from peak.util.decorators import rewrap moduleLog = logging.getLogger("mock.trace_decorator") @@ -19,42 +18,42 @@ def doLog(logger, level, *args, **kargs): if logger.isEnabledFor(level): logger.handle(logger.makeRecord(logger.name, level, *args, **kargs)) -def traceLog(logger = moduleLog): - log = logger - @decorator - def trace(f, *args, **kw): - # default to logger that was passed by module, but - # can override by passing logger=foo as function parameter. - # make sure this doesnt conflict with one of the parameters - # you are expecting - - filename = os.path.normcase(f.func_code.co_filename) - func_name = f.func_code.co_name - lineno = f.func_code.co_firstlineno - - l2 = kw.get('logger', log) - message = "ENTER %s(" % f.func_name - for arg in args: - message = message + repr(arg) + ", " - for k,v in kw.items(): - message = message + "%s=%s" % (k,repr(v)) - message = message + ")" - - frame = sys._getframe(2) - doLog(l2, logging.DEBUG, os.path.normcase(frame.f_code.co_filename), frame.f_lineno, message, args=[], exc_info=None, func=frame.f_code.co_name) - try: - result = "Bad exception raised: Exception was not a derived class of 'Exception'" +def traceLog(log = moduleLog): + def decorator(func): + def trace(*args, **kw): + # default to logger that was passed by module, but + # can override by passing logger=foo as function parameter. + # make sure this doesnt conflict with one of the parameters + # you are expecting + + filename = os.path.normcase(func.func_code.co_filename) + func_name = func.func_code.co_name + lineno = func.func_code.co_firstlineno + + l2 = kw.get('logger', log) + message = "ENTER %s(" % func_name + for arg in args: + message = message + repr(arg) + ", " + for k,v in kw.items(): + message = message + "%s=%s" % (k,repr(v)) + message = message + ")" + + frame = sys._getframe(2) + doLog(l2, logging.DEBUG, os.path.normcase(frame.f_code.co_filename), frame.f_lineno, message, args=[], exc_info=None, func=frame.f_code.co_name) try: - result = f(*args, **kw) - except (KeyboardInterrupt, Exception), e: - result = "EXCEPTION RAISED" - doLog(l2, logging.DEBUG, filename, lineno, "EXCEPTION: %s\n" % e, args=[], exc_info=sys.exc_info(), func=func_name) - raise - finally: - doLog(l2, logging.DEBUG, filename, lineno, "LEAVE %s --> %s\n" % (f.func_name, result), args=[], exc_info=None, func=func_name) - - return result - return trace + result = "Bad exception raised: Exception was not a derived class of 'Exception'" + try: + result = func(*args, **kw) + except (KeyboardInterrupt, Exception), e: + result = "EXCEPTION RAISED" + doLog(l2, logging.DEBUG, filename, lineno, "EXCEPTION: %s\n" % e, args=[], exc_info=sys.exc_info(), func=func_name) + raise + finally: + doLog(l2, logging.DEBUG, filename, lineno, "LEAVE %s --> %s\n" % (func_name, result), args=[], exc_info=None, func=func_name) + + return result + return rewrap(func, trace) + return decorator # unit tests... if __name__ == "__main__": |