Update of /cvsroot/mailman/mailman3/src/mailman/interfaces
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31133/src/mailman/interfaces

Added Files:
      Tag: 3.0
        __init__.py enum.py features.py lists.py members.py 
        profiles.py qrunner.py roles.py sites.py storages.py 
        transactions.py units.py user.py users.py 
Log Message:
Initial checkin of Mailman3 source

--- NEW FILE: __init__.py ---

--- NEW FILE: enum.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Enumeration meta class.

To define your own enumeration, do something like:

class Color(Enum):
    red = 1
    green = 2
    blue = 3

Now, Color.red, Color.green and Color.blue behave totally
different: they are enumerated values, not integers.  Enums support comparison
but not arithmetic.

Enumerations cannot be instantiated; however they can be subclassed.
"""

COMMASPACE = ', '

# Based on example by Jeremy Hylton
# Modified and extended by Barry Warsaw



class EnumMetaclass(type):
    def __init__(cls, name, bases, dict):
        # cls == the class being defined
        # name == the name of the class
        # bases == the class's bases
        # dict == the class attributes
        super(EnumMetaclass, cls).__init__(name, bases, dict)
        # Store EnumInstances here for easy access.
        cls._members = []
        cls._sorted = []
        # For each class attribute, create an EnumInstance and store that back
        # on the class instead of the int.  Skip Python reserved names.
        for attr in dict.keys():
            if not (attr.startswith('__') and attr.endswith('__')):
                enumval = EnumInstance(name, dict[attr], attr)
                # Store as an attribute on the class, and save the attr name
                setattr(cls, attr, enumval)
                cls._members.append(attr)
                cls._sorted.append(enumval)
        cls._sorted.sort()

    def __getattr__(cls, name):
        if name == '__members__':
            return cls._members
        raise AttributeError, name

    def __repr__(cls):
        # s1 will hold the list of base classes, sans the Enum class
        # s2 wll hold the attribute name/values in no particular order
        s1 = s2 = ''
        enumbases = [base.__name__ for base in cls.__bases__
                     if isinstance(base, EnumMetaclass) and base is not Enum]
        if enumbases:
            s1 = '(%s)' % COMMASPACE.join(enumbases)
        enumvalues = ['%s: %d' % (val, getattr(cls, val))
                      for val in cls._members]
        if enumvalues:
            s2 = ': {%s}' % COMMASPACE.join(enumvalues)
        return '%s%s%s' % (cls.__name__, s1, s2)

    def __iter__(cls):
        return iter(cls._sorted)

    def __getitem__(cls, i):
        return cls._sorted[i]



class EnumInstance(int):
    """Class to represent an enumeration value.

    EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
    like the integer 12 when compared, but doesn't support arithmetic.
    """
    # Python allows you to subclass from built in types, but it requires both
    # an __new__() and an __init__() which take the same list of arguments.
    # Some -- but different -- arguments are ignored by both methods.  That's
    # just the way it is.
    def __new__(cls, classname, value, enumname):
        return int.__new__(cls, value)

    def __init__(self, classname, value, enumname):
        self._classname = classname
        self._enumname = enumname

    def __repr__(self):
        return 'EnumInstance(%s, %s, %d)' % (
            self._classname, self._enumname, self)

    def __str__(self):
        return self._enumname

    # For protocol 2 pickling
    def __getnewargs__(self):
        return self._classname, int(self), self._enumname



class Enum:
    __metaclass__ = EnumMetaclass

--- NEW FILE: features.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interfaces specifying composable features.
"""

from protocols import Interface, Attribute
from mailman.interfaces.enum import Enum



class WidgetTypes(Enum):
    """Enumeration of widget types.

    Radio - a simple radio button array
    String - a one-line text input field
    Text - a formless multi-line text input area
    Email - a text input field accepting an email address
    EmailList - a text input area accepting one email address and real name
                per line.
    EmailListPattern - a text input area accepting one email address or
                       caret-prefixed regular expression per line
    Number - a number, which may be an integer or a float
    FileUpload - a file upload composite widget
    Select - a select list composite widget
    Topic - a topic entry composite widget
    Checkbox - a checkbox array
    """
    Radio = 1
    String = 2
    Text = 3
    Email = 4
    EmailList = 5
    EmailListPattern = 6
    Number = 7
    FileUpload = 8
    Select = 9
    Topic = 10
    Checkbox = 11
    



