How to wrap a class's methods?

Mathias Waack M.Waack at gmx.de
Thu Feb 17 15:30:49 EST 2005


Grant Edwards wrote:

> I want to subclass an IMAP connection so that most of the
> methods raise an exception if the returned status isn't 'OK'.
> This works, but there's got to be a way to do it that doesn't
> involve so much duplication:
> 
> class MyImap4_ssl(imaplib.IMAP4_SSL):
> 
>     def login(*args):
>         s,r = imaplib.IMAP4_SSL.login(*args)
>         if s!='OK':
>             raise NotOK((s,r))
>         return r
>         
>     def list(*args):
>         s,r = imaplib.IMAP4_SSL.list(*args)
>         if s!='OK':
>             raise NotOK((s,r))
>         return r
>         
>     def search(*args):
>         s,r = imaplib.IMAP4_SSL.search(*args)
>         if s!='OK':
>             raise NotOK((s,r))
>         return r
>         
>     [and so on for another dozen methods]

How about using a delegator: 

class Wrapper:
  funcs = ("login", "list", "search")
  def __init__(self, classobj):
    self.__wrapped = classobj()
  def __getattr__(self, attr):
    if attr in Wrapper.funcs:
      def f(*args):
        f1 = getattr(self.__wrapped, attr)
        s,r = f1(args)
        if s != 'OK': raise NotOk((s,r))
        return r
      return f
    # raise some exception here
imap = Wrapper(imaplib.IMAP4_SSL)

If you wrap all methods you can ignore the if-test. Instead of the
class object you can pass instances to the wrapper if you need
special arguments for initialization. 

I don't like subclassing;)

Mathias

PS: note that we're wrapping the instance's methods, not the class's
methods!



More information about the Python-list mailing list