summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mailman/docs/NEWS.rst7
-rw-r--r--src/mailman/interfaces/listmanager.py30
-rw-r--r--src/mailman/model/docs/listmanager.rst66
-rw-r--r--src/mailman/model/listmanager.py15
-rw-r--r--src/mailman/model/mailinglist.py4
-rw-r--r--src/mailman/model/tests/test_listmanager.py18
6 files changed, 97 insertions, 43 deletions
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index df8032284..654cf4edc 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -17,6 +17,13 @@ Bugs
* A missing html_to_plain_text_command is now properly detected and logged.
(closes #345)
+Interfaces
+----------
+ * Broaden the semantics for ``IListManager.get()``. This API now accepts
+ both ``List-ID``s and fully qualified list names, since that's the most
+ common use case. There's now a separate ``.get_by_fqdn()`` which only
+ accepts the latter and mirrors the already existing ``.get_by_list_id()``.
+
3.1.0 -- "Between The Wheels"
=============================
diff --git a/src/mailman/interfaces/listmanager.py b/src/mailman/interfaces/listmanager.py
index 3f52d6f0e..dcd4ba152 100644
--- a/src/mailman/interfaces/listmanager.py
+++ b/src/mailman/interfaces/listmanager.py
@@ -94,22 +94,36 @@ class IListManager(Interface):
:raise `ListAlreadyExistsError` if the named list already exists.
"""
- def get(fqdn_listname):
+ def get(list_spec):
+ """Return the mailing list with the given specification, if it exists.
+
+ :param list_spec: Either the fully qualified name of the mailing list,
+ or its List-ID. If list_spec has an `@` in it, it's considered an
+ FQDN listname, otherwise it's considered a List-ID.
+ :type list_spec: str
+ :return: the matching mailing list or None if no matching list is
+ found.
+ :rtype: IMailingList
+ """
+
+ def get_by_fqdn(fqdn_listname):
"""Return the mailing list with the given name, if it exists.
:param fqdn_listname: The fully qualified name of the mailing list.
- :type fqdn_listname: Unicode.
- :return: the matching `IMailingList` or None if the named list does
- not exist.
+ :type fqdn_listname: str
+ :return: the matching mailing list or None if no matching list is
+ found.
+ :rtype: IMailingList
"""
def get_by_list_id(list_id):
"""Return the mailing list with the given list id, if it exists.
- :param fqdn_listname: The fully qualified name of the mailing list.
- :type fqdn_listname: Unicode.
- :return: the matching `IMailingList` or None if the named list does
- not exist.
+ :param list_id: The List-ID
+ :type list_id: str
+ :return: the matching mailing list or None if no matching list is
+ found.
+ :rtype: IMailingList
"""
def delete(mlist):
diff --git a/src/mailman/model/docs/listmanager.rst b/src/mailman/model/docs/listmanager.rst
index 8ff6ad3b0..234394ac6 100644
--- a/src/mailman/model/docs/listmanager.rst
+++ b/src/mailman/model/docs/listmanager.rst
@@ -16,7 +16,7 @@ Creating a mailing list
Creating the list returns the newly created IMailList object.
>>> from mailman.interfaces.mailinglist import IMailingList
- >>> mlist = list_manager.create('test@example.com')
+ >>> mlist = list_manager.create('ant@example.com')
>>> IMailingList.providedBy(mlist)
True
@@ -26,13 +26,13 @@ mailing list moves to a different host, so it is what uniquely distinguishes
the mailing list to the system.
>>> print(mlist.list_name)
- test
+ ant
>>> print(mlist.mail_host)
example.com
>>> print(mlist.fqdn_listname)
- test@example.com
+ ant@example.com
>>> print(mlist.list_id)
- test.example.com
+ ant.example.com
Deleting a mailing list
@@ -46,9 +46,9 @@ Use the list manager to delete a mailing list.
After deleting the list, you can create it again.
- >>> mlist = list_manager.create('test@example.com')
+ >>> mlist = list_manager.create('ant@example.com')
>>> print(mlist.fqdn_listname)
- test@example.com
+ ant@example.com
Retrieving a mailing list
@@ -57,21 +57,29 @@ Retrieving a mailing list
When a mailing list exists, you can ask the list manager for it and you will
always get the same object back.
- >>> mlist_2 = list_manager.get('test@example.com')
- >>> mlist_2 is mlist
- True
+ >>> list_manager.get('ant@example.com')
+ <mailing list "ant@example.com" at ...>
-You can also get a mailing list by it's list id.
+The ``.get()`` method is ambidextrous, so it also accepts ``List-ID``s.
- >>> mlist_2 = list_manager.get_by_list_id('test.example.com')
- >>> mlist_2 is mlist
- True
+ >>> list_manager.get('ant.example.com')
+ <mailing list "ant@example.com" at ...>
+
+You can get a mailing list specifically by its ``List-ID``.
+
+ >>> list_manager.get_by_list_id('ant.example.com')
+ <mailing list "ant@example.com" at ...>
+
+And you can get a mailing list specifically by its fully-qualified list name.
+
+ >>> list_manager.get_by_fqdn('ant@example.com')
+ <mailing list "ant@example.com" at ...>
If you try to get a list that doesn't existing yet, you get ``None``.
- >>> print(list_manager.get('test_2@example.com'))
+ >>> print(list_manager.get('bee@example.com'))
None
- >>> print(list_manager.get_by_list_id('test_2.example.com'))
+ >>> print(list_manager.get_by_list_id('bee.example.com'))
None
You also get ``None`` if the list name is invalid.
@@ -88,33 +96,33 @@ iterate over the mailing list objects, the list posting addresses, or the list
address components.
::
- >>> mlist_3 = list_manager.create('test_3@example.com')
- >>> mlist_4 = list_manager.create('test_4@example.com')
+ >>> mlist_3 = list_manager.create('cat@example.com')
+ >>> mlist_4 = list_manager.create('dog@example.com')
>>> for name in sorted(list_manager.names):
... print(name)
- test@example.com
- test_3@example.com
- test_4@example.com
+ ant@example.com
+ cat@example.com
+ dog@example.com
>>> for list_id in sorted(list_manager.list_ids):
... print(list_id)
- test.example.com
- test_3.example.com
- test_4.example.com
+ ant.example.com
+ cat.example.com
+ dog.example.com
>>> for fqdn_listname in sorted(m.fqdn_listname
... for m in list_manager.mailing_lists):
... print(fqdn_listname)
- test@example.com
- test_3@example.com
- test_4@example.com
+ ant@example.com
+ cat@example.com
+ dog@example.com
>>> for list_name, mail_host in sorted(list_manager.name_components):
... print(list_name, '@', mail_host)
- test @ example.com
- test_3 @ example.com
- test_4 @ example.com
+ ant @ example.com
+ cat @ example.com
+ dog @ example.com
.. _`RFC 2369`: http://www.faqs.org/rfcs/rfc2369.html
diff --git a/src/mailman/model/listmanager.py b/src/mailman/model/listmanager.py
index 885e5c284..e20598f81 100644
--- a/src/mailman/model/listmanager.py
+++ b/src/mailman/model/listmanager.py
@@ -59,11 +59,11 @@ class ListManager:
return mlist
@dbconnection
- def get(self, store, fqdn_listname):
+ def get(self, store, list_spec):
"""See `IListManager`."""
- listname, at, hostname = fqdn_listname.partition('@')
- list_id = '{}.{}'.format(listname, hostname)
- return store.query(MailingList).filter_by(_list_id=list_id).first()
+ return (self.get_by_fqdn(list_spec)
+ if '@' in list_spec
+ else self.get_by_list_id(list_spec))
@dbconnection
def get_by_list_id(self, store, list_id):
@@ -71,6 +71,13 @@ class ListManager:
return store.query(MailingList).filter_by(_list_id=list_id).first()
@dbconnection
+ def get_by_fqdn(self, store, fqdn_listname):
+ """See `IListManager`."""
+ listname, at, hostname = fqdn_listname.partition('@')
+ list_id = '{}.{}'.format(listname, hostname)
+ return store.query(MailingList).filter_by(_list_id=list_id).first()
+
+ @dbconnection
def delete(self, store, mlist):
"""See `IListManager`."""
fqdn_listname = mlist.fqdn_listname
diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py
index 64d1fe1db..2e50575d5 100644
--- a/src/mailman/model/mailinglist.py
+++ b/src/mailman/model/mailinglist.py
@@ -225,13 +225,13 @@ class MailingList(Model):
listen(cls, 'load', cls._post_load)
def __repr__(self):
- return '<mailing list "{0}" at {1:#x}>'.format(
+ return '<mailing list "{}" at {:#x}>'.format(
self.fqdn_listname, id(self))
@property
def fqdn_listname(self):
"""See `IMailingList`."""
- return '{0}@{1}'.format(self.list_name, self.mail_host)
+ return '{}@{}'.format(self.list_name, self.mail_host)
@property
def list_id(self):
diff --git a/src/mailman/model/tests/test_listmanager.py b/src/mailman/model/tests/test_listmanager.py
index da65f88ce..da8c4f76f 100644
--- a/src/mailman/model/tests/test_listmanager.py
+++ b/src/mailman/model/tests/test_listmanager.py
@@ -135,6 +135,24 @@ class TestListManager(unittest.TestCase):
self.assertEqual(len(result), 1)
self.assertEqual(result[0], cat)
+ def test_find_by_list_spec(self):
+ ant = create_list('ant@example.com')
+ list_manager = getUtility(IListManager)
+ self.assertEqual(list_manager.get('ant@example.com'), ant)
+ self.assertEqual(list_manager.get('ant.example.com'), ant)
+
+ def test_find_by_list_id(self):
+ ant = create_list('ant@example.com')
+ list_manager = getUtility(IListManager)
+ self.assertEqual(list_manager.get_by_list_id('ant.example.com'), ant)
+ self.assertIsNone(list_manager.get_by_list_id('ant@example.com'))
+
+ def test_find_by_fqdn(self):
+ ant = create_list('ant@example.com')
+ list_manager = getUtility(IListManager)
+ self.assertEqual(list_manager.get_by_fqdn('ant@example.com'), ant)
+ self.assertIsNone(list_manager.get_by_fqdn('ant.example.com'))
+
class TestListLifecycleEvents(unittest.TestCase):
layer = ConfigLayer