problem with closure arguments and *args in mock object
Peter Otten
__peter__ at web.de
Fri Nov 7 13:41:48 EST 2003
John J. Lee wrote:
> I'm trying define a class to act as a Mock "handler" object for
> testing urllib2.OpenerDirector.
>
> OpenerDirector (actually, my copy of it) does dir(handler.__class__)
> to find out what methods a handler supports. So, my mock class has to
> have appropriate methods defined on it. To avoid the hassle of
> manually defining lots of mock classes, I wanted to have a base class
> MockHandler so that I could do
>
> class MockHandlerSubclass(MockHandler): pass
> # create an instance of subclass, and define methods on the subclass
> h = MockHandlerSubclass(None, ["http_open", "ftp_open", "http_error_302"])
>
>
> Now, when the mock object's methods get called, I want to record the
> called method name along with the arguments passed to the method.
> _define_methods (below) tries to define a method that does that. The
> problem is with this line:
>
> def meth(self, name=name, *args):
>
>
> I want to make this a closure, with name , so what I really want to
> write is this:
>
> def meth(self, *args, name=name):
>
>
> But Python's syntax won't let me.
>
> How can I best work around this?
>
>
> class MockHandler:
> def __init__(self, action, methods):
> self.action = action
> self._define_methods(methods)
> self.argslist = []
> self.names = []
> def _define_methods(self, methods):
> for name in methods:
> def meth(self, name=name, *args): # HERE!
> apply(self.handle, (self,)+args)
> self.names.append(name)
> setattr(self.__class__, name, meth)
> def handle(self, fn_name, *args):
> self.argslist.append(args)
> if self.action is None: return None
> elif self.action == "return": return self
> elif self.action == "error": raise urllib2.URLError()
> def close(self): pass
> def add_parent(self, parent): self.parent = parent
>
>
> John
Not very elegant, but might still serve the purpose:
class Test(object):
def __init__(self):
self.log = []
def handle(self, args):
self.log.append(args)
def define(self, methods):
def makeMethod(name):
def method(self, *args):
self.handle((name,) + args)
return method
for name in methods:
setattr(self.__class__, name, makeMethod(name))
t = Test()
t.define("alpha beta gamma".split())
t.alpha("entteufelter")
t.beta("nu")
t.gamma(1,2,3)
for record in t.log:
print record
Peter
More information about the Python-list
mailing list