summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mailman/app/docs/moderator.rst4
-rw-r--r--src/mailman/app/subscriptions.py86
-rw-r--r--src/mailman/app/tests/test_moderation.py5
-rw-r--r--src/mailman/app/tests/test_subscriptions.py9
-rw-r--r--src/mailman/app/tests/test_unsubscriptions.py13
-rw-r--r--src/mailman/app/tests/test_workflowmanager.py5
-rw-r--r--src/mailman/app/workflow.py8
-rw-r--r--src/mailman/commands/eml_confirm.py5
-rw-r--r--src/mailman/commands/eml_membership.py7
-rw-r--r--src/mailman/commands/tests/test_confirm.py10
-rw-r--r--src/mailman/config/configure.zcml8
-rw-r--r--src/mailman/database/alembic/versions/448a93984c35_unsubscription_workflow.py5
-rw-r--r--src/mailman/interfaces/workflow.py14
-rw-r--r--src/mailman/model/docs/subscriptions.rst5
-rw-r--r--src/mailman/model/pending.py4
-rw-r--r--src/mailman/model/tests/test_workflow.py78
-rw-r--r--src/mailman/model/workflow.py13
-rw-r--r--src/mailman/rest/members.py5
-rw-r--r--src/mailman/rest/sub_moderation.py5
-rw-r--r--src/mailman/rest/tests/test_membership.py8
-rw-r--r--src/mailman/rest/tests/test_moderation.py5
-rw-r--r--src/mailman/runners/docs/command.rst3
-rw-r--r--src/mailman/runners/tests/test_confirm.py5
-rw-r--r--src/mailman/runners/tests/test_join.py6
24 files changed, 112 insertions, 204 deletions
diff --git a/src/mailman/app/docs/moderator.rst b/src/mailman/app/docs/moderator.rst
index e183d050c..ce25a4711 100644
--- a/src/mailman/app/docs/moderator.rst
+++ b/src/mailman/app/docs/moderator.rst
@@ -217,12 +217,12 @@ the unsubscribing address is required.
Fred is a member of the mailing list...
>>> from mailman.interfaces.usermanager import IUserManager
- >>> from zope.component import getAdapter, getUtility
+ >>> from zope.component import getUtility
>>> mlist.send_welcome_message = False
>>> fred = getUtility(IUserManager).create_address(
... 'fred@example.com', 'Fred Person')
>>> from mailman.interfaces.subscriptions import ISubscriptionManager
- >>> registrar = getAdapter(mlist, ISubscriptionManager, name='subscribe')
+ >>> registrar = ISubscriptionManager(mlist)
>>> token, token_owner, member = registrar.register(
... fred, pre_verified=True, pre_confirmed=True, pre_approved=True)
>>> member
diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py
index 2790a6751..15df6b3f3 100644
--- a/src/mailman/app/subscriptions.py
+++ b/src/mailman/app/subscriptions.py
@@ -297,7 +297,9 @@ class SubscriptionWorkflow(Workflow):
# We can immediately subscribe the user to the mailing list.
self.member = self.mlist.subscribe(self.subscriber)
# This workflow is done so throw away any associated state.
- getUtility(IWorkflowStateManager).restore(self.name, self.token)
+ if self.token is not None:
+ getUtility(IWorkflowStateManager).discard(self.token)
+ self._set_token(TokenOwner.no_one)
def _step_send_confirmation(self):
self._set_token(TokenOwner.subscriber)
@@ -533,7 +535,9 @@ class UnSubscriptionWorkflow(Workflow):
pass
self.member = None
# This workflow is done so throw away any associated state.
- getUtility(IWorkflowStateManager).restore(self.name, self.token)
+ if self.token is not None:
+ getUtility(IWorkflowStateManager).discard(self.token)
+ self._set_token(TokenOwner.no_one)
def _step_unsubscribe_from_restored(self):
# Prevent replay attacks.
@@ -546,48 +550,11 @@ class UnSubscriptionWorkflow(Workflow):
self.push('do_unsubscription')
-class BaseSubscriptionManager:
- """Base class to handle registration and un-registration workflows."""
-
- def __init__(self, mlist):
- self._mlist = mlist
-
- def _get_workflow(self):
- raise NotImplementedError
-
- def register(self, subscriber=None, *,
- pre_verified=False, pre_confirmed=False, pre_approved=False):
- raise NotImplementedError
-
- def unregister(self, subscriber=None, *,
- pre_confirmed=False, pre_approved=False):
- raise NotImplementedError
-
- def confirm(self, token):
- workflow = self._get_workflow()
- workflow.token = token
- workflow.restore()
- # In order to just run the whole workflow, all we need to do
- # is iterate over the workflow object. On calling the __next__
- # over the workflow iterator it automatically executes the steps
- # that needs to be done.
- list(workflow)
- return workflow.token, workflow.token_owner, workflow.member
-
- def discard(self, token):
- with flush():
- getUtility(IPendings).confirm(token)
- getUtility(IWorkflowStateManager).discard(
- self._get_workflow().name, token)
-
-
@public
@implementer(ISubscriptionManager)
-class SubscriptionManager(BaseSubscriptionManager):
- """Handle registrations and confirmations for subscriptions."""
-
- def _get_workflow(self):
- return SubscriptionWorkflow(self._mlist)
+class SubscriptionManager:
+ def __init__(self, mlist):
+ self._mlist = mlist
def register(self, subscriber=None, *,
pre_verified=False, pre_confirmed=False, pre_approved=False):
@@ -600,15 +567,6 @@ class SubscriptionManager(BaseSubscriptionManager):
list(workflow)
return workflow.token, workflow.token_owner, workflow.member
-
-@public
-@implementer(ISubscriptionManager)
-class UnsubscriptionManager(BaseSubscriptionManager):
- """Handle un-subscriptions and confirmations for un-subscriptions."""
-
- def _get_workflow(self):
- return UnSubscriptionWorkflow(self._mlist)
-
def unregister(self, subscriber=None, *,
pre_confirmed=False, pre_approved=False):
workflow = UnSubscriptionWorkflow(
@@ -618,6 +576,32 @@ class UnsubscriptionManager(BaseSubscriptionManager):
list(workflow)
return workflow.token, workflow.token_owner, workflow.member
+ def confirm(self, token):
+ if token is None:
+ raise LookupError
+ pendable = getUtility(IPendings).confirm(token, expunge=False)
+ if pendable is None:
+ raise LookupError
+ workflow_type = pendable.get('type')
+ assert workflow_type in (PendableSubscription.PEND_TYPE,
+ PendableUnsubscription.PEND_TYPE)
+ workflow = (SubscriptionWorkflow
+ if workflow_type == PendableSubscription.PEND_TYPE
+ else UnSubscriptionWorkflow)(self._mlist)
+ workflow.token = token
+ workflow.restore()
+ # In order to just run the whole workflow, all we need to do
+ # is iterate over the workflow object. On calling the __next__
+ # over the workflow iterator it automatically executes the steps
+ # that needs to be done.
+ list(workflow)
+ return workflow.token, workflow.token_owner, workflow.member
+
+ def discard(self, token):
+ with flush():
+ getUtility(IPendings).confirm(token)
+ getUtility(IWorkflowStateManager).discard(token)
+
def _handle_confirmation_needed_events(event, template_name):
subject = 'confirm {}'.format(event.token)
diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py
index 63b665948..90485bfad 100644
--- a/src/mailman/app/tests/test_moderation.py
+++ b/src/mailman/app/tests/test_moderation.py
@@ -35,7 +35,7 @@ from mailman.testing.helpers import (
specialized_message_from_string as mfs)
from mailman.testing.layers import SMTPLayer
from mailman.utilities.datetime import now
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestModeration(unittest.TestCase):
@@ -153,8 +153,7 @@ class TestUnsubscription(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
- self._registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ self._registrar = ISubscriptionManager(self._mlist)
def test_unsubscribe_defer(self):
# When unsubscriptions must be approved by the moderator, but the
diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/app/tests/test_subscriptions.py
index 9f02593a9..a6a00d80e 100644
--- a/src/mailman/app/tests/test_subscriptions.py
+++ b/src/mailman/app/tests/test_subscriptions.py
@@ -359,8 +359,6 @@ class TestSubscriptionWorkflow(unittest.TestCase):
pre_verified=True,
pre_confirmed=True,
pre_approved=True)
- # Cache the token.
- token = workflow.token
# Consume the entire state machine.
list(workflow)
# Anne is now a member of the mailing list.
@@ -370,13 +368,6 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# The workflow is done, so it has no token.
self.assertIsNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
- # The pendable associated with the token has been evicted.
- self.assertIsNone(getUtility(IPendings).confirm(token, expunge=False))
- # There is no saved workflow associated with the token. This shows up
- # as an exception when we try to restore the workflow.
- new_workflow = SubscriptionWorkflow(self._mlist)
- new_workflow.token = token
- self.assertRaises(LookupError, new_workflow.restore)
def test_moderator_approves(self):
# The workflow runs until moderator approval is required, at which
diff --git a/src/mailman/app/tests/test_unsubscriptions.py b/src/mailman/app/tests/test_unsubscriptions.py
index b7693f774..d8dbc18cb 100644
--- a/src/mailman/app/tests/test_unsubscriptions.py
+++ b/src/mailman/app/tests/test_unsubscriptions.py
@@ -184,7 +184,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
self.assertIsNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
- def test_do_unsubscription_pre_approved_pre_onfirmed(self):
+ def test_do_unsubscription_pre_approved_pre_confirmed(self):
# A moderation-requiring un-subscription policy plus a pre-appvoed
# address means the user gets un-subscribed to the mailing list without
# any further confirmations or approvals.
@@ -201,14 +201,12 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
def test_do_unsubscription_cleanups(self):
- # Once the user is un-subscribed, the token and its associated pending
+ # Once the user is unsubscribed, the token and its associated pending
# database record will be removed from the database.
self._mlist.unsubscription_policy = SubscriptionPolicy.open
workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
pre_approved=True,
pre_confirmed=True)
- # Cache the token.
- token = workflow.token
# Run the workflow.
list(workflow)
# Anne is now un-subscribed from the list.
@@ -217,13 +215,6 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# Workflow is done, so it has no token.
self.assertIsNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
- # The pendable associated with the token as been evicted.
- self.assertIsNone(getUtility(IPendings).confirm(token, expunge=False))
- # There is no workflow associated with the token. This shows up as an
- # exception when trying to restore the workflow.
- new_workflow = UnSubscriptionWorkflow(self._mlist)
- new_workflow.token = token
- self.assertRaises(LookupError, new_workflow.restore)
def test_moderator_approves(self):
# The workflow runs until moderator approval is required, at which
diff --git a/src/mailman/app/tests/test_workflowmanager.py b/src/mailman/app/tests/test_workflowmanager.py
index f72486111..4193beefe 100644
--- a/src/mailman/app/tests/test_workflowmanager.py
+++ b/src/mailman/app/tests/test_workflowmanager.py
@@ -28,7 +28,7 @@ from mailman.interfaces.usermanager import IUserManager
from mailman.testing.helpers import get_queue_messages
from mailman.testing.layers import ConfigLayer
from mailman.utilities.datetime import now
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestRegistrar(unittest.TestCase):
@@ -38,8 +38,7 @@ class TestRegistrar(unittest.TestCase):
def setUp(self):
self._mlist = create_list('ant@example.com')
- self._registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ self._registrar = ISubscriptionManager(self._mlist)
self._pendings = getUtility(IPendings)
self._anne = getUtility(IUserManager).create_address(
'anne@example.com')
diff --git a/src/mailman/app/workflow.py b/src/mailman/app/workflow.py
index eec8a14a8..762b0fd91 100644
--- a/src/mailman/app/workflow.py
+++ b/src/mailman/app/workflow.py
@@ -132,15 +132,11 @@ class Workflow:
raise AssertionError(
"Can't save a workflow state with more than one step "
"in the queue")
- state_manager.save(
- self.__class__.__name__,
- self.token,
- step,
- json.dumps(data))
+ state_manager.save(self.token, step, json.dumps(data))
def restore(self):
state_manager = getUtility(IWorkflowStateManager)
- state = state_manager.restore(self.__class__.__name__, self.token)
+ state = state_manager.restore(self.token)
if state is None:
# The token doesn't exist in the database.
raise LookupError(self.token)
diff --git a/src/mailman/commands/eml_confirm.py b/src/mailman/commands/eml_confirm.py
index b8e1610c4..6787b0987 100644
--- a/src/mailman/commands/eml_confirm.py
+++ b/src/mailman/commands/eml_confirm.py
@@ -21,7 +21,6 @@ from mailman import public
from mailman.core.i18n import _
from mailman.interfaces.command import ContinueProcessing, IEmailCommand
from mailman.interfaces.subscriptions import ISubscriptionManager, TokenOwner
-from zope.component import getAdapter
from zope.interface import implementer
@@ -50,8 +49,8 @@ class Confirm:
tokens.add(token)
results.confirms = tokens
try:
- new_token, token_owner, member = getAdapter(
- mlist, ISubscriptionManager, name='subscribe').confirm(token)
+ new_token, token_owner, member = ISubscriptionManager(
+ mlist).confirm(token)
if new_token is None:
assert token_owner is TokenOwner.no_one, token_owner
assert member is not None, member
diff --git a/src/mailman/commands/eml_membership.py b/src/mailman/commands/eml_membership.py
index 2c535a9d5..e658e7b58 100644
--- a/src/mailman/commands/eml_membership.py
+++ b/src/mailman/commands/eml_membership.py
@@ -25,7 +25,7 @@ from mailman.interfaces.member import DeliveryMode, MemberRole
from mailman.interfaces.subscriptions import (
ISubscriptionManager, ISubscriptionService)
from mailman.interfaces.usermanager import IUserManager
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
from zope.interface import implementer
@@ -101,8 +101,7 @@ used.
print(_('$person is already a member'), file=results)
return ContinueProcessing.yes
subscriber = match_subscriber(email, display_name)
- getAdapter(
- mlist, ISubscriptionManager, name='subscribe').register(subscriber)
+ ISubscriptionManager(mlist).register(subscriber)
print(_('Confirmation email sent to $person'), file=results)
return ContinueProcessing.yes
@@ -197,7 +196,7 @@ You may be asked to confirm your request.""")
return ContinueProcessing.yes
# Ignore any subsequent 'leave' commands.
already_left.add(email)
- manager = getAdapter(mlist, ISubscriptionManager, name='unsubscribe')
+ manager = ISubscriptionManager(mlist)
token, token_owner, member = manager.unregister(user_address)
person = formataddr((user.display_name, email)) # noqa
if member is None:
diff --git a/src/mailman/commands/tests/test_confirm.py b/src/mailman/commands/tests/test_confirm.py
index 7351bd6b7..e0f816f24 100644
--- a/src/mailman/commands/tests/test_confirm.py
+++ b/src/mailman/commands/tests/test_confirm.py
@@ -30,7 +30,7 @@ from mailman.interfaces.usermanager import IUserManager
from mailman.runners.command import CommandRunner, Results
from mailman.testing.helpers import get_queue_messages, make_testable_runner
from mailman.testing.layers import ConfigLayer
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestConfirm(unittest.TestCase):
@@ -42,8 +42,8 @@ class TestConfirm(unittest.TestCase):
self._mlist = create_list('test@example.com')
anne = getUtility(IUserManager).create_address(
'anne@example.com', 'Anne Person')
- self._token, token_owner, member = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe').register(anne)
+ self._token, token_owner, member = ISubscriptionManager(
+ self._mlist).register(anne)
self._command = Confirm()
# Clear the virgin queue.
get_queue_messages('virgin')
@@ -88,8 +88,8 @@ class TestEmailResponses(unittest.TestCase):
'bart@example.com', 'Bart Person')
# Clear any previously queued confirmation messages.
get_queue_messages('virgin')
- self._token, token_owner, member = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe').register(bart)
+ self._token, token_owner, member = ISubscriptionManager(
+ self._mlist).register(bart)
# There should now be one email message in the virgin queue, i.e. the
# confirmation message sent to Bart.
items = get_queue_messages('virgin', expected_count=1)
diff --git a/src/mailman/config/configure.zcml b/src/mailman/config/configure.zcml
index 338f02e1c..2fd0c8788 100644
--- a/src/mailman/config/configure.zcml
+++ b/src/mailman/config/configure.zcml
@@ -50,14 +50,6 @@
for="mailman.interfaces.mailinglist.IMailingList"
provides="mailman.interfaces.subscriptions.ISubscriptionManager"
factory="mailman.app.subscriptions.SubscriptionManager"
- name='subscribe'
- />
-
- <adapter
- for="mailman.interfaces.mailinglist.IMailingList"
- provides="mailman.interfaces.subscriptions.ISubscriptionManager"
- factory="mailman.app.subscriptions.UnsubscriptionManager"
- name='unsubscribe'
/>
<utility
diff --git a/src/mailman/database/alembic/versions/448a93984c35_unsubscription_workflow.py b/src/mailman/database/alembic/versions/448a93984c35_unsubscription_workflow.py
index 85003bd1e..dc57c8aee 100644
--- a/src/mailman/database/alembic/versions/448a93984c35_unsubscription_workflow.py
+++ b/src/mailman/database/alembic/versions/448a93984c35_unsubscription_workflow.py
@@ -9,7 +9,7 @@ import sqlalchemy as sa
from alembic import op
from mailman.database.helpers import exists_in_db
-from mailman.database.types import Enum
+from mailman.database.types import Enum, SAUnicode
from mailman.interfaces.mailinglist import SubscriptionPolicy
@@ -35,8 +35,11 @@ def upgrade():
op.execute(mlist.update().values(
{'unsubscription_policy':
op.inline_literal(SubscriptionPolicy.open)}))
+ with op.batch_alter_table('workflowstate') as batch_op:
+ batch_op.drop_column('name')
def downgrade():
with op.batch_alter_table('mailinglist') as batch_op:
batch_op.drop_column('unsubscription_policy')
+ op.add_column('workflowstate', sa.Column('name', SAUnicode))
diff --git a/src/mailman/interfaces/workflow.py b/src/mailman/interfaces/workflow.py
index bf2138959..9846f4683 100644
--- a/src/mailman/interfaces/workflow.py
+++ b/src/mailman/interfaces/workflow.py
@@ -25,8 +25,6 @@ from zope.interface import Attribute, Interface
class IWorkflowState(Interface):
"""The state of a workflow."""
- name = Attribute('The name of the workflow.')
-
token = Attribute('A unique key identifying the workflow instance.')
step = Attribute("This workflow's next step.")
@@ -38,11 +36,9 @@ class IWorkflowState(Interface):
class IWorkflowStateManager(Interface):
"""The workflow states manager."""
- def save(name, token, step, data=None):
+ def save(token, step, data=None):
"""Save the state of a workflow.
- :param name: The name of the workflow.
- :type name: str
:param token: A unique token identifying this workflow instance.
:type token: str
:param step: The next step for this workflow.
@@ -51,11 +47,9 @@ class IWorkflowStateManager(Interface):
:type data: str
"""
- def restore(name, token):
+ def restore(token):
"""Get the saved state for a workflow or None if nothing was saved.
- :param name: The name of the workflow.
- :type name: str
:param token: A unique token identifying this workflow instance.
:type token: str
:return: The saved state associated with this name/token pair, or None
@@ -63,11 +57,9 @@ class IWorkflowStateManager(Interface):
:rtype: ``IWorkflowState``
"""
- def discard(name, token):
+ def discard(token):
"""Throw away the saved state for a workflow.
- :param name: The name of the workflow.
- :type name: str
:param token: A unique token identifying this workflow instance.
:type token: str
"""
diff --git a/src/mailman/model/docs/subscriptions.rst b/src/mailman/model/docs/subscriptions.rst
index 4c079d542..1e1810a7a 100644
--- a/src/mailman/model/docs/subscriptions.rst
+++ b/src/mailman/model/docs/subscriptions.rst
@@ -13,9 +13,8 @@ To begin, adapt a mailing list to an ``ISubscriptionManager``. This is a
named interface because the same interface manages both subscriptions and
unsubscriptions.
- >>> from zope.component import getAdapter
>>> mlist = create_list('ant@example.com')
- >>> manager = getAdapter(mlist, ISubscriptionManager, 'subscribe')
+ >>> manager = ISubscriptionManager(mlist)
Either addresses or users with a preferred address can be registered.
@@ -114,7 +113,7 @@ that their email address is already verified, that step is not required. To
begin with unsubscribing, you need to adapt the mailing list to the same
interface, but with a different name.
- >>> manager = getAdapter(mlist, ISubscriptionManager, 'unsubscribe')
+ >>> manager = ISubscriptionManager(mlist)
If the mailing list's unsubscription policy is open, unregistering the
subscription takes effect immediately.
diff --git a/src/mailman/model/pending.py b/src/mailman/model/pending.py
index 9d8315605..7e7f0b2eb 100644
--- a/src/mailman/model/pending.py
+++ b/src/mailman/model/pending.py
@@ -130,8 +130,8 @@ class Pendings:
# Iterate on PendedKeyValue entries that are associated with the
# pending object's ID. Watch out for type conversions.
for keyvalue in pending.key_values:
- # The `type` key is special and served. It is not JSONified. See
- # the IPendable interface for details.
+ # The `type` key is special and reserved. It is not JSONified.
+ # See the IPendable interface for details.
if keyvalue.key == 'type':
value = keyvalue.value
else:
diff --git a/src/mailman/model/tests/test_workflow.py b/src/mailman/model/tests/test_workflow.py
index ee14f17a7..6aade980b 100644
--- a/src/mailman/model/tests/test_workflow.py
+++ b/src/mailman/model/tests/test_workflow.py
@@ -32,116 +32,88 @@ class TestWorkflow(unittest.TestCase):
def test_save_restore_workflow(self):
# Save and restore a workflow.
- name = 'ant'
token = 'bee'
step = 'cat'
data = 'dog'
- self._manager.save(name, token, step, data)
- state = self._manager.restore(name, token)
- self.assertEqual(state.name, name)
+ self._manager.save(token, step, data)
+ state = self._manager.restore(token)
self.assertEqual(state.token, token)
self.assertEqual(state.step, step)
self.assertEqual(state.data, data)
def test_save_restore_workflow_without_step(self):
# Save and restore a workflow that contains no step.
- name = 'ant'
token = 'bee'
data = 'dog'
- self._manager.save(name, token, data=data)
- state = self._manager.restore(name, token)
- self.assertEqual(state.name, name)
+ self._manager.save(token, data=data)
+ state = self._manager.restore(token)
self.assertEqual(state.token, token)
self.assertIsNone(state.step)
self.assertEqual(state.data, data)
def test_save_restore_workflow_without_data(self):
# Save and restore a workflow that contains no data.
- name = 'ant'
token = 'bee'
step = 'cat'
- self._manager.save(name, token, step)
- state = self._manager.restore(name, token)
- self.assertEqual(state.name, name)
+ self._manager.save(token, step)
+ state = self._manager.restore(token)
self.assertEqual(state.token, token)
self.assertEqual(state.step, step)
self.assertIsNone(state.data)
def test_save_restore_workflow_without_step_or_data(self):
# Save and restore a workflow that contains no step or data.
- name = 'ant'
token = 'bee'
- self._manager.save(name, token)
- state = self._manager.restore(name, token)
- self.assertEqual(state.name, name)
+ self._manager.save(token)
+ state = self._manager.restore(token)
self.assertEqual(state.token, token)
self.assertIsNone(state.step)
self.assertIsNone(state.data)
- def test_restore_workflow_with_no_matching_name(self):
- # Try to restore a workflow that has no matching name in the database.
- name = 'ant'
- token = 'bee'
- self._manager.save(name, token)
- state = self._manager.restore('ewe', token)
- self.assertIsNone(state)
-
def test_restore_workflow_with_no_matching_token(self):
# Try to restore a workflow that has no matching token in the database.
- name = 'ant'
- token = 'bee'
- self._manager.save(name, token)
- state = self._manager.restore(name, 'fly')
- self.assertIsNone(state)
-
- def test_restore_workflow_with_no_matching_token_or_name(self):
- # Try to restore a workflow that has no matching token or name in the
- # database.
- name = 'ant'
token = 'bee'
- self._manager.save(name, token)
- state = self._manager.restore('ewe', 'fly')
+ self._manager.save(token)
+ state = self._manager.restore('fly')
self.assertIsNone(state)
def test_restore_removes_record(self):
- name = 'ant'
token = 'bee'
self.assertEqual(self._manager.count, 0)
- self._manager.save(name, token)
+ self._manager.save(token)
self.assertEqual(self._manager.count, 1)
- self._manager.restore(name, token)
+ self._manager.restore(token)
self.assertEqual(self._manager.count, 0)
def test_save_after_restore(self):
- name = 'ant'
token = 'bee'
self.assertEqual(self._manager.count, 0)
- self._manager.save(name, token)
+ self._manager.save(token)
self.assertEqual(self._manager.count, 1)
- self._manager.restore(name, token)
+ self._manager.restore(token)
self.assertEqual(self._manager.count, 0)
- self._manager.save(name, token)
+ self._manager.save(token)
self.assertEqual(self._manager.count, 1)
def test_discard(self):
# Discard some workflow state. This is use by
# ISubscriptionManager.discard().
- self._manager.save('ant', 'token', 'one')
- self._manager.save('bee', 'token', 'two')
- self._manager.save('ant', 'nekot', 'three')
- self._manager.save('bee', 'nekot', 'four')
+ self._manager.save('token1', 'one')
+ self._manager.save('token2', 'two')
+ self._manager.save('token3', 'three')
+ self._manager.save('token4', 'four')
self.assertEqual(self._manager.count, 4)
- self._manager.discard('bee', 'token')
+ self._manager.discard('token2')
self.assertEqual(self._manager.count, 3)
- state = self._manager.restore('ant', 'token')
+ state = self._manager.restore('token1')
self.assertEqual(state.step, 'one')
- state = self._manager.restore('bee', 'token')
+ state = self._manager.restore('token2')
self.assertIsNone(state)
- state = self._manager.restore('ant', 'nekot')
+ state = self._manager.restore('token3')
self.assertEqual(state.step, 'three')
- state = self._manager.restore('bee', 'nekot')
+ state = self._manager.restore('token4')
self.assertEqual(state.step, 'four')
def test_discard_missing_workflow(self):
- self._manager.discard('bogus-name', 'bogus-token')
+ self._manager.discard('bogus-token')
self.assertEqual(self._manager.count, 0)
diff --git a/src/mailman/model/workflow.py b/src/mailman/model/workflow.py
index 1072fa548..53763a0e8 100644
--- a/src/mailman/model/workflow.py
+++ b/src/mailman/model/workflow.py
@@ -33,7 +33,6 @@ class WorkflowState(Model):
__tablename__ = 'workflowstate'
- name = Column(SAUnicode, primary_key=True)
token = Column(SAUnicode, primary_key=True)
step = Column(SAUnicode)
data = Column(SAUnicode)
@@ -45,23 +44,23 @@ class WorkflowStateManager:
"""See `IWorkflowStateManager`."""
@dbconnection
- def save(self, store, name, token, step=None, data=None):
+ def save(self, store, token, step=None, data=None):
"""See `IWorkflowStateManager`."""
- state = WorkflowState(name=name, token=token, step=step, data=data)
+ state = WorkflowState(token=token, step=step, data=data)
store.add(state)
@dbconnection
- def restore(self, store, name, token):
+ def restore(self, store, token):
"""See `IWorkflowStateManager`."""
- state = store.query(WorkflowState).get((name, token))
+ state = store.query(WorkflowState).get(token)
if state is not None:
store.delete(state)
return state
@dbconnection
- def discard(self, store, name, token):
+ def discard(self, store, token):
"""See `IWorkflowStateManager`."""
- state = store.query(WorkflowState).get((name, token))
+ state = store.query(WorkflowState).get(token)
if state is not None:
store.delete(state)
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py
index fd9f141cc..b35440af4 100644
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -37,7 +37,7 @@ from mailman.rest.preferences import Preferences, ReadOnlyPreferences
from mailman.rest.validator import (
Validator, enum_validator, subscriber_validator)
from uuid import UUID
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class _MemberBase(CollectionMixin):
@@ -253,8 +253,7 @@ class AllMembers(_MemberBase):
# Now we can run the registration process until either the
# subscriber is subscribed, or the workflow is paused for
# verification, confirmation, or approval.
- registrar = getAdapter(
- mlist, ISubscriptionManager, name='subscribe')
+ registrar = ISubscriptionManager(mlist)
try:
token, token_owner, member = registrar.register(
subscriber,
diff --git a/src/mailman/rest/sub_moderation.py b/src/mailman/rest/sub_moderation.py
index 273d4c3a0..55b6a7609 100644
--- a/src/mailman/rest/sub_moderation.py
+++ b/src/mailman/rest/sub_moderation.py
@@ -28,7 +28,7 @@ from mailman.rest.helpers import (
CollectionMixin, bad_request, child, conflict, etag, no_content,
not_found, okay)
from mailman.rest.validator import Validator, enum_validator
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class _ModerationBase:
@@ -54,8 +54,7 @@ class IndividualRequest(_ModerationBase):
def __init__(self, mlist, token):
super().__init__()
self._mlist = mlist
- self._registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ self._registrar = ISubscriptionManager(self._mlist)
self._token = token
def on_get(self, request, response):
diff --git a/src/mailman/rest/tests/test_membership.py b/src/mailman/rest/tests/test_membership.py
index 9e5a486f3..f705fdcf6 100644
--- a/src/mailman/rest/tests/test_membership.py
+++ b/src/mailman/rest/tests/test_membership.py
@@ -34,7 +34,7 @@ from mailman.testing.helpers import (
from mailman.testing.layers import ConfigLayer, RESTLayer
from mailman.utilities.datetime import now
from urllib.error import HTTPError
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestMembership(unittest.TestCase):
@@ -214,8 +214,7 @@ class TestMembership(unittest.TestCase):
def test_duplicate_pending_subscription(self):
# Issue #199 - a member's subscription is already pending and they try
# to subscribe again.
- registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ registrar = ISubscriptionManager(self._mlist)
with transaction():
self._mlist.subscription_policy = SubscriptionPolicy.moderate
anne = self._usermanager.create_address('anne@example.com')
@@ -238,8 +237,7 @@ class TestMembership(unittest.TestCase):
# Issue #199 - a member's subscription is already pending and they try
# to subscribe again. Unlike above, this pend is waiting for the user
# to confirm their subscription.
- registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ registrar = ISubscriptionManager(self._mlist)
with transaction():
self._mlist.subscription_policy = (
SubscriptionPolicy.confirm_then_moderate)
diff --git a/src/mailman/rest/tests/test_moderation.py b/src/mailman/rest/tests/test_moderation.py
index cbf9c9381..e0c3f1ccf 100644
--- a/src/mailman/rest/tests/test_moderation.py
+++ b/src/mailman/rest/tests/test_moderation.py
@@ -32,7 +32,7 @@ from mailman.testing.helpers import (
specialized_message_from_string as mfs)
from mailman.testing.layers import RESTLayer
from urllib.error import HTTPError
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestPostModeration(unittest.TestCase):
@@ -150,8 +150,7 @@ class TestSubscriptionModeration(unittest.TestCase):
def setUp(self):
with transaction():
self._mlist = create_list('ant@example.com')
- self._registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ self._registrar = ISubscriptionManager(self._mlist)
manager = getUtility(IUserManager)
self._anne = manager.create_address(
'anne@example.com', 'Anne Person')
diff --git a/src/mailman/runners/docs/command.rst b/src/mailman/runners/docs/command.rst
index fec0d628b..2243d4ff4 100644
--- a/src/mailman/runners/docs/command.rst
+++ b/src/mailman/runners/docs/command.rst
@@ -141,9 +141,8 @@ address, and the other is the results of his email command.
2
>>> from mailman.interfaces.subscriptions import ISubscriptionManager
- >>> from zope.component import getAdapter
- >>> manager = getAdapter(mlist, ISubscriptionManager, 'subscribe')
+ >>> manager = ISubscriptionManager(mlist)
>>> for item in messages:
... subject = item.msg['subject']
... print('Subject:', subject)
diff --git a/src/mailman/runners/tests/test_confirm.py b/src/mailman/runners/tests/test_confirm.py
index bb18914d0..af6f03eb5 100644
--- a/src/mailman/runners/tests/test_confirm.py
+++ b/src/mailman/runners/tests/test_confirm.py
@@ -31,7 +31,7 @@ from mailman.testing.helpers import (
get_queue_messages, make_testable_runner,
specialized_message_from_string as mfs)
from mailman.testing.layers import ConfigLayer
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestConfirm(unittest.TestCase):
@@ -47,8 +47,7 @@ class TestConfirm(unittest.TestCase):
self._mlist = create_list('test@example.com')
self._mlist.send_welcome_message = False
anne = getUtility(IUserManager).create_address('anne@example.org')
- registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ registrar = ISubscriptionManager(self._mlist)
self._token, token_owner, member = registrar.register(anne)
def test_confirm_with_re_prefix(self):
diff --git a/src/mailman/runners/tests/test_join.py b/src/mailman/runners/tests/test_join.py
index 1fb1dfe5c..1e249d68f 100644
--- a/src/mailman/runners/tests/test_join.py
+++ b/src/mailman/runners/tests/test_join.py
@@ -31,7 +31,7 @@ from mailman.testing.helpers import (
get_queue_messages, make_testable_runner,
specialized_message_from_string as mfs)
from mailman.testing.layers import ConfigLayer
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestJoin(unittest.TestCase):
@@ -145,8 +145,8 @@ class TestJoinWithDigests(unittest.TestCase):
subject_words = str(items[1].msg['subject']).split()
self.assertEqual(subject_words[0], 'confirm')
token = subject_words[1]
- token, token_owner, rmember = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe').confirm(token)
+ token, token_owner, rmember = ISubscriptionManager(
+ self._mlist).confirm(token)
self.assertIsNone(token)
self.assertEqual(token_owner, TokenOwner.no_one)
# Now, make sure that Anne is a member of the list and is receiving