------------------------------------------------------------
revno: 6639
committer: Barry Warsaw <[EMAIL PROTECTED]>
branch nick: domains
timestamp: Sat 2008-09-20 00:33:07 -0400
message:
  Support for proper domains by interface.  Add a test and update modules as
  necessary.  Finally delete DEFAULT_EMAIL_HOST and DEFAULT_URL_HOST.  Now
  add_domain() must be called in the confirmation file for every domain.
  
  add_domain() itself is now pretty much just a proxy for the Domain
  constructor.
  
  Add stop() as an alias for pdb.set_trace() to the documentation doctest globs.
added:
  mailman/docs/domains.txt
  mailman/domain.py
modified:
  mailman/Cgi/create.py
  mailman/Defaults.py
  mailman/archiving/mhonarc.py
  mailman/archiving/pipermail.py
  mailman/archiving/prototype.py
  mailman/configuration.py
  mailman/interfaces/domain.py
  mailman/testing/testing.cfg.in
  mailman/tests/test_documentation.py

=== modified file 'mailman/Cgi/create.py'
--- a/mailman/Cgi/create.py     2008-02-08 04:01:48 +0000
+++ b/mailman/Cgi/create.py     2008-09-20 04:33:07 +0000
@@ -151,8 +151,12 @@
     # Make sure the url host name matches one of our virtual domains.  Then
     # calculate the list's posting address.
     url_host = Utils.get_request_domain()
-    email_host = config.get_email_host(url_host)
-    if not email_host:
+    # Find the IDomain matching this url_host if there is one.
+    for email_host, domain in config.domains:
+        if domain.url_host == url_host:
+            email_host = domain.email_host
+            break
+    else:
         safehostname = Utils.websafe(url_host)
         request_creation(doc, cgidata,
                          _('Unknown virtual host: $safehostname'))

=== modified file 'mailman/Defaults.py'
--- a/mailman/Defaults.py       2008-07-10 02:35:44 +0000
+++ b/mailman/Defaults.py       2008-09-20 04:33:07 +0000
@@ -124,40 +124,6 @@
 
 
 #####
-# Virtual domains
-#####
-
-# Mailman needs to know about at least one domain, called the 'site default
-# domain'.  If you run only one domain with Mailman, this will generally be
-# calculated automatically when you configured Mailman.  You can always change
-# this in your mailman.cfg file.  You can also add additional virtual domains
-# in your mailman.cfg file to enable multiple virtual domains.  Every mailing
-# list will be situated in exactly one virtual domain.
-#
-# For Mailman's purposes, a virtual domain associates an email host name with
-# a web host name.  These may be the same, but often they are different, and
-# the list is always referred to by its fully-qualified posting address.  For
-# example, if you created 'mylist' in the example.com domain, people can post
-# to your list via '[EMAIL PROTECTED]'.  They may refer to the web pages via
-# 'www.example.com'.  So your email host name is 'example.com' and your web
-# host name is 'www.example.com'.
-#
-# To add a virtual domain, put a call to add_domain(email_host, url_host) in
-# your mailman.cfg file.  If no add_domain() calls are found, Mailman will
-# automatically add a virtual domain for the following defaults.  However if
-# you explicit add domains, you will need to add these defaults as well.
-#
-# These defaults will be filled in by configure.
-DEFAULT_EMAIL_HOST  = '@MAILHOST@'
-DEFAULT_URL_HOST    = '@URLHOST@'
-
-# Note that you will want to run bin/fix_url.py to change the domain of an
-# existing list.  bin/fix_url.py must be run within the bin/withlist script,
-# like so: bin/withlist -l -r bin/fix_url.py <listname>
-
-
-
-#####
 # Spam avoidance defaults
 #####
 

=== modified file 'mailman/archiving/mhonarc.py'
--- a/mailman/archiving/mhonarc.py      2008-07-10 02:35:44 +0000
+++ b/mailman/archiving/mhonarc.py      2008-09-20 04:33:07 +0000
@@ -52,7 +52,7 @@
     def list_url(mlist):
         """See `IArchiver`."""
         # XXX What about private MHonArc archives?
