I\'m developing a documentation testing framework -- basically unit tests for PDFs. Tests are (decorated) methods of instances of classes defined by the framework, and these
Here's a one line method decorator that seems to do the job without modifying any Special attributes of Callable types* marked Read-only:
# method decorator -- makes undeclared 'self' argument available to method
injectself = lambda f: lambda self: eval(f.func_code, dict(self=self))
class TestClass:
def __init__(self, thing):
self.attr = thing
@injectself
def method():
print 'in TestClass::method(): self.attr = %r' % self.attr
return 42
test = TestClass("attribute's value")
ret = test.method()
print 'return value:', ret
# output:
# in TestClass::method(): self.attr = "attribute's value"
# return value: 42
Note that unless you take precautions to prevent it, a side-effect of the eval() function may be it adding a few entries -- such as a reference to the __builtin__ module under the key __builtins__ -- automatically to the dict passed to it.
@kendall: Per your comment about how you're using this with methods being in container classes (but ignoring the injection of additional variables for the moment) -- is the following something like what you're doing? It's difficult for me to understand how things are split up between the framework and what the users write. It sounds like an interesting design pattern to me.
# method decorator -- makes undeclared 'self' argument available to method
injectself = lambda f: lambda self: eval(f.func_code, dict(self=self))
class methodclass:
def __call__():
print 'in methodclass::__call__(): self.attr = %r' % self.attr
return 42
class TestClass:
def __init__(self, thing):
self.attr = thing
method = injectself(methodclass.__call__)
test = TestClass("attribute's value")
ret = test.method()
print 'return value:', ret
# output
# in methodclass::__call__(): self.attr = "attribute's value"
# return value: 42