florianfuchs has proposed merging lp:~flo-fuchs/mailman/restclient into
lp:mailman.
Requested reviews:
Mailman Coders (mailman-coders)
I added a rest client in src/mailmanclient as well as a doctest in
src/mailman/rest/docs/restclient.txt.
--
https://code.launchpad.net/~flo-fuchs/mailman/restclient/+merge/28522
Your team Mailman Coders is requested to review the proposed merge of
lp:~flo-fuchs/mailman/restclient into lp:mailman.
=== added file 'src/mailman/rest/docs/restclient.txt'
--- src/mailman/rest/docs/restclient.txt 1970-01-01 00:00:00 +0000
+++ src/mailman/rest/docs/restclient.txt 2010-06-25 16:50:42 +0000
@@ -0,0 +1,89 @@
+===================
+Mailman REST Client
+===================
+
+Domains
+=======
+
+ # The test framework starts out with an example domain, so let's delete
+ # that first.
+ >>> from mailman.interfaces.domain import IDomainManager
+ >>> from zope.component import getUtility
+ >>> domain_manager = getUtility(IDomainManager)
+
+ >>> domain_manager.remove('example.com')
+ <Domain example.com...>
+ >>> transaction.commit()
+
+In order to add new lists first a new domain has to be added.
+
+ >>> from mailmanclient.rest import MailmanRESTClient, MailmanRESTClientError
+ >>> c = MailmanRESTClient('localhost:8001')
+ >>> c.create_domain('example.com')
+ True
+
+
+Mailing lists
+=============
+
+You can get a lists of all lists by calling get_lists(). If no lists have been created yet, MailmanRESTClientError is raised.
+
+ >>> lists = c.get_lists()
+ Traceback (most recent call last):
+ ...
+ MailmanRESTClientError: No mailing lists found
+
+Lists can be created by calling create_list('[email protected]').
+
+ >>> c.create_list('[email protected]')
+ True
+ >>> c.create_list('[email protected]')
+ True
+
+If there are any mailing lists a list of dicts is returned.
+
+ >>> lists = c.get_lists()
+ >>> lists
+ [{u'real_name': u'Test-one', u'self_link': u'http://localhost:8001/3.0/lists/[email protected]', u'http_etag': u'"5e99519ef1b823a52254b77e89bec54fbd17bef0"', u'host_name': u'example.com', u'fqdn_listname': u'[email protected]', u'list_name': u'test-one'}, {u'real_name': u'Test-two', u'self_link': u'http://localhost:8001/3.0/lists/[email protected]', u'http_etag': u'"a05542c9faa07cbe2b8fdf8a1655a2361ab365f2"', u'host_name': u'example.com', u'fqdn_listname': u'[email protected]', u'list_name': u'test-two'}]
+
+Information about a specific list can be read (returns a single dict).
+
+ >>> list = c.read_list('[email protected]')
+ >>> list
+ {u'real_name': u'Test-one', u'self_link': u'http://localhost:8001/3.0/lists/[email protected]', u'http_etag': u'"5e99519ef1b823a52254b77e89bec54fbd17bef0"', u'host_name': u'example.com', u'fqdn_listname': u'[email protected]', u'list_name': u'test-one'}
+
+
+Membership
+==========
+
+Users can subscribe to a mailing list using the list's name, their email address, as well as their name.
+
+ >>> c.subscribe_list('[email protected]', '[email protected]', 'Garp')
+ True
+ >>> c.subscribe_list('[email protected]', '[email protected]', 'Jenny')
+ True
+ >>> c.subscribe_list('[email protected]', '[email protected]', 'Jenny')
+ True
+
+Members of all mailings list can be listed (returns a list of dicts).
+
+ >>> all_members = c.get_members()
+ >>> all_members
+ [{u'self_link': u'http://localhost:8001/3.0/lists/[email protected]/member/[email protected]', u'http_etag': u'"925a22dc585a1c713d79912bd951f4cbb358dae2"'}, {u'self_link': u'http://localhost:8001/3.0/lists/[email protected]/member/[email protected]', u'http_etag': u'"344ef9f37f59cce14a81b688dd1fa3d39112e6b5"'}, {u'self_link': u'http://localhost:8001/3.0/lists/[email protected]/member/[email protected]', u'http_etag': u'"a5c962186200af483f6508dfbabca7a4a78ef309"'}]
+
+As well as the members of a specific lists:
+
+ >>> list_members = c.get_members('[email protected]')
+ >>> list_members
+ [{u'self_link': u'http://localhost:8001/3.0/lists/[email protected]/member/[email protected]', u'http_etag': u'"925a22dc585a1c713d79912bd951f4cbb358dae2"'}, {u'self_link': u'http://localhost:8001/3.0/lists/[email protected]/member/[email protected]', u'http_etag': u'"344ef9f37f59cce14a81b688dd1fa3d39112e6b5"'}]
+
+Lists can be unsubscribed by using list name and the member's email address
+
+ >>> c.leave_list('[email protected]', '[email protected]')
+ True
+
+After leaving the list only the remaining members are shown:
+
+ >>> new_members = c.get_members('[email protected]')
+ >>> new_members
+ [{u'self_link': u'http://localhost:8001/3.0/lists/[email protected]/member/[email protected]', u'http_etag': u'"925a22dc585a1c713d79912bd951f4cbb358dae2"'}]
=== added directory 'src/mailmanclient'
=== added file 'src/mailmanclient/__init__.py'
=== added file 'src/mailmanclient/rest.py'
--- src/mailmanclient/rest.py 1970-01-01 00:00:00 +0000
+++ src/mailmanclient/rest.py 2010-06-25 16:50:42 +0000
@@ -0,0 +1,248 @@
+# Copyright (C) 2009-2010 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman 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 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman 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
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+import json
+from httplib import HTTPConnection, HTTPException
+from urllib import urlencode
+
+class MailmanRESTClientError(Exception):
+ """An exception thrown by the Mailman REST API client."""
+ pass
+
+class MailmanRESTClient(object):
+ """A thin client wrapper for the Mailman REST API."""
+
+ def __init__(self, host):
+ self.host = host
+ if self.host[-1] == '/':
+ self.host = self.host[:-1]
+
+ # general header information
+ self.headers = {
+ "User-Agent": "MailmanRESTClient",
+ "Accept": "text/plain",
+ }
+
+ try:
+ self.c = HTTPConnection(self.host)
+ except:
+ raise MailmanRESTClientError('Could not connect to server')
+
+ def __repr__(self):
+ return '<MailmanRESTClient: %s>' % self.host
+
+ def _get_url(self, path):
+ try:
+ self.c.request('GET', path, None, self.headers)
+ except:
+ raise MailmanRESTClientError('Error sending request')
+
+ try:
+ r = self.c.getresponse()
+ raw_data = r.read()
+ if len(raw_data) == 0:
+ raise None
+ data = json.loads(raw_data)
+ except:
+ raise MailmanRESTClientError('Error sending request')
+ finally:
+ self.c.close()
+
+ return data
+
+ def _post_url(self, path, data):
+ self.headers['Content-type'] = "application/x-www-form-urlencoded"
+
+ try:
+ self.c.request('POST', path, urlencode(data), self.headers)
+ except:
+ raise MailmanRESTClientError('Could not send request')
+
+ try:
+ r = self.c.getresponse()
+
+ if r.status == 201:
+ return True
+ else:
+ return r.status
+ finally:
+ self.c.close()
+
+ def _delete_url(self, path):
+ try:
+ self.c.request('DELETE', path, None, self.headers)
+ except:
+ raise MailmanRESTClientError('Could not send request')
+ finally:
+ self.c.close()
+
+ def _put_url(self, path):
+ """To be implemented...
+ """
+ pass
+
+ def get_lists(self):
+ """Get a list of mail lists.
+
+ returns a list of dicts
+ """
+ try:
+ r = self._get_url('/3.0/lists')
+ except:
+ raise MailmanRESTClientError('Could not send request')
+
+ if 'entries' not in r:
+ raise MailmanRESTClientError('No mailing lists found')
+
+ return r['entries']
+
+ def read_list(self, list_name):
+ """Get information about list.
+
+ :param list_name: name of the list to get information about
+ :type list_name: string
+ :rtype: dict
+ """
+ try:
+ r = self._get_url('/3.0/lists/' + list_name)
+ except:
+ raise MailmanRESTClientError('Unable to get info about list')
+
+ return r
+
+ def create_list(self, fqdn_listname, **kwargs):
+ """Create a new list.
+
+ :param fqdn_listname: the name of the list including the @ and the domain name. eg. [email protected]
+ :type fqdn_listname: string
+ :rtype: None
+ """
+ data = {
+ 'fqdn_listname': fqdn_listname
+ }
+ data.update(**kwargs)
+ try:
+ return self._post_url('/3.0/lists', data)
+ except MailmanRESTClientError, e:
+ raise MailmanRESTClientError(e)
+
+
+ def subscribe_list(self, fqdn_listname, address, real_name, **kwargs):
+ """Add an address to a list.
+
+ :param fqdn_listname: the name of the list .
+ :type fqdn_listname: string
+ :param address: email address to add to the list.
+ :type address: string
+ :param real_name: the "real" name for the address to be addded
+ :type real_name: string
+ """
+
+ data = {
+ 'fqdn_listname': fqdn_listname,
+ 'address': address,
+ 'real_name': real_name
+ }
+ data.update(**kwargs)
+ try:
+ r = self._post_url('/3.0/members', data)
+ except:
+ raise MailmanRESTClientError('unable to join list')
+
+ return r
+
+ def leave_list(self, fqdn_listname, address):
+ """Remove an address from a list.
+
+ :param fqdn_listname: the name of the list.
+ :type fqdn_listname: string
+ :param address: email address that is leaving the list
+ :type address: string
+ :rtype: None
+ """
+ try:
+ r = self._delete_url('/3.0/lists/' + fqdn_listname + '/member/' + address )
+ except:
+ raise MailmanRESTClientError('unable to leave list')
+
+ return True
+
+ def get_members(self, fqdn_listname = None):
+ """Get a list of all members for all lists.
+
+ :rtype: list of dicts
+ :type fqdn_listname: string
+ """
+
+ if fqdn_listname != None:
+ url = '/3.0/lists/' + fqdn_listname + '/roster/members'
+ else:
+ url = '/3.0/members'
+ try:
+ r = self._get_url(url)
+ except:
+ raise MailmanRESTClientError('Could not complete request')
+
+ if 'entries' not in r:
+ raise MailmanRESTClientError('Could not find any members')
+
+ return r['entries']
+
+ def get_domains(self):
+ """Get a list of domains.
+
+ :rtype: list of dicts
+ """
+ try:
+ r = self._get_url('/3.0/domains')
+ except:
+ raise MailmanRESTClientError('Could not complete request')
+ if 'entries' not in r:
+ raise MailmanRESTClientError('Could not find any domains')
+
+ return r['entries']
+
+ def read_domain(self, domain_name):
+ """Get information about a specific domain.
+
+ :param domain_name: the name of the domain.
+ :rtype: dict
+ """
+ try:
+ r = self._get_url('/3.0/domains/' + domain_name)
+ except:
+ raise MailmanRESTClientError('Unable to read domain')
+
+ return r
+
+ def create_domain(self, email_host, **kwargs):
+ """Create a new domain name.
+
+ :param email_host: domain name to create
+ :type email_host: string
+ """
+ data = {
+ 'email_host': email_host,
+ }
+ data.update(**kwargs)
+ try:
+ r = self._post_url('/3.0/domains', data)
+ except:
+ raise MailmanRESTClientError('Unable to create domain')
+
+ return r
+
_______________________________________________
Mailman-coders mailing list
[email protected]
http://mail.python.org/mailman/listinfo/mailman-coders