-        web_host = config.domains.get(mlist.host_name, mlist.host_name)
+        web_host = config.domains[mlist.host_name].url_host
         return Template(config.PUBLIC_ARCHIVE_URL).safe_substitute(
             listname=mlist.fqdn_listname,
             hostname=web_host,

=== modified file 'mailman/archiving/pipermail.py'
--- a/mailman/archiving/pipermail.py    2008-07-05 15:06:37 +0000
+++ b/mailman/archiving/pipermail.py    2008-09-20 04:33:07 +0000
@@ -59,7 +59,15 @@
 
 
 def adapt_mailing_list_for_pipermail(iface, obj):
-    """Adapt IMailingLists to IPipermailMailingList."""
+    """Adapt `IMailingLists` to `IPipermailMailingList`.
+
+    :param iface: The interface to adapt to.
+    :type iface: `zope.interface.Interface`
+    :param obj: The object being adapted.
+    :type obj: any object
+    :return: An `IPipermailMailingList` instance if adaptation succeeded or
+        None if it didn't.
+    """
     if IMailingList.providedBy(obj) and iface is IPipermailMailingList:
         return PipermailMailingListAdapter(obj)
     return None
@@ -82,7 +90,7 @@
         if mlist.archive_private:
             url = mlist.script_url('private') + '/index.html'
         else:
-            web_host = config.domains.get(mlist.host_name, mlist.host_name)
+            web_host = config.domains[mlist.host_name].url_host
             url = Template(config.PUBLIC_ARCHIVE_URL).safe_substitute(
                 listname=mlist.fqdn_listname,
                 hostname=web_host,

=== modified file 'mailman/archiving/prototype.py'
--- a/mailman/archiving/prototype.py    2008-07-10 02:35:44 +0000
+++ b/mailman/archiving/prototype.py    2008-09-20 04:33:07 +0000
@@ -49,8 +49,7 @@
     @staticmethod
     def list_url(mlist):
         """See `IArchiver`."""
-        web_host = config.domains.get(mlist.host_name, mlist.host_name)
-        return 'http://' + web_host
+        return config.domains[mlist.host_name].base_url
 
     @staticmethod
     def permalink(mlist, msg):

=== modified file 'mailman/configuration.py'
--- a/mailman/configuration.py  2008-07-05 15:06:37 +0000
+++ b/mailman/configuration.py  2008-09-20 04:33:07 +0000
@@ -24,6 +24,7 @@
 from mailman import Defaults
 from mailman import Errors
 from mailman import version
+from mailman.domain import Domain
 from mailman.languages import LanguageManager
 
 SPACE = ' '
@@ -45,8 +46,7 @@
 
 class Configuration(object):
     def __init__(self):
-        self.domains = {}       # email host -> web host
-        self._reverse = None
+        self.domains = {}       # email host -> IDomain
         self.qrunners = {}
         self.qrunner_shortcuts = {}
         self.QFILE_SCHEMA_VERSION = version.QFILE_SCHEMA_VERSION
@@ -150,10 +150,6 @@
         del ns['add_qrunner']
         del ns['del_qrunner']
         self.__dict__.update(ns)
-        # Add the default domain if there are no virtual domains currently
-        # defined.
-        if not self.domains:
-            self.add_domain(self.DEFAULT_EMAIL_HOST, self.DEFAULT_URL_HOST)
         # Enable all specified languages, and promote the language manager to
         # a public attribute.
         self.languages = self._languages
@@ -181,36 +177,25 @@
         self.pipelines = {}
         self.commands = {}
 
-    def add_domain(self, email_host, url_host=None):
+    def add_domain(self, *args, **kws):
         """Add a virtual domain.
 
-        :param email_host: The host name for the email interface.
-        :param url_host: Optional host name for the web interface.  If not
-            given, the email host will be used.
+        See `Domain`.
         """
-        if url_host is None:
-            url_host = email_host
-        if email_host in self.domains:
+        domain = Domain(*args, **kws)
+        if domain.email_host in self.domains:
             raise Errors.BadDomainSpecificationError(
-                'Duplicate email host: %s' % email_host)
+                'Duplicate email host: %s' % domain.email_host)
         # Make sure there's only one mapping for the url_host
-        if url_host in self.domains.values():
+        if domain.url_host in self.domains.values():
             raise Errors.BadDomainSpecificationError(
-                'Duplicate url host: %s' % url_host)
+                'Duplicate url host: %s' % domain.url_host)
         # We'll do the reverse mappings on-demand.  There shouldn't be too
         # many virtual hosts that it will really matter that much.
