diff options
| -rw-r--r-- | src/mailman/interfaces/rest.py | 44 | ||||
| -rw-r--r-- | src/mailman/model/listmanager.py | 3 | ||||
| -rw-r--r-- | src/mailman/queue/rest.py | 2 | ||||
| -rw-r--r-- | src/mailman/rest/adapters.py | 14 | ||||
| -rw-r--r-- | src/mailman/rest/webservice.py | 86 | ||||
| -rw-r--r-- | src/mailman/rest/wsgiapp.py | 87 |
6 files changed, 96 insertions, 140 deletions
diff --git a/src/mailman/interfaces/rest.py b/src/mailman/interfaces/rest.py deleted file mode 100644 index 9ec7914ad..000000000 --- a/src/mailman/interfaces/rest.py +++ /dev/null @@ -1,44 +0,0 @@ -# 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/>. - -"""Interfaces for the RESTful admin server.""" - -from __future__ import absolute_import, unicode_literals - -__metaclass__ = type -__all__ = [ - 'APIValueError', - 'IResolvePathNames', - ] - - -from zope.interface import Interface - -from mailman.core.errors import MailmanError - - - -class APIValueError(MailmanError, ValueError): - """A `ValueError` from the REST API.""" - - - -class IResolvePathNames(Interface): - """A marker interface objects that implement simple traversal.""" - - def get(name): - """Traverse to a contained object.""" diff --git a/src/mailman/model/listmanager.py b/src/mailman/model/listmanager.py index cc3226b80..3d0448e8e 100644 --- a/src/mailman/model/listmanager.py +++ b/src/mailman/model/listmanager.py @@ -32,7 +32,6 @@ from zope.interface import implements from mailman.config import config from mailman.interfaces.address import InvalidEmailAddressError from mailman.interfaces.listmanager import IListManager, ListAlreadyExistsError -from mailman.interfaces.rest import IResolvePathNames from mailman.model.mailinglist import MailingList @@ -40,7 +39,7 @@ from mailman.model.mailinglist import MailingList class ListManager: """An implementation of the `IListManager` interface.""" - implements(IListManager, IResolvePathNames) + implements(IListManager) # pylint: disable-msg=R0201 def create(self, fqdn_listname): diff --git a/src/mailman/queue/rest.py b/src/mailman/queue/rest.py index a14f0b081..a7c9727e2 100644 --- a/src/mailman/queue/rest.py +++ b/src/mailman/queue/rest.py @@ -32,7 +32,7 @@ import signal import logging from mailman.queue import Runner -from mailman.rest.webservice import make_server +from mailman.rest.wsgiapp import make_server log = logging.getLogger('mailman.http') diff --git a/src/mailman/rest/adapters.py b/src/mailman/rest/adapters.py index 2ae5d497e..6acfe3866 100644 --- a/src/mailman/rest/adapters.py +++ b/src/mailman/rest/adapters.py @@ -36,7 +36,6 @@ from mailman.interfaces.address import InvalidEmailAddressError from mailman.interfaces.listmanager import IListManager, NoSuchListError from mailman.interfaces.member import DeliveryMode from mailman.interfaces.membership import ISubscriptionService -from mailman.interfaces.rest import APIValueError @@ -77,15 +76,10 @@ class SubscriptionService: mlist = getUtility(IListManager).get(fqdn_listname) if mlist is None: raise NoSuchListError(fqdn_listname) - # Convert from string to enum. Turn Python's ValueErrors into one - # suitable for the REST API. - try: - mode = (DeliveryMode.regular - if delivery_mode is None - else DeliveryMode(delivery_mode)) - except ValueError: - raise APIValueError( - 'Invalid delivery_mode: {0}'.format(delivery_mode)) + # Convert from string to enum. + mode = (DeliveryMode.regular + if delivery_mode is None + else DeliveryMode(delivery_mode)) if real_name is None: real_name, at, domain = address.partition('@') if len(at) == 0: diff --git a/src/mailman/rest/webservice.py b/src/mailman/rest/webservice.py index d7f7d231e..9db29f133 100644 --- a/src/mailman/rest/webservice.py +++ b/src/mailman/rest/webservice.py @@ -21,9 +21,7 @@ from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ - 'AdminWebServiceApplication', - 'AdminWebServiceRequest', - 'make_server', + 'Root', ] @@ -31,10 +29,8 @@ import json import hashlib import logging -from restish.app import RestishApp from restish import http, resource -from wsgiref.simple_server import ( - make_server as wsgi_server, WSGIRequestHandler) +from wsgiref.simple_server import make_server as wsgi_server from zope.component import getUtility from zope.interface import implements @@ -51,8 +47,6 @@ from mailman.interfaces.mailinglist import IMailingList from mailman.interfaces.member import ( AlreadySubscribedError, IMember, MemberRole) from mailman.interfaces.membership import ISubscriptionService -from mailman.interfaces.rest import APIValueError, IResolvePathNames -#from mailman.rest.publication import AdminWebServicePublication COMMASPACE = ', ' @@ -370,7 +364,7 @@ class AllMembers(_MemberBase): return http.bad_request([], b'No such list') except InvalidEmailAddressError: return http.bad_request([], b'Invalid email address') - except APIValueError as error: + except ValueError as error: return http.bad_request([], str(error)) # wsgiref wants headers to be bytes, not unicodes. location = b'http://localhost:8001/3.0/lists/{0}/member/{1}'.format( @@ -399,77 +393,3 @@ class AllMembers(_MemberBase): member_data = self._format_member(member) entries.append(member_data) return http.ok([], json.dumps(response)) - - - - -## class AdminWebServiceRootResource(RootResource): -## """The lazr.restful non-versioned root resource.""" - -## implements(IResolvePathNames) - -## # XXX 2010-02-16 barry lazr.restful really wants this class to exist and -## # be a subclass of RootResource. Our own traversal really wants this to -## # implement IResolvePathNames. RootResource says to override -## # _build_top_level_objects() to return the top-level objects, but that -## # appears to never be called by lazr.restful, so you've got me. I don't -## # understand this, which sucks, so just ensure that it doesn't do anything -## # useful so if/when I do understand this, I can resolve the conflict -## # between the way lazr.restful wants us to do things and the way our -## # traversal wants to do things. -## def _build_top_level_objects(self): -## """See `RootResource`.""" -## raise NotImplementedError('Magic suddenly got invoked') - -## def get(self, name): -## """See `IResolvePathNames`.""" -## top_names = dict( -## domains=getUtility(IDomainCollection), -## lists=getUtility(IListManager), -## members=getUtility(ISubscriptionService), -## system=system, -## ) -## return top_names.get(name) - - -## class AdminWebServiceApplication(WSGIApplication): -## """A WSGI application for the admin REST interface.""" - -## # The only thing we need to override is the publication class. -## publication_class = AdminWebServicePublication - - -class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): - """Handler class which just logs output to the right place.""" - - def log_message(self, format, *args): - """See `BaseHTTPRequestHandler`.""" - log.info('%s - - %s', self.address_string(), format % args) - - -class AdminWebServiceApplication(RestishApp): - """Interpose in the restish request processor.""" - - def __call__(self, environ, start_response): - """See `RestishApp`.""" - try: - response = super(AdminWebServiceApplication, self).__call__( - environ, start_response) - except: - config.db.abort() - raise - else: - config.db.commit() - return response - - - -def make_server(): - """Create the WSGI admin REST server.""" - app = AdminWebServiceApplication(Root()) - host = config.webservice.hostname - port = int(config.webservice.port) - server = wsgi_server( - host, port, app, - handler_class=AdminWebServiceWSGIRequestHandler) - return server diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py new file mode 100644 index 000000000..cfb8cba50 --- /dev/null +++ b/src/mailman/rest/wsgiapp.py @@ -0,0 +1,87 @@ +# Copyright (C) 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/>. + +"""Basic WSGI Application object for REST server.""" + +from __future__ import absolute_import, unicode_literals + +__metaclass__ = type +__all__ = [ + 'make_application', + 'make_server', + ] + + +import logging + +from restish.app import RestishApp +from wsgiref.simple_server import WSGIRequestHandler +from wsgiref.simple_server import make_server as wsgi_server + +from mailman.config import config +from mailman.rest.webservice import Root + + +log = logging.getLogger('mailman.http') + + + +class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): + """Handler class which just logs output to the right place.""" + + def log_message(self, format, *args): + """See `BaseHTTPRequestHandler`.""" + log.info('%s - - %s', self.address_string(), format % args) + + +class AdminWebServiceApplication(RestishApp): + """Connect the restish WSGI application to Mailman's database.""" + + def __call__(self, environ, start_response): + """See `RestishApp`.""" + try: + response = super(AdminWebServiceApplication, self).__call__( + environ, start_response) + except: + config.db.abort() + raise + else: + config.db.commit() + return response + + + +def make_application(): + """Create the WSGI application. + + Use this if you want to integrate Mailman's REST server with your own WSGI + server. + """ + return AdminWebServiceApplication(Root()) + + +def make_server(): + """Create the Mailman REST server. + + Use this if you just want to run Mailman's wsgiref-based REST server. + """ + host = config.webservice.hostname + port = int(config.webservice.port) + server = wsgi_server( + host, port, make_application(), + handler_class=AdminWebServiceWSGIRequestHandler) + return server |