class IFeature(Interface):
    """Interface specifying a feature description and process.
    """

    category = Attribute('category', """
    The name of the category, as a key.  Not translated.
    """)

    description = Attribute('description', """
    Human readable description of the category.
    """)

    subcategories = Attribute('subcategories', """
    List of subcategories, as keys.
    """)

    def getSubcategory(sub):
        """Return the subcategory as an IFeature."""

    options = Attribute('options', """
    List of options as keys.
    """)

    def getOption(option):
        """Return the option as an IOption."""



class IOption(Interface):
    """Representation of an option."""

    name = Attribute('name', """
    The option name.
    """)

    type = Attribute('type', """
    The widget type as a WidgetType enum.
    """)

    description = Attribute('description', """
    The option description as web presentable text.
    """)

    detail = Attribute('detail', """
    Option details as web presentable text.  May be None if the detail is no
    different from the description.
    """)

--- NEW FILE: lists.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interface for mailing lists.
"""

from protocols import Interface, Attribute
from mailman.interfaces.members import DeliveryStatus, DeliveryMode



class IListMembership(Interface):
    """Interface for mailing lists memberships."""

    id = Attribute('id', """
    Unique id identifying this mailing list.  The id will never change and
    will never be reused.
    """)

    rosters = Attribute('rosters', """
    Sequence of IRosters containing the entire list's membership.
    """)

    def getMembers(status=DeliveryStatus.Enabled,
                   mode=DeliveryMode.Regular,
                   filter=None):
        """Return an IRoster containing all the list members matching the
        specified criteria:

        status - If not None, specifies the delivery status for the users in
                 the IRoster.

        mode - If not None, specifies the delivery mode for the users in the
               IRoster.

        filter - If not None, this is a callable that is used to calculate
                 which members get returned /after/ the status and mode
                 filters are applied.  This can be used to retrieve, e.g. all
                 the members whose email address starts with `b' or all
                 members who match a regular expression.  Efficiency of using
                 the filter argument is dependent on the back-end
                 implementation.
        """

    def getBouncingMembers():
        """Return an IRoster containing all the list members with non-empty
        bounce information.  This is not the same as calling getMembers() with
        a status of ByBounce, since the latter will not include addresses
        which have begun bouncing but have not yet reached the threshold.
        """

    def isMember(address):
        """Return whether the address is a member of the mailing list or not.
        Returns the sequence of IRosters which contains the member, or None if
        the address is not a member of the list.
        """

    def getMemberTOC():
        """Return a summary of the subscribed membership as a sequence of
        (letter, count) pairs.  letter is the first letter of the email
        address.  count is the number of addresses in the list membership that
        start with this letter.
        """



class IListIdentity(Interface):
    """Interface for list identity.
    """

    name = Attribute('name', """
    The name of the mailing list.  This must be qualified with the web or
    email domain that the list lives in to be unique.
    """)

    domain = Attribute('domain', """
    The domain that the list lives in, as an IDomain.
    """)

    category = Attribute('category', """
    The category for this mailing list, or None.
    """)


# XXX how to handle cascading defaults?
# site -> vdomain -> category -> list

--- NEW FILE: members.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interface for members, who are defined as having a login and a password.
"""

from protocols import Interface, Attribute



class IMember(Interface):
    """The interface describing 'members' for authentication purposes."""

    memberid = Attribute('memberid', """
    An identifier that is unique for this member.  Read-only.
    """)

    login = Attribute('login', """
    The login text that uniquely identifies this member.
    """)

    password = Attribute('password', """
    A string that authenticates the member.
    """)

    def authenticate(response):
        """Returns True if the response matches the member's password.

        The implementation is free to hash or otherwise store the password in
        non-clear text, thus it cannot be compared directly against the
        password string.
        """



class IMemberFactory(Interface):
    """The public interface to the member authentication storage.

    If the implementation is an integration with an external system, it is
    free to disallow writes to the IMember objects it vends, or to create new
    IMember objects.  In that case it should raise MemberIsReadOnlyError.
    """

    def getMemberById(memberid):
        """Return the member referenced by memberid.

        Returns None if there is no memberid in the system.
        """

    def getMemberByLogin(login):
        """Return the member referenced by the given login.

        Returns None if there is no memberid in the system.
        """

    def createNewMember(login, password):
        """Create a new member record given the login and password.

        A unique member id will automatically be assigned, and an IMember will
        be returned.  Raises AlreadyAMemberError if the login is already known
        to the system.
        """



class IMemberStorage(Interface):
    """The interface between IMembers and their persistent storage.

    This is a back-channel interface that generally isn't used by user code.
    It specifies how IMember implementations should get specific data from the
    back-end storage.
    """

    def getLogin(self, memberid):
        """Return the login string for the given member id.

        If the member id is not known, None is returned.
        """

    def setLogin(self, memberid, login):
        """Sets the login for the given member.

        Raises NotAMemberError if memberid is not known.  Raises
        AlreadyAMemberError if the login is already associated with a member.
        """

    def getPassword(self, memberid):
        """Return the password, possibly hashed, for the given member id.

        If the member id is not known, None is returned.
        """

    def setPassword(self, memberid, cleartextpw):
        """Sets the password for the member.

        cleartextpw is the clear text password for the member, however the
        implementation is free to encrypt or hash the password.

        Raises NotAMemberError if memberid is not known.
        """

    def authenticate(self, memberid, response):
        """Return True if the response matches the stored member's password.

        Return False if the response does not match.  Return None if the
        member id is not known.
        """

    def deleteMemberId(self, memberid):
        """Deletes the member information associated with member id.

        However, the system ensures that the member id can never be re-used.
        Raises NotAMemberError if memberid is not known.
        """

--- NEW FILE: profiles.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interfaces for profiles."""

from protocols import Interface, Attribute



class IProfile(Interface):
    """Basic profile information for a person the system knows about.

    An IProfile contains information related to a specific person the system
    knows about.  It contains default information that serves as a template
    for when this member subscribes to a new list.  It also contains bounce
    information aggregated from all lists they are members of.  IProfiles have
    an opaque key that uniquely identifies this profile in the system.
    """

    userid = Attribute('userid', """
    Unique primary key for this profile.  Read-only.
    """)

    address = Attribute('address', """
    The primary address to use when delivering messages to this recipient.
    This address must be case-preserved in the localpart, and it must conform
    to the standards for email addresses as defined in RFC 2822.  It must also
    have already been confirmed as being valid for the recipient (e.g. via
    mailback if necessary).

    See also 'aliases'.
    """)

    realname = Attribute('realname', """
    The real name of the recipient, if known, otherwise the empty string.
    """)

    aliases = Attribute('aliases', """
    List of email addresses which serve as aliases for this recipient, for
    making posting permission decisions.  The same constraints as for
    'address' apply to these addresses.  Users may opt to have different
    mailing lists deliver messages to one of the associated aliases.
    """)

    password = Attribute('password', """
    A hashed password for the recipient, allowing them to edit their
    preferences.  Note that we do not store the user's password clear text.
    If you set this, it should be to the hashed password value.
    """)

    defaults = Attribute('defaults', """
    An IPreferences holding the settings preferred by the user for any new
    lists that they subsequently subscribe to.  Changing these does not change
    the values for any existing subscription.  Read-only (although the
    returned object is writeable).
    """)

    status = Attribute('status', """
    An IDeliveryStatus holding the global delivery status for a recipient.
    This may be overridden by specific delivery status information for a
    mailing list.
    """)

    bounceInfo = Attribute('bounceInfo', """
    An IBounceInfo holding bounce information for the recipient.
    """)

    listsOn = Attribute('listsOn', """
    A sequence of list ids for the lists this person is a member of.
    """)

    roles = Attribute('roles', """
    A sequences of IRoles allowing for additional permissions.
    """)



class IProfileStorage(Interface):
    """An interface for find and creating new IProfile records.
    """

    def useridForAddress(address):
        """Return the user id for the given address, if registered.

        Otherwise, return None.
        """

    def getProfile(userid):
        """Return the profile for the given user id.

        Returns None if the user id is not registered.
        """

    def createProfile(address):
        """Create and return a profile for the address.

        Raises ProfileExistsError if the address is already associated with an
        existing profile.
        """

    def getAddress(userid):
        """Return the primary address for the given user id."""

    def setAddress(userid, address):
        """Set the primary address for the given user id."""

    def getRealname(userid):
        """Get the real name for the given user id."""

    def setRealname(userid, name):
        """Set the real name for the given user id."""

    def getPasswordHash(userid):
        """Get the hashed password for the given user id."""

    def setPasswordHash(userid, password):
        """Set the password hash for the given user id."""

--- NEW FILE: qrunner.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""The qrunner interface as expected by the bin/qrunner script."""

from protocols import Interface



class IQRunner(Interface):
    def __init__(slice=None, numslices=1):
        """Create a qrunner.

        slice indicates which part of the hash space this qrunner instance
        will pay attention to.  numslices is the total number of hash space
        slices.
        """

    def stop():
        """Stop the qrunner at the next opportunity."""

    def run():
        """Start the qrunner."""

    def _cleanup(self):
        """Clean up upon exit from the main processing loop.

        Called when the Runner's main loop is stopped, this should perform
        any necessary resource deallocation.  Its return value is irrelevant.
        """
        utils.reap(self._kids)

    def _dispose(self, mlist, msg, msgdata):
        """Dispose of a single message destined for a mailing list.

        Called for each message that the Runner is responsible for, this is
        the primary overridable method for processing each message.
        Subclasses, must provide implementation for this method.

        mlist is the MailList instance this message is destined for.

        msg is the Message object representing the message.

        msgdata is a dictionary of message metadata.
        """
        raise NotImplementedError

    def _doperiodic(self):
        """Do some processing `every once in a while'.

        Called every once in a while both from the Runner's main loop, and
        from the Runner's hash slice processing loop.  You can do whatever
        special periodic processing you want here, and the return value is
        irrelevant.
        """
        pass

    def _snooze(self, filecnt):
        """Sleep for a little while.

        filecnt is the number of messages in the queue the last time through.
        Sub-runners can decide to continue to do work, or sleep for a while
        based on this value.  By default, we only snooze if there was nothing
        to do last time around.
        """
        if filecnt or self.SLEEPTIME <= 0:
            return
        time.sleep(self.SLEEPTIME)

    def _shortcircuit(self):
        """Return a true value if the individual file processing loop should
        exit before it's finished processing each message in the current slice
        of hash space.  A false value tells _oneloop() to continue processing
        until the current snapshot of hash space is exhausted.

        You could, for example, implement a throttling algorithm here.
        """
        return self._stop

--- NEW FILE: roles.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interfaces for roles and permissions.
"""

