diff options
| author | Barry Warsaw | 2012-12-25 15:44:40 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2012-12-25 15:44:40 -0500 |
| commit | 9c5a2e27116c95484dd993c4b7ceed64ca9823e4 (patch) | |
| tree | 406e55afc61c602e6dd3f1b98cb6f45f621fcc77 /src | |
| parent | f63a2651d3a1fff24d62de747e2e7ab864a075ee (diff) | |
| parent | e75e3c364a26ee08b0da9b29115de40271f574c5 (diff) | |
| download | mailman-9c5a2e27116c95484dd993c4b7ceed64ca9823e4.tar.gz mailman-9c5a2e27116c95484dd993c4b7ceed64ca9823e4.tar.zst mailman-9c5a2e27116c95484dd993c4b7ceed64ca9823e4.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/bin/master.py | 2 | ||||
| -rw-r--r-- | src/mailman/commands/cli_control.py | 8 | ||||
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 17 | ||||
| -rw-r--r-- | src/mailman/interfaces/member.py | 31 | ||||
| -rw-r--r-- | src/mailman/model/docs/membership.rst | 23 | ||||
| -rw-r--r-- | src/mailman/model/mailinglist.py | 5 | ||||
| -rw-r--r-- | src/mailman/model/member.py | 6 |
7 files changed, 80 insertions, 12 deletions
diff --git a/src/mailman/bin/master.py b/src/mailman/bin/master.py index 25a7dc444..00469c46a 100644 --- a/src/mailman/bin/master.py +++ b/src/mailman/bin/master.py @@ -425,6 +425,7 @@ class Loop: necessary and configured to do so. """ log = logging.getLogger('mailman.runner') + log.info('Master started') self._pause() while True: try: @@ -478,6 +479,7 @@ Runner {0} reached maximum restart limit of {1:d}, not restarting.""", new_pid = self._start_runner(spec) new_info = (rname, slice_number, count, restarts) self._kids.add(new_pid, new_info) + log.info('Master stopped') def cleanup(self): """Ensure that all children have exited.""" diff --git a/src/mailman/commands/cli_control.py b/src/mailman/commands/cli_control.py index b5a79b820..6e211b83c 100644 --- a/src/mailman/commands/cli_control.py +++ b/src/mailman/commands/cli_control.py @@ -48,7 +48,7 @@ qlog = logging.getLogger('mailman.runner') @implementer(ICLISubCommand) class Start: - """Start the Mailman daemons.""" + """Start the Mailman master and runner processes.""" name = 'start' @@ -191,7 +191,7 @@ class SignalCommand: class Stop(SignalCommand): - """Stop the Mailman daemons.""" + """Stop the Mailman master and runner processes.""" name = 'stop' message = _("Shutting down Mailman's master runner") @@ -199,7 +199,7 @@ class Stop(SignalCommand): class Reopen(SignalCommand): - """Reopen the Mailman daemons.""" + """Signal the Mailman processes to re-open their log files..""" name = 'reopen' message = _('Reopening the Mailman runners') @@ -208,7 +208,7 @@ class Reopen(SignalCommand): @implementer(ICLISubCommand) class Restart(SignalCommand): - """Stop the Mailman daemons.""" + """Stop and restart the Mailman runner subprocesses.""" name = 'restart' message = _('Restarting the Mailman runners') diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 64df34ef1..c0a94ab0d 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -73,18 +73,23 @@ Interfaces `IMailingList` to an `IBanManager` to manage the bans for a specific mailing list. To manage the global bans, adapt ``None``. -Integration ------------ - * Added support for Postfix `relay_domains` setting for better virtual domain - support. Contributed by Jimmy Bergman. - Commands -------- * `bin/mailman aliases` loses the `--output`, `--format`, and `--simple` arguments, and adds a `--directory` argument. This is necessary to support the Postfix `relay_domains` support. * `bin/mailman start` was passing the wrong relative path to its runner - subprocesses when -C was given. LP: #982551 + subprocesses when -C was given. (LP: #982551) + +Other +----- + * Added support for Postfix `relay_domains` setting for better virtual domain + support. Contributed by Jimmy Bergman. + * Two new events are triggered on membership changes: `SubscriptionEvent` + when a new member joins a mailing list, and an `UnsubscriptionEvent` when a + member leaves a mailing list. (LP: #1047286) + * Improve the --help text for the `start`, `stop`, `restart`, and `reopen` + subcommands. (LP: #1035033) Bugs ---- diff --git a/src/mailman/interfaces/member.py b/src/mailman/interfaces/member.py index 997338835..815bda2d4 100644 --- a/src/mailman/interfaces/member.py +++ b/src/mailman/interfaces/member.py @@ -26,10 +26,13 @@ __all__ = [ 'DeliveryStatus', 'IMember', 'MemberRole', + 'MembershipChangeEvent', 'MembershipError', 'MembershipIsBannedError', 'MissingPreferredAddressError', 'NotAMemberError', + 'SubscriptionEvent', + 'UnsubscriptionEvent', ] @@ -74,6 +77,34 @@ class MemberRole(Enum): +class MembershipChangeEvent: + """Base class for subscription/unsubscription events.""" + + def __init__(self, mlist, member): + self.mlist = mlist + self.member = member + + +class SubscriptionEvent(MembershipChangeEvent): + """Event which gets triggered when a user joins a mailing list.""" + + def __str__(self): + return '{0} joined {1}'.format(self.member.address, self.mlist.list_id) + + +class UnsubscriptionEvent(MembershipChangeEvent): + """Event which gets triggered when a user leaves a mailing list. + + One thing to keep in mind: because the IMember is deleted when the + unsubscription happens, this event actually gets triggered just before the + member is unsubscribed. + """ + + def __str__(self): + return '{0} left {1}'.format(self.member.address, self.mlist.list_id) + + + class MembershipError(MailmanError): """Base exception for all membership errors.""" diff --git a/src/mailman/model/docs/membership.rst b/src/mailman/model/docs/membership.rst index 3286bfe6e..f257f25ce 100644 --- a/src/mailman/model/docs/membership.rst +++ b/src/mailman/model/docs/membership.rst @@ -315,3 +315,26 @@ Now her membership reflects the new address. >>> for m in bee.members.members: ... print m.member_id.int, m.mailing_list.list_id, m.address.email 7 bee.example.com gperson@example.com + + +Events +====== + +An event is triggered when a new member is subscribed to a mailing list. +:: + + >>> from mailman.testing.helpers import event_subscribers + >>> def handle_event(event): + ... print event + + >>> cat = create_list('cat@example.com') + >>> herb = user_manager.create_address('herb@example.com') + >>> with event_subscribers(handle_event): + ... member = cat.subscribe(herb) + herb@example.com joined cat.example.com + +An event is triggered when a member is unsubscribed from a mailing list. + + >>> with event_subscribers(handle_event): + ... member.unsubscribe() + herb@example.com left cat.example.com diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py index 2c55540be..324e1a1c8 100644 --- a/src/mailman/model/mailinglist.py +++ b/src/mailman/model/mailinglist.py @@ -33,6 +33,7 @@ from storm.locals import ( TimeDelta, Unicode) from urlparse import urljoin from zope.component import getUtility +from zope.event import notify from zope.interface import implementer from mailman.config import config @@ -50,7 +51,8 @@ from mailman.interfaces.mailinglist import ( IAcceptableAlias, IAcceptableAliasSet, IMailingList, Personalization, ReplyToMunging) from mailman.interfaces.member import ( - AlreadySubscribedError, MemberRole, MissingPreferredAddressError) + AlreadySubscribedError, MemberRole, MissingPreferredAddressError, + SubscriptionEvent) from mailman.interfaces.mime import FilterType from mailman.interfaces.nntp import NewsgroupModeration from mailman.interfaces.user import IUser @@ -493,6 +495,7 @@ class MailingList(Model): subscriber=subscriber) member.preferences = Preferences() store.add(member) + notify(SubscriptionEvent(self, member)) return member diff --git a/src/mailman/model/member.py b/src/mailman/model/member.py index 76fe2f992..c189983b9 100644 --- a/src/mailman/model/member.py +++ b/src/mailman/model/member.py @@ -27,6 +27,7 @@ __all__ = [ from storm.locals import Int, Reference, Unicode from storm.properties import UUID from zope.component import getUtility +from zope.event import notify from zope.interface import implementer from mailman.core.constants import system_preferences @@ -36,7 +37,8 @@ from mailman.database.types import Enum from mailman.interfaces.action import Action from mailman.interfaces.address import IAddress from mailman.interfaces.listmanager import IListManager -from mailman.interfaces.member import IMember, MemberRole, MembershipError +from mailman.interfaces.member import ( + IMember, MemberRole, MembershipError, UnsubscriptionEvent) from mailman.interfaces.user import IUser, UnverifiedAddressError from mailman.interfaces.usermanager import IUserManager from mailman.utilities.uid import UniqueIDFactory @@ -186,5 +188,7 @@ class Member(Model): @dbconnection def unsubscribe(self, store): """See `IMember`.""" + # Yes, this must get triggered before self is deleted. + notify(UnsubscriptionEvent(self.mailing_list, self)) store.remove(self.preferences) store.remove(self) |
