
On Wed, 2005-09-21 at 18:07, John Dennis wrote:
Good news, bad news: good news is I've implemented a LDAP based membership adapter that implements the complete MemberAdapter interface (the previous LDAP adapter was incomplete and limited in application). In stand alone testing my adapter seems to work quite nicely.
Skip to the last paragraph if you don't need or want the details.
Now the bad news, I'm having trouble integrating it because of either structural problems with adapters or a lack of understanding of how adapters are supposed to work. I'm looking for guidance or insight. Here are the issues I've run into:
John, I think you understand the current state of affairs exactly right. At the time I designed the extend.py stuff, it wasn't a requirement to support site-wide list specialization.
- Adapters are discovered by the presence of extend.py in the list's directory. How does extend.py get into the list directory? The only way I could figure was manual copying after list creation, this isn't a viable mechanism for a running site.
Right. I was thinking you might be able to hook into the create() and remove() methods in the MTA modules, but that doesn't work for several reasons. First, you've have to implement the same code for each module, and second, the call to those functions doesn't really happen at the right time.
Provide a site wide variable that specifies an adapter for every list which is overridden by the presence of extend.py in the list directory. If the site wide adapter is used then MailList.__init__() loads it and calls an initialization function in the module (extend()??, __init__()??)
At the end of MailList.Create() it should test for the existence of an adapter and if so it should attempt to call the adapters Create() method.
Just as the adapter is not informed of list creation is is not informed of list destruction either, calls need to be added to invoke Remove() as well.
You might consider instead creating these functions in the Mailman/Site.py module. The intention of that module is to implement site-wide customizations (or at least, provide the hooks for that). Right now, there's nothing in there that hooks into the list creation and instantiation process, but it definitely could.
You could add these functions:
* list_create(): called when a new mailing list is first created.
* list_open(): called when an existing mailing list is opened
(i.e. its __init__() is called).
The above each take the MailList instance and can stuff new methods into the instance to override any behavior you want. I don't think you'll need to hook into MailList.Load() or MailList.Save() because those you'll do in your site-wide adapter.
Also, hooking into list deletion is trickier because as you can see in bin/rmlist and Mailman/Cgi/rmlist.py, they don't actually call anything on the MailList instance before the low-level removal procedure is performed (i.e. unlinking and such). That's a flaw that would take more work to fix, because what you'd really want to do is move the bulk of that code into the MailList class, and have those two other files call something like MailList.Delete(). The latter would then be hooked by a Site.py list_delete() function.
I'm happy to provide patches for all this, I'm not interested in suggesting anyone else do more work, I'm mostly interested in knowing if I'm on the right track or if I have a misunderstanding.
I think you're on the right track. Hopefully the above is helpful.
PostScript (or a few more questions):
Now after having fully implemented the adapter interface I have to admit I don't really understand what its buying you over the existing OldMemberAdapter. My initial thought was to capitalize on existing user information at a site, but given the way mailman data is structured (a set of lists, each list may contain both local and unknown foreign users, and user properties are per list) then there seems to be little value in intermingling site user data and mailman list data.
Also, it was not clear how an adapter might implement just a subset of the methods via inheritance, I suppose it would copy the function pointers from the mlist._memberadapter into its own methods before resetting mlist._memberadapter to itself. yes/no?
I'm not sure I understand exactly what you're trying to do here. The intention was that using a different adapter was an all-or-nothing proposition. I.e. if you were going to use an LDAP or MySQL adapter, then you wouldn't use any of the config.pck based OldMemberAdapter. I have my doubts that Mailman would be able to intermix the two.
-Barry