diff options
| author | Barry Warsaw | 2010-02-25 21:07:27 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2010-02-25 21:07:27 -0500 |
| commit | c231eb4a8c1bd593804a3a2f05f07966dcd73f18 (patch) | |
| tree | bcfbf3f0a66f1e55fffc3289aec7389ee9c79227 /src | |
| parent | 70dd8a96cc0e01b42737b46e30cf37b5c8fa0747 (diff) | |
| download | mailman-c231eb4a8c1bd593804a3a2f05f07966dcd73f18.tar.gz mailman-c231eb4a8c1bd593804a3a2f05f07966dcd73f18.tar.zst mailman-c231eb4a8c1bd593804a3a2f05f07966dcd73f18.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/rest/docs/domains.txt | 4 | ||||
| -rw-r--r-- | src/mailman/rest/docs/lists.txt | 2 | ||||
| -rw-r--r-- | src/mailman/rest/docs/membership.txt | 4 | ||||
| -rw-r--r-- | src/mailman/rest/domains.py | 33 | ||||
| -rw-r--r-- | src/mailman/rest/helpers.py | 50 | ||||
| -rw-r--r-- | src/mailman/rest/lists.py | 33 | ||||
| -rw-r--r-- | src/mailman/rest/members.py | 31 |
7 files changed, 87 insertions, 70 deletions
diff --git a/src/mailman/rest/docs/domains.txt b/src/mailman/rest/docs/domains.txt index 86c868530..b8e0170b0 100644 --- a/src/mailman/rest/docs/domains.txt +++ b/src/mailman/rest/docs/domains.txt @@ -16,8 +16,8 @@ The REST API can be queried for the set of known domains, of which there are initially none. >>> dump_json('http://localhost:8001/3.0/domains') - http_etag: "f62b4cab6d4bfa731d5ff091dde29d318a3234a8" - start: None + http_etag: "..." + start: 0 total_size: 0 Once a domain is added though, it is accessible through the API. diff --git a/src/mailman/rest/docs/lists.txt b/src/mailman/rest/docs/lists.txt index d04fed0b3..6abf29a1d 100644 --- a/src/mailman/rest/docs/lists.txt +++ b/src/mailman/rest/docs/lists.txt @@ -8,7 +8,7 @@ yet though. >>> dump_json('http://localhost:8001/3.0/lists') http_etag: "..." - start: None + start: 0 total_size: 0 Create a mailing list in a domain and it's accessible via the API. diff --git a/src/mailman/rest/docs/membership.txt b/src/mailman/rest/docs/membership.txt index e86f598f1..70d4384ce 100644 --- a/src/mailman/rest/docs/membership.txt +++ b/src/mailman/rest/docs/membership.txt @@ -10,7 +10,7 @@ There are no mailing lists and no members yet. >>> dump_json('http://localhost:8001/3.0/members') http_etag: "..." - start: None + start: 0 total_size: 0 We create a mailing list, which starts out with no members. @@ -20,7 +20,7 @@ We create a mailing list, which starts out with no members. >>> dump_json('http://localhost:8001/3.0/members') http_etag: "..." - start: None + start: 0 total_size: 0 diff --git a/src/mailman/rest/domains.py b/src/mailman/rest/domains.py index 32f010534..8b7cd2699 100644 --- a/src/mailman/rest/domains.py +++ b/src/mailman/rest/domains.py @@ -31,15 +31,15 @@ from zope.component import getUtility from mailman.interfaces.domain import ( BadDomainSpecificationError, IDomainManager) -from mailman.rest.helpers import etag, path_to +from mailman.rest.helpers import CollectionMixin, etag, path_to -class _DomainBase(resource.Resource): +class _DomainBase(resource.Resource, CollectionMixin): """Shared base class for domain representations.""" - def _domain_data(self, domain): - """Return the domain data for a single domain.""" + def _resource_as_dict(self, domain): + """See `CollectionMixin`.""" return dict( base_url=domain.base_url, contact_address=domain.contact_address, @@ -49,9 +49,9 @@ class _DomainBase(resource.Resource): url_host=domain.url_host, ) - def _format_domain(self, domain): - """Format the data for a single domain.""" - return etag(self._domain_data(domain)) + def _get_collection(self, request): + """See `CollectionMixin`.""" + return list(getUtility(IDomainManager)) class ADomain(_DomainBase): @@ -66,7 +66,7 @@ class ADomain(_DomainBase): domain = getUtility(IDomainManager).get(self._domain) if domain is None: return http.not_found() - return http.ok([], self._format_domain(domain)) + return http.ok([], self._resource_as_json(domain)) class AllDomains(_DomainBase): @@ -90,18 +90,7 @@ class AllDomains(_DomainBase): return http.created(location, [], None) @resource.GET() - def container(self, request): - """Return the /domains end-point.""" - domains = list(getUtility(IDomainManager)) - if len(domains) == 0: - resource = dict(start=None, total_size=0) - return http.ok([], etag(resource)) - entries = [self._domain_data(domain) for domain in domains] - # Tag the domain entries, but use the dictionaries. - [etag(data) for data in entries] - resource = dict( - start=0, - total_size=len(domains), - entries=entries, - ) + def collection(self, request): + """/domains""" + resource = self._make_collection(request) return http.ok([], etag(resource)) diff --git a/src/mailman/rest/helpers.py b/src/mailman/rest/helpers.py index fac4ae4f1..87614d1f0 100644 --- a/src/mailman/rest/helpers.py +++ b/src/mailman/rest/helpers.py @@ -21,6 +21,7 @@ from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ + 'ContainerMixin', 'etag', 'path_to', ] @@ -71,3 +72,52 @@ def etag(resource): etag = hashlib.sha1(repr(resource)).hexdigest() resource['http_etag'] = '"{0}"'.format(etag) return json.dumps(resource) + + + +class CollectionMixin: + """Mixin class for common collection-ish things.""" + + def _resource_as_dict(self, resource): + """Return the dictionary representation of a resource. + + This must be implemented by subclasses. + + :param resource: The resource object. + :type resource: object + :return: The representation of the resource. + :rtype: dict + """ + raise NotImplementedError + + def _resource_as_json(self, resource): + """Return the JSON formatted representation of the resource.""" + return etag(self._resource_as_dict(resource)) + + def _get_collection(self, request): + """Return the collection as a concrete list. + + This must be implemented by subclasses. + + :param request: A restish request. + :return: The collection + :rtype: list + """ + raise NotImplementedError + + def _make_collection(self, request): + """Provide the collection to restish.""" + collection = self._get_collection(request) + if len(collection) == 0: + return dict(start=0, total_size=0) + else: + entries = [self._resource_as_dict(resource) + for resource in collection] + # Tag the resources but use the dictionaries. + [etag(resource) for resource in entries] + # Create the collection resource + return dict( + start=0, + total_size=len(collection), + entries=entries, + ) diff --git a/src/mailman/rest/lists.py b/src/mailman/rest/lists.py index 682353373..b232cc5bc 100644 --- a/src/mailman/rest/lists.py +++ b/src/mailman/rest/lists.py @@ -33,7 +33,7 @@ from mailman.interfaces.domain import BadDomainSpecificationError from mailman.interfaces.listmanager import ( IListManager, ListAlreadyExistsError) from mailman.interfaces.member import MemberRole -from mailman.rest.helpers import etag, path_to +from mailman.rest.helpers import CollectionMixin, etag, path_to from mailman.rest.members import AMember @@ -62,11 +62,11 @@ member_matcher.score = () -class _ListBase(resource.Resource): +class _ListBase(resource.Resource, CollectionMixin): """Shared base class for mailing list representations.""" - def _list_data(self, mlist): - """Return the list data for a single mailing list.""" + def _resource_as_dict(self, mlist): + """See `CollectionMixin`.""" return dict( fqdn_listname=mlist.fqdn_listname, host_name=mlist.host_name, @@ -75,9 +75,9 @@ class _ListBase(resource.Resource): self_link=path_to('lists/{0}'.format(mlist.fqdn_listname)), ) - def _format_list(self, mlist): - """Format the mailing list for a single mailing list.""" - return etag(self._list_data(mlist)) + def _get_collection(self, request): + """See `CollectionMixin`.""" + return list(getUtility(IListManager)) class AList(_ListBase): @@ -91,7 +91,7 @@ class AList(_ListBase): """Return a single mailing list end-point.""" if self._mlist is None: return http.not_found() - return http.ok([], self._format_list(self._mlist)) + return http.ok([], self._resource_as_json(self._mlist)) @resource.child(member_matcher) def member(self, request, segments, role, address): @@ -123,18 +123,7 @@ class AllLists(_ListBase): return http.created(location, [], None) @resource.GET() - def container(self, request): - """Return the /lists end-point.""" - mlists = list(getUtility(IListManager)) - if len(mlists) == 0: - resource = dict(start=None, total_size=0) - return http.ok([], etag(resource)) - entries = [self._list_data(mlist) for mlist in mlists] - # Tag the list entries, but use the dictionaries. - [etag(data) for data in entries] - resource = dict( - start=0, - total_size=len(mlists), - entries=entries, - ) + def collection(self, request): + """/lists""" + resource = self._make_collection(request) return http.ok([], etag(resource)) diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py index b18097935..ace1ff3cb 100644 --- a/src/mailman/rest/members.py +++ b/src/mailman/rest/members.py @@ -34,24 +34,24 @@ from mailman.interfaces.address import InvalidEmailAddressError from mailman.interfaces.listmanager import NoSuchListError from mailman.interfaces.member import AlreadySubscribedError, MemberRole from mailman.interfaces.membership import ISubscriptionService -from mailman.rest.helpers import etag, path_to +from mailman.rest.helpers import CollectionMixin, etag, path_to -class _MemberBase(resource.Resource): +class _MemberBase(resource.Resource, CollectionMixin): """Shared base class for member representations.""" - def _member_data(self, member): - """Return the member data for a single member.""" + def _resource_as_dict(self, member): + """See `CollectionMixin`.""" enum, dot, role = str(member.role).partition('.') return dict( self_link=path_to('lists/{0}/{1}/{2}'.format( member.mailing_list, role, member.address.address)), ) - def _format_member(self, member): - """Format the data for a single member.""" - return etag(self._member_data(member)) + def _get_collection(self, request): + """See `CollectionMixin`.""" + return list(getUtility(ISubscriptionService)) class AMember(_MemberBase): @@ -77,7 +77,7 @@ class AMember(_MemberBase): @resource.GET() def member(self, request): """Return a single member end-point.""" - return http.ok([], self._format_member(self._member)) + return http.ok([], self._resource_as_json(self._member)) @resource.DELETE() def delete(self, request): @@ -122,17 +122,6 @@ class AllMembers(_MemberBase): @resource.GET() def container(self, request): - """Return the /members end-point.""" - members = list(getUtility(ISubscriptionService)) - if len(members) == 0: - resource = dict(start=None, total_size=0) - return http.ok([], etag(resource)) - entries = [self._member_data(member) for member in members] - # Tag the domain entries, but use the dictionaries. - [etag(data) for data in entries] - resource = dict( - start=0, - total_size=len(members), - entries=entries, - ) + """/members""" + resource = self._make_collection(request) return http.ok([], etag(resource)) |