from protocols import Interface, Attribute


class IRole(Interface):
    """An interface for describing additional roles a user might have.
    """


class IListModerator(IRole):
    """Interface for list moderators.
    """

    id = Attribute('id', """
    The id of the list associated with this role.
    """)


class IListOwner(IListModerator):
    """Interface for list owners.

    List owners are also list moderators.
    """


class IListRemover(IRole):
    """Interface for those able to remove lists.
    """


class IDomainOwner(IRole):
    """Interface for virtual domain owners.
    """

    domain = Attribute('domain', """
    The name of the virtual domain this role owns.
    """)


class IListCreator(IRole):
    """Interface for those able to create lists.
    """


class ISiteOwner(IRole):
    """Interface for site owners.
    """

--- NEW FILE: sites.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interface describing whole sites and virtual domains.
"""

from protocols import Interface, Attribute


class IDomain(Interface):
    """Information uniquely describing a virtual domain.
    """

    emailhost = Attribute('emailhost', """
    The hostname part of an email address for posting to this list.
    """)

    urlhost = Attribute('urlhost', """
    The hostname part of the url to reach this mailing list.
    """)

    def address(localpart):
        """Return a fully qualified email address, which is the base address
        for the list, plus any extra local part.
        """

    def url(path):
        """Return the normalized url path with the proper protocol and port
        numbers inserted.
        """



class IDomainRegistry(Interface):
    """Register all virtual domains at a site."""

    def register(domain):
        """Register domain, an IDomain."""

    def getDomainForEmailhost(emailhost):
        """Get the IDomain for the given emailhost.

        Return False if the lookup failed.
        """

    def getDomainForURLhost(urlhost):
        """Get the IDomain for the given urlhost.

        Return False if the lookup failed.
        """

--- NEW FILE: storages.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interfaces for the three primary storages.

Mailman has three logical storages, one for users, one for lists, and one for
messages.  The database manager is used to get access to one of these three
storages (which of course, may actually be implemented by the same object).
"""