-        self.domains[email_host] = url_host
-        # Invalidate the reverse mapping cache
-        self._reverse = None
+        self.domains[domain.email_host] = domain
 
-    # Given an email host name, the url host name can be looked up directly.
-    # This does the reverse mapping.
-    def get_email_host(self, url_host, default=None):
-        if self._reverse is None:
-            # XXX Can't use a generator comprehension until Python 2.4 is
-            # minimum requirement.
-            self._reverse = dict([(v, k) for k, v in self.domains.items()])
-        return self._reverse.get(url_host, default)
+    # Proxy the docstring for the above method.
+    add_domain.__doc__ = Domain.__init__.__doc__
 
     def add_qrunner(self, name, count=1):
         """Convenient interface for adding additional qrunners.

=== added file 'mailman/docs/domains.txt'
--- a/mailman/docs/domains.txt  1970-01-01 00:00:00 +0000
+++ b/mailman/docs/domains.txt  2008-09-20 04:33:07 +0000
@@ -0,0 +1,74 @@
+Domains
+=======
+
+Domains are how Mailman interacts with email host names and web host names.
+Generally, new domains are registered in the mailman.cfg configuration file by
+calling the add_domain() method.
+
+At a minimum, the email host name must be specified.
+
+    >>> from mailman.configuration import config
+    >>> config.add_domain('example.net')
+
+The domain object can be looked up by email host name.
+
+    >>> domain = config.domains['example.net']
+    >>> print domain.email_host
+    example.net
+
+The base url is calculated by default if not given.
+
+    >>> print domain.base_url
+    http://example.net
+
+There is no description by default.
+
+    >>> print domain.description
+    None
+
+By default, the contact address is the domain's postmaster.
+
+    >>> print domain.contact_address
+    [EMAIL PROTECTED]
+
+And the url_host is by default the same as the email host.
+
+    >>> print domain.url_host
+    example.net
+
+
+Full specification
+------------------
+
+The domain can also be much more fully defined.
+
+    >>> config.add_domain(
+    ...     'example.org', 'https://mail.example.org',
+    ...     'The example domain',
+    ...     '[EMAIL PROTECTED]')
+
+    >>> domain = config.domains['example.org']
+    >>> print domain.email_host
+    example.org
+    >>> print domain.base_url
+    https://mail.example.org
+    >>> print domain.description
+    The example domain
+    >>> print domain.contact_address
+    [EMAIL PROTECTED]
+    >>> print domain.url_host
+    mail.example.org
+
+
+Confirmation tokens
+-------------------
+
+Confirmation tokens can be added to either the email confirmation address...
+
+    >>> print domain.confirm_address('xyz')
+    [EMAIL PROTECTED]
+
+...or the confirmation url.
+
+    >>> print domain.confirm_url('abc')
+    https://mail.example.org/confirm/abc

=== added file 'mailman/domain.py'
--- a/mailman/domain.py 1970-01-01 00:00:00 +0000
+++ b/mailman/domain.py 2008-09-20 04:33:07 +0000
@@ -0,0 +1,67 @@
+# Copyright (C) 2008 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+"""Domains."""
+
+__metaclass__ = type
+__all__ = [
+    'Domain',
+    ]
+
+from urlparse import urljoin, urlparse
+from zope.interface import implements
+
+from mailman.interfaces.domain import IDomain
+
+
+
+class Domain:
+    """Domains."""
+
+    implements(IDomain)
+
+    def __init__(self, email_host, base_url=None, description=None,
+                 contact_address=None):
+        """Create and register a domain.
+
+        :param email_host: The host name for the email interface.
+        :type email_host: string
+        :param base_url: The optional base url for the domain, including
+            scheme.  If not given, it will be constructed from the
+            `email_host` using the http protocol.
+        :type base_url: string
+        :param description: An optional description of the domain.
+        :type description: string
+        :type contact_address: The email address to contact a human for this
+            domain.  If not given, [EMAIL PROTECTED] will be used.
+        """
+        self.email_host = email_host
+        self.base_url = (base_url if base_url is not None else
+                         'http://' + email_host)
+        self.description = description
+        self.contact_address = (contact_address
+                                if contact_address is not None
+                                else 'postmaster@' + email_host)
+        self.url_host = urlparse(self.base_url).netloc
+
+    def confirm_address(self, token=''):
+        """See `IDomain`."""
+        return '[EMAIL PROTECTED]' % (token, self.email_host)
+
+    def confirm_url(self, token=''):
+        """See `IDomain`."""
+        return urljoin(self.base_url, 'confirm/' + token)

=== modified file 'mailman/interfaces/domain.py'
--- a/mailman/interfaces/domain.py      2008-02-08 04:01:48 +0000
+++ b/mailman/interfaces/domain.py      2008-09-20 04:33:07 +0000
@@ -24,30 +24,54 @@
 class IDomain(Interface):
     """Interface representing domains."""
 
-    domain_name = Attribute(
-        """The domain's name, e.g. python.org.""")
+    email_host = Attribute(
+        """The host name for email for this domain.
+
+        :type: string
+        """)
+
+    url_host = Attribute(
+        """The host name for the web interface for this domain.
+
+        :type: string
+        """)
+
+    base_url = Attribute(
+        """The base url for the Mailman server at this domain.
+
+        The base url includes the scheme and host name.
+
+        :type: string
+        """)
 
     description = Attribute(
         """The human readable description of the domain name.
 
-        E.g. Python Dot Org or mail.python.org.
+        :type: string
         """)
 
     contact_address = Attribute(
         """The contact address for the human at this domain.
 
         E.g. [EMAIL PROTECTED]
-        """)
-
-    base_url = Attribute(
-        """The base url for the Mailman server at this domain.
-
-        E.g. https://mail.python.org
+
+        :type: string
         """)
 
     def confirm_address(token=''):
