problem with closure arguments and *args in mock object

John J. Lee jjl at pobox.com
Fri Nov 7 12:24:16 EST 2003


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




More information about the Python-list mailing list