Merge authors:
Florian Fuchs (flo-fuchs)
Related merge proposals:
https://code.launchpad.net/~flo-fuchs/mailman.client/settings/+merge/56088
proposed by: Florian Fuchs (flo-fuchs)
review: Needs Information - Florian Fuchs (flo-fuchs)
review: Approve - Barry Warsaw (barry)
------------------------------------------------------------
revno: 14 [merge]
committer: Florian Fuchs <[email protected]>
branch nick: mailman.client
timestamp: Mon 2011-06-20 09:08:14 +0200
message:
Merge settings branch, adding:
- a _Settings class to manipulate mailing list settings
- methods to delete mailing lists
- Some MM3a7 compatibility changes
modified:
mailman/client/_client.py
mailman/client/docs/using.txt
--
lp:mailman.client
https://code.launchpad.net/~mailman-coders/mailman.client/trunk
Your team Mailman Coders is subscribed to branch lp:mailman.client.
To unsubscribe from this branch go to
https://code.launchpad.net/~mailman-coders/mailman.client/trunk/+edit-subscription
=== modified file 'mailman/client/_client.py'
--- mailman/client/_client.py 2010-12-26 21:11:54 +0000
+++ mailman/client/_client.py 2011-05-30 07:14:15 +0000
@@ -189,6 +189,10 @@
'lists/{0}'.format(fqdn_listname))
return _List(self._connection, content['self_link'])
+ def delete_list(self, fqdn_listname):
+ response, content = self._connection.call(
+ 'lists/{0}'.format(fqdn_listname), None, 'DELETE')
+
class _Domain:
@@ -282,15 +286,26 @@
for entry in sorted(content['entries'],
key=itemgetter('address'))]
+ @property
+ def settings(self):
+ return _Settings(self._connection,
+ 'lists/{0}/config'.format(self.fqdn_listname))
+
def get_member(self, address):
"""Get a membership.
:param address: The email address of the member for this list.
:return: A member proxy object.
"""
- response, content = self._connection.call(
- 'lists/{0}/member/{1}'.format(self.fqdn_listname, address))
- return _Member(self._connection, content['self_link'])
+ # In order to get the member object we need to
+ # iterate over the existing member list
+ for member in self.members:
+ if member.address == address:
+ return member
+ break
+ else:
+ raise ValueError('%s is not a member address of %s' %
+ (address, self.fqdn_listname))
def subscribe(self, address, real_name=None):
"""Subscribe an email address to a mailing list.
@@ -303,7 +318,7 @@
"""
data = dict(
fqdn_listname=self.fqdn_listname,
- address=address,
+ subscriber=address,
real_name=real_name,
)
response, content = self._connection.call('members', data)
@@ -314,9 +329,21 @@
:param address: The address to unsubscribe.
"""
- self._connection.call(
- 'lists/{0}/member/{1}'.format(self.fqdn_listname, address),
- method='DELETE')
+ # In order to get the member object we need to
+ # iterate over the existing member list
+
+ for member in self.members:
+ if member.address == address:
+ self._connection.call(member.self_link, method='DELETE')
+ break
+ else:
+ raise ValueError('%s is not a member address of %s' %
+ (address, self.fqdn_listname))
+
+
+ def delete(self):
+ response, content = self._connection.call(
+ 'lists/{0}'.format(self.fqdn_listname), None, 'DELETE')
@@ -345,11 +372,71 @@
self._get_info()
return self._info['address']
+ @property
+ def self_link(self):
+ self._get_info()
+ return self._info['self_link']
+
+ @property
+ def role(self):
+ self._get_info()
+ return self._info['role']
+
+ @property
+ def user(self):
+ self._get_info()
+ return self._info['user']
+
def unsubscribe(self):
"""Unsubscribe the member from a mailing list.
- :param address: The address to unsubscribe.
+ :param self_link: The REST resource to delete
"""
- self._connection.call(
- 'lists/{0}/member/{1}'.format(self.fqdn_listname, self.address),
- method='DELETE')
+ self._connection.call(self.self_link, method='DELETE')
+
+
+READ_ONLY_ATTRS = ('bounces_address', 'created_at', 'digest_last_sent_at',
+ 'fqdn_listname', 'http_etag', 'host_name', 'join_address',
+ 'last_post_at', 'leave_address', 'list_id', 'list_name',
+ 'next_digest_number', 'no_reply_address', 'owner_address',
+ 'post_id', 'posting_address', 'request_address', 'scheme',
+ 'volume', 'web_host',)
+
+
+class _Settings():
+ def __init__(self, connection, url):
+ self._connection = connection
+ self._url = url
+ self._info = None
+ self._get_info()
+
+ def __repr__(self):
+ return repr(self._info)
+
+ def _get_info(self):
+ if self._info is None:
+ response, content = self._connection.call(self._url)
+ self._info = content
+
+ def __iter__(self):
+ for key in self._info.keys():
+ yield key
+
+ def __getitem__(self, key):
+ return self._info[key]
+
+ def __setitem__(self, key, value):
+ self._info[key] = value
+
+ def __len__(self):
+ return len(self._info)
+
+ def save(self):
+ data = {}
+ for attribute, value in self._info.items():
+ if attribute not in READ_ONLY_ATTRS:
+ data[attribute] = value
+ response, content = self._connection.call(self._url, data, 'PATCH')
+
+
+
=== modified file 'mailman/client/docs/using.txt'
--- mailman/client/docs/using.txt 2010-12-26 21:11:54 +0000
+++ mailman/client/docs/using.txt 2011-06-20 06:55:25 +0000
@@ -119,6 +119,20 @@
<List "[email protected]">
<List "[email protected]">
+You can use a list instance to delete the list.
+
+ >>> test_three = client.get_list('[email protected]')
+ >>> test_three.delete()
+
+You can also delete a list using the client instance's delete_list method.
+
+ >>> client.delete_list('[email protected]')
+
+ >>> for mlist in client.lists:
+ ... print mlist
+ <List "[email protected]">
+ <List "[email protected]">
+
Membership
==========
@@ -170,6 +184,19 @@
>>> cris = test_two.get_member('[email protected]')
>>> cris
<Member "[email protected]" on "[email protected]">
+ >>> print cris.role
+ member
+ >>> print cris.self_link
+ http://localhost:8001/3.0/members/4
+ >>> print cris.user
+ http://localhost:8001/3.0/users/3
+
+If you use an address which is not a member of test_two `ValueError` is raised:
+
+ >>> test_two.unsubscribe('[email protected]')
+ Traceback (most recent call last):
+ ...
+ ValueError: [email protected] is not a member address of [email protected]
After a while, Anna decides to unsubscribe from the Test One mailing list,
though she keeps her Test Two membership active.
@@ -188,3 +215,48 @@
... print member
<Member "[email protected]" on "[email protected]">
<Member "[email protected]" on "[email protected]">
+
+If you try to unsubscribe an address which is not a member address `ValueError` is raised:
+
+ >>> test_one.unsubscribe('[email protected]')
+ Traceback (most recent call last):
+ ...
+ ValueError: [email protected] is not a member address of [email protected]
+
+
+List Settings
+=============
+
+We can get all list settings via a lists settings attribute. A proxy object for the settings is returned which behaves much like a dictionary.
+
+ >>> settings = test_one.settings
+ >>> len(settings)
+ 48
+
+ >>> for attr in sorted(settings):
+ ... print attr + ': ' + str(settings[attr])
+ acceptable_aliases: []
+ ...
+ welcome_msg:
+
+ >>> print settings['real_name']
+ Test-one
+
+We can access all valid list settings as attributes.
+
+ >>> print settings['fqdn_listname']
+ [email protected]
+ >>> print settings['description']
+
+ >>> settings['description'] = 'A very meaningful description.'
+ >>> settings['real_name'] = 'Test Numero Uno'
+
+ >>> settings.save()
+
+ >>> settings_new = test_one.settings
+ >>> print settings_new['description']
+ A very meaningful description.
+ >>> print settings_new['real_name']
+ Test Numero Uno
+
+
_______________________________________________
Mailman-coders mailing list
[email protected]
http://mail.python.org/mailman/listinfo/mailman-coders