------------------------------------------------------------
revno: 6751
committer: Barry Warsaw <[email protected]>
branch nick: 3.0
timestamp: Mon 2009-07-20 23:13:59 -0400
message:
  Our first writable REST API!  You can now create new domains through the
  webserver.
  
  Fix the https/http urls.
  
  Add the adapter for HTTPCharsets so POSTs work properly.  Nice little cargo
  cult from lazr.restful.
modified:
  src/mailman/interfaces/domain.py
  src/mailman/queue/docs/rest.txt
  src/mailman/rest/adapters.py
  src/mailman/rest/configuration.py
  src/mailman/rest/configure.zcml
  src/mailman/rest/docs/basic.txt
  src/mailman/rest/docs/domains.txt
  src/mailman/rest/docs/lists.txt
  src/mailman/tests/test_documentation.py

=== modified file 'src/mailman/interfaces/domain.py'
--- src/mailman/interfaces/domain.py    2009-07-17 02:36:06 +0000
+++ src/mailman/interfaces/domain.py    2009-07-21 03:13:59 +0000
@@ -29,7 +29,7 @@
 
 from lazr.restful.declarations import (
     collection_default_content, export_as_webservice_collection,
-    export_as_webservice_entry, exported)
+    export_as_webservice_entry, export_factory_operation, exported)
 from zope.interface import Interface, Attribute
 from zope.schema import TextLine
 