from protocols import Interface, Attribute



class IStorage(Interface):
    """Generic storage interface."""

    def open():
        """Open the storage."""

    def close():
        """Close the storage."""



class IListStorage(IStorage):
    """The interface to the underlying list data storage."""

    def set(listid, var, data):
        """Set the value of the variable for the listid to data.

        listid is the fully qualified list identifier.  It contains both the
        list name and the domain, separated by the '@' character.

        var is the name of the list configuration variable.

        data is the variable's value.  It can be any Python object.
        """

    def get(listid, var):
        """Return the stored value of the variable for listid.

        listid is the fully qualified list identifier.  It contains both the
        list name and the domain, separated by the '@' character.

        var is the name of the list configuration variable.
        """

    def list_exists(listid):
        """If the list exists, return True, otherwise False."""

    def create_list(listid):
        """Create the list.

        Return the timestamp (as a datetime object) for when the list was
        created.  If the list already exists, raise ListExistsError.
        """

    def delete_list(listid):
        """Deletes all record of the list from the database.

        Raises NoListError if the list does not exist.
        """

    listids = Attribute(
        """A generator returning all the list ids.""")

    domains = Attribute(
        """A generator returning all the unique domains.""")



class IUserStorage(IStorage):
    """The interface to the underlying user data storage."""

    def get_user(uid, domain):
        """Return the IUser associated with the given uid in the given domain.

        uid is guaranteed unique across all domains, however domain (which is
        a Mailman virtual domain name) is used as a backend selector if
        necessary.

        Raises NoUserError if no user can be found.
        """

    def create_user(domain):
        """Create a new user, returning the new IUser.

        Domain (which is a Mailman virtual domain name) is used as a backend
        selector if necessary.

        A unique user id will automatically be assigned.
        """