-        """The address used for various forms of email confirmation."""
+        """The address used for various forms of email confirmation.
+
+        :param token: The confirmation token to use in the email address.
+        :type token: string
+        :return: The email confirmation address.
+        :rtype: string
+        """
 
     def confirm_url(token=''):
-        """The url used for various forms of confirmation."""
+        """The url used for various forms of confirmation.
 
+        :param token: The confirmation token to use in the url.
+        :type token: string
+        :return: The confirmation url.
+        :rtype: string
+        """

=== modified file 'mailman/testing/testing.cfg.in'
--- a/mailman/testing/testing.cfg.in    2008-07-05 14:41:12 +0000
+++ b/mailman/testing/testing.cfg.in    2008-09-20 04:33:07 +0000
@@ -12,6 +12,6 @@
 MAIL_ARCHIVE_BASEURL = 'http://go.mail-archive.dev/'
 MAIL_ARCHIVE_RECIPIENT = '[EMAIL PROTECTED]'
 
-add_domain('example.com', 'www.example.com')
+add_domain('example.com', 'http://www.example.com')
 
 # bin/testall will add additional runtime configuration variables here.

=== modified file 'mailman/tests/test_documentation.py'
--- a/mailman/tests/test_documentation.py       2008-07-06 14:27:05 +0000
+++ b/mailman/tests/test_documentation.py       2008-09-20 04:33:07 +0000
@@ -53,6 +53,14 @@
     return message
 
 
+def stop():
+    """Call into pdb.set_trace()"""
+    # Do the import here so that you get the wacky special hacked pdb instead
+    # of Python's normal pdb.
+    import pdb
+    pdb.set_trace()
+
+
 def setup(testobj):
     """Test setup."""
     smtpd = SMTPServer()
@@ -64,6 +72,10 @@
     testobj.globs['message_from_string'] = specialized_message_from_string
     testobj.globs['commit'] = config.db.commit
     testobj.globs['smtpd'] = smtpd
+    testobj.globs['stop'] = stop
+    # Stash the current state of the global domains away for restoration in
+    # the teardown.
+    testobj._domains = config.domains.copy()
 
 
 
@@ -71,6 +83,8 @@
     """Clear all persistent data at the end of a doctest."""
     # Clear the database of all rows.
     config.db._reset()
+    # Reset the global domains.
+    config.domains = testobj._domains
     # Remove all but the default style.
     for style in style_manager.styles:
         if style.name <> 'default':



--
Primary development focus
https://code.launchpad.net/~mailman-coders/mailman/3.0

You are receiving this branch notification because you are subscribed to it.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe: 
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org

Reply via email to