@@ -174,3 +174,27 @@
         :return: The list of all known domains.
         :rtype: list of `IDomain`
         """
+
+    @export_factory_operation(
+        IDomain,
+        ('email_host', 'description', 'base_url', 'contact_address'))
+    def new(email_host, description=None, base_url=None, contact_address=None):
+        """Add a new domain.
+
+        :param email_host: The email host name for the domain.
+        :type email_host: string
+        :param description: The description of the domain.
+        :type description: string
+        :param base_url: The base url, including the scheme for the web
+            interface of the domain.  If not given, it defaults to
+            http://`email_host`/
+        :type base_url: string
+        :param contact_address: The email contact address for the human
+            managing the domain.  If not given, defaults to
+            postmas...@`email_host`
+        :type contact_address: string
+        :return: The new domain object
+        :rtype: `IDomain`
+        :raises `BadDomainSpecificationError`: when the `email_host` is
+            already registered.
+        """

=== modified file 'src/mailman/queue/docs/rest.txt'
--- src/mailman/queue/docs/rest.txt     2009-05-10 20:13:02 +0000
+++ src/mailman/queue/docs/rest.txt     2009-07-21 03:13:59 +0000
@@ -1,3 +1,4 @@
+===========
 REST server
 ===========
 
@@ -13,11 +14,11 @@
     http_etag: "..."
     mailman_version: GNU Mailman 3.0... (...)
     python_version: ...
-    resource_type_link: https://localhost:8001/3.0/#system
-    self_link: https://localhost:8001/3.0/system
+    resource_type_link: http://localhost:8001/3.0/#system
+    self_link: http://localhost:8001/3.0/system
 
 
 Clean up
---------
+========
 
     >>> master.stop()

=== modified file 'src/mailman/rest/adapters.py'
--- src/mailman/rest/adapters.py        2009-07-17 02:36:06 +0000
+++ src/mailman/rest/adapters.py        2009-07-21 03:13:59 +0000
@@ -61,3 +61,10 @@
         if domain is None:
             raise NotFound(self, name)
         return domain
+
+    def new(self, email_host, description=None, base_url=None,
+            contact_address=None):
+        """See `IDomainCollection`."""
+        value = self._manager.add(
+            email_host, description, base_url, contact_address)
+        return value

=== modified file 'src/mailman/rest/configuration.py'
--- src/mailman/rest/configuration.py   2009-07-01 22:04:04 +0000
+++ src/mailman/rest/configuration.py   2009-07-21 03:13:59 +0000
@@ -25,6 +25,7 @@
     ]
 
 
+from lazr.config import as_boolean
 from lazr.restful.interfaces import IWebServiceConfiguration
 from zope.interface import implements
 
@@ -51,7 +52,7 @@
     @property
     def use_https(self):
         """See `IWebServiceConfiguration`."""
-        return config.webservice.use_https
+        return as_boolean(config.webservice.use_https)
 
     # This should match the major.minor Mailman version.
     service_version_uri_prefix = '{0.MAJOR_REV}.{0.MINOR_REV}'.format(version)

=== modified file 'src/mailman/rest/configure.zcml'
--- src/mailman/rest/configure.zcml     2009-07-17 02:36:06 +0000
+++ src/mailman/rest/configure.zcml     2009-07-21 03:13:59 +0000
@@ -12,6 +12,8 @@
   <webservice:register module="mailman.interfaces.listmanager" />
   <webservice:register module="mailman.interfaces.system" />
 
+  <adapter factory="zope.publisher.http.HTTPCharsets" />
+
   <adapter
     for="mailman.interfaces.domain.IDomainManager"
     provides="mailman.interfaces.domain.IDomainCollection"

=== modified file 'src/mailman/rest/docs/basic.txt'
--- src/mailman/rest/docs/basic.txt     2009-05-27 21:56:01 +0000
+++ src/mailman/rest/docs/basic.txt     2009-07-21 03:13:59 +0000
@@ -16,8 +16,8 @@
     http_etag: "..."
     mailman_version: GNU Mailman 3.0... (...)
     python_version: ...
-    resource_type_link: https://localhost:8001/3.0/#system
-    self_link: https://localhost:8001/3.0/system
+    resource_type_link: http://localhost:8001/3.0/#system
+    self_link: http://localhost:8001/3.0/system
 
 
 Non-existent links

=== modified file 'src/mailman/rest/docs/domains.txt'
--- src/mailman/rest/docs/domains.txt   2009-07-19 02:31:45 +0000
+++ src/mailman/rest/docs/domains.txt   2009-07-21 03:13:59 +0000
@@ -14,7 +14,7 @@
 initially none.
 
     >>> dump_json('http://localhost:8001/3.0/domains')
-    resource_type_link: https://localhost:8001/3.0/#domains
+    resource_type_link: http://localhost:8001/3.0/#domains
     start: None
     total_size: 0
 
@@ -34,10 +34,10 @@
         description: An example domain
         email_host: example.com
         http_etag: "..."
-        resource_type_link: https://localhost:8001/3.0/#domain
-        self_link: https://localhost:8001/3.0/domains/example.com
+        resource_type_link: http://localhost:8001/3.0/#domain
+        self_link: http://localhost:8001/3.0/domains/example.com
         url_host: lists.example.com
-    resource_type_link: https://localhost:8001/3.0/#domains
+    resource_type_link: http://localhost:8001/3.0/#domains
     start: 0
     total_size: 1
 
@@ -64,8 +64,8 @@
         description: An example domain
         email_host: example.com
         http_etag: "..."
-        resource_type_link: https://localhost:8001/3.0/#domain
-        self_link: https://localhost:8001/3.0/domains/example.com
+        resource_type_link: http://localhost:8001/3.0/#domain
+        self_link: http://localhost:8001/3.0/domains/example.com
         url_host: lists.example.com
     entry 1:
         base_url: http://mail.example.org
@@ -73,8 +73,8 @@
         description: None
         email_host: example.org
         http_etag: "..."
-        resource_type_link: https://localhost:8001/3.0/#domain
-        self_link: https://localhost:8001/3.0/domains/example.org
+        resource_type_link: http://localhost:8001/3.0/#domain
+        self_link: http://localhost:8001/3.0/domains/example.org
         url_host: mail.example.org
     entry 2:
         base_url: http://example.net
@@ -82,10 +82,10 @@
         description: Porkmasters
         email_host: lists.example.net
         http_etag: "..."
-        resource_type_link: https://localhost:8001/3.0/#domain
-        self_link: https://localhost:8001/3.0/domains/lists.example.net
+        resource_type_link: http://localhost:8001/3.0/#domain
+        self_link: http://localhost:8001/3.0/domains/lists.example.net
         url_host: example.net
-    resource_type_link: https://localhost:8001/3.0/#domains
+    resource_type_link: http://localhost:8001/3.0/#domains
     start: 0
     total_size: 3
 
@@ -102,8 +102,8 @@
     description: Porkmasters
     email_host: lists.example.net
     http_etag: "..."
-    resource_type_link: https://localhost:8001/3.0/#domain
-    self_link: https://localhost:8001/3.0/domains/lists.example.net
+    resource_type_link: http://localhost:8001/3.0/#domain
+    self_link: http://localhost:8001/3.0/domains/lists.example.net
     url_host: example.net
 
 But we get a 404 for a non-existent domain.
@@ -112,3 +112,43 @@
     Traceback (most recent call last):
     ...
     HTTPError: HTTP Error 404: Not Found
+
+
+Creating new domains
+====================
+
+New domains can be created by posting to the 'domains' url.  However
+lazr.restful requires us to use a 'named operation' instead of posting
+directly to the URL.
+
+    >>> dump_json('http://localhost:8001/3.0/domains', {
+    ...           'ws.op': 'new',
+    ...           'email_host': 'lists.example.com',
+    ...           })
+    URL: http://localhost:8001/3.0/domains
+    content-length: 0
+    content-type: text/plain
+    date: ...
+    location: http://localhost:8001/3.0/domains/lists.example.com
+    server: WSGIServer/... Python/...
+    x-content-type-warning: guessed from content
+    x-powered-by: Zope (www.zope.org), Python (www.python.org)
+
+Now the web service knows about our new domain.
+
+    >>> dump_json('http://localhost:8001/3.0/domains/lists.example.com')
+    base_url: http://lists.example.com
+    contact_address: [email protected]
+    description: None
+    email_host: lists.example.com
+    http_etag: "349365fdbf946e64fc1052b936b9192eaa94b850"
+    resource_type_link: http://localhost:8001/3.0/#domain
+    self_link: http://localhost:8001/3.0/domains/lists.example.com
+    url_host: lists.example.com
+
+And the new domain is in our database.
+
+    >>> manager['lists.example.com']
+    <Domain lists.example.com,
+            base_url: http://lists.example.com,
+            contact_address: [email protected]>

=== modified file 'src/mailman/rest/docs/lists.txt'
--- src/mailman/rest/docs/lists.txt     2009-07-11 01:55:26 +0000
+++ src/mailman/rest/docs/lists.txt     2009-07-21 03:13:59 +0000
@@ -7,6 +7,6 @@
 yet though.
 
     >>> dump_json('http://localhost:8001/3.0/lists')
-    resource_type_link: https://localhost:8001/3.0/#mailing_lists
+    resource_type_link: http://localhost:8001/3.0/#mailing_lists
     start: None
     total_size: 0

=== modified file 'src/mailman/tests/test_documentation.py'
--- src/mailman/tests/test_documentation.py     2009-07-19 02:31:45 +0000
+++ src/mailman/tests/test_documentation.py     2009-07-21 03:13:59 +0000
@@ -37,6 +37,7 @@
 import unittest
 
 from email import message_from_string
+from urllib import urlencode
 from urllib2 import urlopen
 
 import mailman
@@ -109,16 +110,28 @@
         print '{0:{2}}: {1}'.format(key, msgdata[key], longest)
 
 
-def dump_json(url):
+def dump_json(url, data=None):
     """Print the JSON dictionary read from a URL.
 
     :param url: The url to open, read, and print.
     :type url: string
+    :param data: Data to use to POST to a URL.
+    :type data: dict
     """
-    fp = urlopen(url)
+    if data is None:
+        fp = urlopen(url)
+    else:
+        fp = urlopen(url, urlencode(data))
     # fp does not support the context manager protocol.
     try:
-        data = json.load(fp)
+        raw_data = fp.read()
+        if len(raw_data) == 0:
+            print 'URL:', fp.geturl()
+            info = fp.info()
+            for header in sorted(info):
+                print '{0}: {1}'.format(header, info[header])
+            return
+        data = json.loads(raw_data)
     finally:
         fp.close()
     for key in sorted(data):



--
lp:mailman
https://code.launchpad.net/~mailman-coders/mailman/3.0

Your team Mailman Checkins is subscribed to branch lp:mailman.
To unsubscribe from this branch go to 
https://code.launchpad.net/~mailman-coders/mailman/3.0/+edit-subscription.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe: 
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org

Reply via email to