class IMessageStorage(IStorage):
    """The interface to the underlying message storage."""

    def get_message(msgid):
        """Return the IMessage object associated with the message id.

        Note that the message id is an internal object id, not the value of
        the RFC 2822 Message-Id header.
        """

    def get_messages_for_id(message_id):
        """Return the IMessage objects associated with message_id.

        Here, message_id is the value of an RFC 2822 Message-Id.  Because
        these are not guaranteed unique, this method returns an iterator which
        can be used to retrieve all the IMessage objects that contain the
        given Message-Id.
        """

    def put(message):
        """Put the message into the message storage.

        message is an email.Message.Message object.  This method returns the
        new IMessage object for the message.
        """

--- NEW FILE: transactions.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Transactions."""

from protocols import Interface


class ITransactionManager(Interface):
    """Manages transactions on databases."""

    def begin():
        """Start a transaction, returning an ITransaction object."""


class ITransaction(Interface):
    """Defines transactions on databases."""

    def abort():
        """Abort this current transaction."""

    def commit():
        """Commit this current transaction."""

--- NEW FILE: units.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.


def seconds(s):
    return s

def minutes(m):
    return m * 60

def hours(h):
    return 60 * minutes(s)

def days(d):
    return 24 * hours(d)

def kbytes(b):
    return 1024 * b

def mbytes(b):
    return 1024 * kbytes(b)

def gbytes(b):
    return 1024 * gbytes(b)

--- NEW FILE: user.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""User related interfaces."""

