Creating an event catching plugin

Hello,
can you point me to existing, open-source mailman plugins?
I want to write a plugin, which fires on all subscriptions, unsubscriptions and configuration changes.
This code:
def subscribe_events(e): print('EVENT', e)
@implementer(IPlugin) class SievePlugin: def __init__(self): print('XXX') zope.event.subscribers.append(subscribe_events)
def post_hook(self):
print('YYY')
zope.event.subscribers.append(subscribe_events)
prints: XXX EVENT x@example.org joined zzz.udoma.bapha.be EVENT ab c <mm@example.org> joined zzz.udoma.bapha.be
or XXX EVENT x@example.org left zzz.udoma.bapha.be
on mailman addmembers/mailman delmembers
. But it does not trigger a
UnsubscriptionEvent or SubscriptionEvent.
Greetings Дилян

Hello,
the object passed was actually an unsubscription/subscription event, which was just pretty-printed.
Is there any explanation, why in the code below YYY is not printed?
when I add
def pre_hook(self):
print('pre_HOOK')
pre_HOOK is also not printed, but __init__ is called, as XXX is printed.
Greetings Дилян
On Tue, 2022-03-08 at 19:39 +0200, Дилян Палаузов wrote:

I am not sure if you figured it out already, I see that you moved your code from pre_hook to __init__ for your plugin.
Just for testing, I enabled the print(‘hello world’)
in your plugin and in a local install and it seems to work,
$ mailman info
Hello World
GNU Mailman 3.3.6b1 (Tom Sawyer)
Python 3.9.10 (main, Jan 15 2022, 11:40:53)
[Clang 13.0.0 (clang-1300.0.29.3)]
config file: /Users/maxking/Documents/mm3/core-workspace-2/var/etc/mailman.cfg
db url: sqlite:////Users/maxking/Documents/mm3/core-workspace-2/var/data/mailman.db
devmode: DISABLED
REST root url: http://localhost:8001/3.1/
REST credentials: restadmin:restpass
The configuration is like your README.md recommends
[plugin.mailman_sieve]
class: mailman_sieve.SievePlugin
enabled: yes
configuration: ./sieve.cfg
We don’t currently have any that i know of, so this is really the first one! I am happy to see that :-)
We should put up a list of community maintained plugins in a page at docs.mailman3.org so the users can actually discover them plugin.
I guess you were using print
statements for debugging when working on the plugin, but generally, it is good to use logging library instead since print logs to stdout, which might not be set correctly in daemon processes like Mailman.
-- thanks, Abhilash Raj (maxking)

Hello,
On Thu, 2022-03-10 at 11:26 -0800, Abhilash Raj wrote:
pre_hook(), post_hook() and resource must be present in the IPLugin implementation, see https://gitlab.com/mailman/mailman/-/issues/985 . Otherwise logs/plugins.log gets:
Mar 11 10:11:00 2022 (1998657) Plugin class does not implement IPlugin: mailman_sieve.SievePlugin
and ”mailman info” does not call the hooks.
What is the difference between doing something in pre_hook(), or in __init__() ?
Greetings Дилян

Yeah, even though we can accomodate missing pre-hook and failing post-hooks, the initialization code expects the classes to conform to the IPlugin interface and ones that don’t are not loaded3.
I am looking more into zope.interface that we use for defining the plugin interface but I am not seeing any way to actually mark methods as optional while also defining the interface. So, meanwhile, I guess we have to settle for no-op hooks in the plugins. I’ll keep looking into what we can do to make this better.
So, typically, i’d say that anything that you want to re-run after a Python class has been instantiated, would go into a method.
While currently, plugins are initialized and the pre-hook is called almost just after1, you won’t see any real difference in functionality.
But it would be a good practice to move it to a pre_hook so you can separate out the initialization and actual _actions_ of the Plugin. It will also help with testing in future. I see that you are just adding an event listener and don’t need access to the database.
-- thanks, Abhilash Raj (maxking)

Hello,
the object passed was actually an unsubscription/subscription event, which was just pretty-printed.
Is there any explanation, why in the code below YYY is not printed?
when I add
def pre_hook(self):
print('pre_HOOK')
pre_HOOK is also not printed, but __init__ is called, as XXX is printed.
Greetings Дилян
On Tue, 2022-03-08 at 19:39 +0200, Дилян Палаузов wrote:

I am not sure if you figured it out already, I see that you moved your code from pre_hook to __init__ for your plugin.
Just for testing, I enabled the print(‘hello world’)
in your plugin and in a local install and it seems to work,
$ mailman info
Hello World
GNU Mailman 3.3.6b1 (Tom Sawyer)
Python 3.9.10 (main, Jan 15 2022, 11:40:53)
[Clang 13.0.0 (clang-1300.0.29.3)]
config file: /Users/maxking/Documents/mm3/core-workspace-2/var/etc/mailman.cfg
db url: sqlite:////Users/maxking/Documents/mm3/core-workspace-2/var/data/mailman.db
devmode: DISABLED
REST root url: http://localhost:8001/3.1/
REST credentials: restadmin:restpass
The configuration is like your README.md recommends
[plugin.mailman_sieve]
class: mailman_sieve.SievePlugin
enabled: yes
configuration: ./sieve.cfg
We don’t currently have any that i know of, so this is really the first one! I am happy to see that :-)
We should put up a list of community maintained plugins in a page at docs.mailman3.org so the users can actually discover them plugin.
I guess you were using print
statements for debugging when working on the plugin, but generally, it is good to use logging library instead since print logs to stdout, which might not be set correctly in daemon processes like Mailman.
-- thanks, Abhilash Raj (maxking)

Hello,
On Thu, 2022-03-10 at 11:26 -0800, Abhilash Raj wrote:
pre_hook(), post_hook() and resource must be present in the IPLugin implementation, see https://gitlab.com/mailman/mailman/-/issues/985 . Otherwise logs/plugins.log gets:
Mar 11 10:11:00 2022 (1998657) Plugin class does not implement IPlugin: mailman_sieve.SievePlugin
and ”mailman info” does not call the hooks.
What is the difference between doing something in pre_hook(), or in __init__() ?
Greetings Дилян

Yeah, even though we can accomodate missing pre-hook and failing post-hooks, the initialization code expects the classes to conform to the IPlugin interface and ones that don’t are not loaded3.
I am looking more into zope.interface that we use for defining the plugin interface but I am not seeing any way to actually mark methods as optional while also defining the interface. So, meanwhile, I guess we have to settle for no-op hooks in the plugins. I’ll keep looking into what we can do to make this better.
So, typically, i’d say that anything that you want to re-run after a Python class has been instantiated, would go into a method.
While currently, plugins are initialized and the pre-hook is called almost just after1, you won’t see any real difference in functionality.
But it would be a good practice to move it to a pre_hook so you can separate out the initialization and actual _actions_ of the Plugin. It will also help with testing in future. I see that you are just adding an event listener and don’t need access to the database.
-- thanks, Abhilash Raj (maxking)
participants (2)
-
Abhilash Raj
-
Дилян Палаузов