[Mailman-Developers] Another extend.py thing.. (was Re: MemberAdaptor... trouble with API?)

Steve Spicklemire steve@spvi.com
Sat, 17 Aug 2002 16:46:10 -0500

Hi (again) mailman folk....

Another issue I've bumped into when trying to use the 'extend.py' method 
of modifying the behavior of a mailman (2.1b3) mailing list is pickling 
the modified list. It seems when a replace the authenticateMember method 
of the list, as described in my previous mail (and below), mailman has 
trouble saving any changes to the list:

I get tracebacks that end up like this:

   File "/var/mailman/Mailman/MailList.py", line 487, in Save
   File "/var/mailman/Mailman/MailList.py", line 447, in __save
     cPickle.dump(dict, fp, 1)
cPickle.PicklingError: Can't pickle <function new_authenticateMember at 
0x82e77e4>: it's not found as __main__.new_authenticateMember

I think the basic issue is that when I assign the modified method to an 
instance of a MailList, it get's stored in the instance's __dict__, 
which during the "Save" method, is then copied and (unsuccessfully) 
pickled. Do I also need to replace the "Save" method so that it avoids 
attempting to pickle stuff it shouldn't/can't? (as in all the methods I 
replaced, including itself?)


Does this approach still really work? Do I really need to subclass 
On Saturday, August 17, 2002, at 11:58  AM, Steve Spicklemire wrote:

> Hi Mailman folks,
> I've started poking around in mailman, trying to help out some folks, 
> and I've come across something I'm not sure how to handle. I'd like to 
> get Mailman working with LDAP, and the first order of business is to 
> simply allow folks to use their LDAP passwords as an option when 
> authenticating with Mailman. Here was my first crack at it:
> from checkLDAP import checkLDAP
> import string
> def makefunc(oldAuth):
>     def new_authenticateMember( member, response, oldAuth=oldAuth, 
> debug=0 ):
>         l_r = string.split(member, '@')
>         if len(l_r) == 2:
>             if l_r[1] == 'our.domain':
>                 if checkLDAP( None, member, response):
>                     return response
>         return oldAuth( member, response)
>     return new_authenticateMember
> def extend(mlist):
>     oldfunc = mlist.authenticateMember
>     mlist.authenticateMember = makefunc(oldfunc)
> I expected that all I needed to do was to replace "authenticateMember' 
> in extend.py and I would be set. Unfortunately, my code never gets 
> called! Snooping through the SecurityManager class, I see that instead, 
> it uses 'getMemberPassword', and never calls 'authenticateMember' at 
> all! The problem is that we don't have any unencrypted passwords to 
> "get". So do I need to override "Authenticate" of SecurityManger to 
> call authenticateMember rather then 'getMemberPassword'? This seems a 
> little wierd. Would it be better to have SecurityManager call 
> 'authenticateMember'? Is the cleartext password really required? If it 
> *is* actually required, couldn't the code just call 
> 'authenticateMember', and if successful, use 'response', rather than 
> asking for the cleartext password from the member adaptor?
> thanks,
> -steve