from protocols import Interface, Attribute



class IUser(Interface):
    """The IUser interface supports just the basic identity interface.

    IUsers have a user id and a password (possibly hashed).  They also support
    authenticating a challenge, and retrieving profiles, addresses,
    subscriptions, and other user-related data.
    """

    uid = Attribute('The read-only unique user id.')

    password = Attribute("""The user's password.

    When setting the password, the back-end storage is allowed to hash the
    given string.  In that case, getting the password later will only return
    the hashed password string.  IOW, there may not be any way to retrieve the
    clear text password.""")

    def authenticate(challenge):
        """Return True if the challenge authenticates the user.

        Otherwise, return False.
        """

    def get_address(label):
        """Get the IAddress object associated with the given label, or None.
        """

    def add_address(label, address):
        """Create an IAddress object for the user, given the label.

        Raises UserAddressError if the IAddress for this label already
        exists.  Returns the newly created IAddress.
        """

    def delete_address(label):
        """Delete the IAddress associated with this label for this user.

        Raises UserAddressError if there is no IAddress for this label.
        """

    addresses = Attribute(
        """A sequence of the IAddress objects for this user.""")



class IAddress(Interface):
    """The interface to an address registered to a user."""

    user = Attribute("""The IUser object associated with this address.
    (read-only).
    """)

    label = Attribute("""The user-provided label for this email association.
    (read-only).
    """)

    address = Attribute("""The email address for this association.
    No confirmation of the address is performed on setting.
    """)

    realname = Attribute('The realname associated with this address.')

--- NEW FILE: users.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# 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., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.

"""Interface for users.
"""

from protocols import Interface, Attribute
from mailman.interfaces.enum import Enum



class DeliveryStatus(Enum):
    """Delivery status flags:

    Enabled   - The deliveries to the user are enabled
    ByUser    - The user explicitly disabled deliveries
    ByAdmin   - The list administrator explicitly disabled deliveries
    ByBounce  - The system disabled deliveries due to bouncing
    Vacation  - The user is on vacation
    NonMember - We know about the address (e.g. for posting purposes) but the
                address is not a member of the list and so shouldn't get a
                copy of messages.
    """
    Enabled = 0
    ByUser = 1
    ByAdmin = 2
    ByBounce = 3
    Vacation = 4
    NoDelivery = 5


class DeliveryMode(Enum):
    """Delivery mode flags:

    Regular     - Immediate delivery of any posted message
    MIMEDigest  - multipart/digest periodic deliveries
    PlainDigest - RFC 1153 (plain text) digests
    URLDigest   - A digest containing summary information and archive urls
    """
    Regular = 0
    MIMEDigest = 1
    PlainDigest = 2
    URLDigest = 3


class Options(Enum):
    """Subscription options:

    DontReceiveOwnPosts
        - Members will not receive copies through the list of their own
          postings to the list.

    AcknowledgePosts
        - Members will receive an acknowledgement of receipt by the mailing
          list of their post.

    ConcealSubscription
        - A member's address is not shown on publically available rosters.

    ReceiveNonmatchingTopics
        - When a message is posted to a list with topics defined, but the
          message does not match any of the topics, should the member get the
          message or not?

    DontReceiveDuplicates
        - When a member's email address is explicitly present in a To or Cc
          header, this flag controls whether or not they get a copy through
          the list.

    DeliveryAfterVacation
        - When set, messages posted to the list during a user's vacation are
          collected, and sent in a digest (in a format based on the digest
          settings) upon return.
    """
    DontReceiveOwnPosts = 1
    AcknowledgePosts = 2
    ConcealSubscription = 3
    ReceiveNonmatchingTopics = 4
    DontReceiveDuplicates = 5
    DeliveryAfterVacation = 6



class IListMember(Interface):
    """The interface describing the association between a member and a
    mailing list they are members of.
    """

    mailingList = Attribute('mailingList', """
    The mailing list that is associated with this object.
    """)

    options = Attribute('options', """
    A mapping between list ids and IPreferences for holding the subscription
    preferences for individual lists.  Always returns a value, although it may
    be the defaults value if the specific list has no differences.
    """)

    status = Attribute('status', """
    An IDeliveryStatus holding the list-specific delivery status for a member.
    If not None, this overrides any global delivery status.
    """)

    topics = Attribute('topics', """
    The topics that this list member is subscribed to for this mailing list.
    """)



class IExternalMemberData(Interface):
    """An interface describing extra information associated with a member.
    This is essentially a limited mapping interface.
    """
    def get(key):
        """Return the data associated with key, or None.  The returned value
        must be a Unicode string (or an 8-bit string containing only ASCII).
        """



class IDeliveryStatus(Interface):
    """Basic interface for delivery and bounce information."""

    status = Attribute('status', """
    A flag indicating the recipient's delivery status.  Must be one of the
    DeliveryStatus enumerations.

    Whenever the status is changed, the statusChangeTime is updated.  If
    status is changed to Enabled, the bounceInfo and vacationReturn values are
    cleared.
    """)

    statusChangeTime = Attribute('statusChangeTime', """
    The date and time that the last delivery status change was made.  This
    value is automatically updated whenever the status is changed.
    Read-only.
    """)

    vacationReturn = Attribute('vacationReturn', """
    The date and time that a recipient on vacation will return.  Setting this
    value to anything other than None sets the status to Vacation.  Setting
    status to Enabled resets this value.
    """)


class IBounceInfo(Interface):
    """Bounce information."""

    score = Attribute('score', """
    The current bounce score, as a floating point number.
    """)

    lastBounceTime = Attribute('lastBounceTime', """
    The date and time of the last registered bounce.  Read-only.
    """)

    noticesLeft = Attribute('noticesLeft', """
    The number of `you are bounce disabled' notices left to send before an
    automatic removal is performed.  Setting this automatically updates the
    lastNoticeDate.
    """)

    lastNoticeDate = Attribute('lastNoticeDate', """
    The date and time that the last `you are bounce disabled' notice was
    sent.  Automatically updated when noticesLeft is changed.
    """)

    reenableCookie = Attribute('reenableCookie', """
    The cookie that is required in order to re-enable the recipient's delivery
    mode.  Read-only.
    """)



class IPreferences(Interface):
    """Preferences for any subsequent subscriptions."""

    language = Attribute('language', """
    The preferred language.  It may be None to indicate that the browser's
    default is preferred.
    """)

    mode = Attribute('mode', """
    The preferred delivery mode for messages.  Must be one of the
    following enum constants (see DeliveryMode above):

        Regular     - Immediate delivery of any posted message
        MIMEDigest  - multipart/digest periodic deliveries
        PlainDigest - RFC 1153 (plain text) digests
        URLDigest   - A digest containing summary information and archive urls
    """)

    options = Attribute('options', """
    The list of default options for new subscriptions.  Must be one of the
    following enum constants (see Options above):

    DontReceiveOwnPosts - Members will not receive copies through the
                          list of their own postings to the list.
    AcknowledgePosts - Members will receive an acknowledgement of
                       receipt by the mailing list of their post.
    ConcealSubscription - A member's address is not shown on publically
                          available rosters.
    ReceiveNonmatchingTopics - When a message is posted to a list with topics
                               defined, but the message does not match any of
                               the topics, should the member get the message
                               or not?
    DontReceiveDuplicates - When a member's email address is explicitly
                            present in a To or Cc header, this flag controls
                            whether or not they get a copy through the list.
    """)



class IRoster(Interface):
    """A collection of IMembers."""

    members = Attribute('members', """
    A sequence of IMembers.
    """)


_______________________________________________
Mailman-checkins mailing list
[EMAIL PROTECTED]
Unsubscribe: http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org

Reply via email to