[Zope3-checkins] SVN: Zope3/trunk/src/zope/ Implemented a WSGI-compliant server based on ZServer's HTTP server. Also

Stephan Richter srichter at cosmos.phy.tufts.edu
Tue Apr 12 16:34:37 EDT 2005


Log message for revision 29956:
  Implemented a WSGI-compliant server based on ZServer's HTTP server. Also 
  removed some duplication of the WSGI code.
  
  

Changed:
  U   Zope3/trunk/src/zope/app/server/configure.zcml
  A   Zope3/trunk/src/zope/app/server/wsgi.py
  U   Zope3/trunk/src/zope/app/wsgi/README.txt
  U   Zope3/trunk/src/zope/app/wsgi/__init__.py
  U   Zope3/trunk/src/zope/app/wsgi/tests.py
  D   Zope3/trunk/src/zope/publisher/tests/test_wsgi.py
  D   Zope3/trunk/src/zope/publisher/wsgi.py
  D   Zope3/trunk/src/zope/publisher/wsgi.txt
  A   Zope3/trunk/src/zope/server/http/wsgihttpserver.py

-=-
Modified: Zope3/trunk/src/zope/app/server/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/server/configure.zcml	2005-04-12 20:32:33 UTC (rev 29955)
+++ Zope3/trunk/src/zope/app/server/configure.zcml	2005-04-12 20:34:35 UTC (rev 29956)
@@ -17,6 +17,12 @@
       />
 
   <utility
+      name="WSGI-HTTP"
+      component=".wsgi.http"
+      provides=".servertype.IServerType"
+      />
+
+  <utility
       name="FTP"
       component=".ftp.server"
       provides=".servertype.IServerType"

Copied: Zope3/trunk/src/zope/app/server/wsgi.py (from rev 29953, Zope3/branches/srichter-wsgi-zserver/src/zope/app/server/wsgi.py)


Property changes on: Zope3/trunk/src/zope/app/server/wsgi.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/trunk/src/zope/app/wsgi/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/wsgi/README.txt	2005-04-12 20:32:33 UTC (rev 29955)
+++ Zope3/trunk/src/zope/app/wsgi/README.txt	2005-04-12 20:34:35 UTC (rev 29956)
@@ -25,7 +25,7 @@
 We can now initialize the application:
 
   >>> from zope.app import wsgi
-  >>> app = wsgi.PublisherApp(db)
+  >>> app = wsgi.WSGIPublisherApplication(db)
 
 The callable ``app`` object accepts two positional arguments, the environment
 and the function that initializes the response and returns a function with

Modified: Zope3/trunk/src/zope/app/wsgi/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/wsgi/__init__.py	2005-04-12 20:32:33 UTC (rev 29955)
+++ Zope3/trunk/src/zope/app/wsgi/__init__.py	2005-04-12 20:34:35 UTC (rev 29956)
@@ -77,7 +77,7 @@
         self.wsgi_write(data)
 
 
-class PublisherApp(object):
+class WSGIPublisherApplication(object):
     """A WSGI application implemenation for the zope publisher
 
     Instances of this class can be used as a WSGI application object.
@@ -105,8 +105,6 @@
 
         publish(request)
 
-        request.close()
-
         # since the response is written using the WSGI ``write()`` callable
         # return an empty iterable (see PEP 333).
         return ""

Modified: Zope3/trunk/src/zope/app/wsgi/tests.py
===================================================================
--- Zope3/trunk/src/zope/app/wsgi/tests.py	2005-04-12 20:32:33 UTC (rev 29955)
+++ Zope3/trunk/src/zope/app/wsgi/tests.py	2005-04-12 20:34:35 UTC (rev 29956)
@@ -17,19 +17,13 @@
 """
 import unittest
 from zope.testing import doctest
-from zope.app.testing import setup, ztapi, placelesssetup
+from zope.app.testing import placelesssetup
 
-def setUp(test):
-    placelesssetup.setUp(test)
-
-def tearDown(test):
-    placelesssetup.tearDown(test)
-
-
 def test_suite():
     return unittest.TestSuite((
         doctest.DocFileSuite('README.txt',
-                             setUp=setUp, tearDown=tearDown,
+                             setUp=placelesssetup.setUp,
+                             tearDown=placelesssetup.tearDown,
                              optionflags=doctest.NORMALIZE_WHITESPACE),
         ))
 

Deleted: Zope3/trunk/src/zope/publisher/tests/test_wsgi.py
===================================================================
--- Zope3/trunk/src/zope/publisher/tests/test_wsgi.py	2005-04-12 20:32:33 UTC (rev 29955)
+++ Zope3/trunk/src/zope/publisher/tests/test_wsgi.py	2005-04-12 20:34:35 UTC (rev 29956)
@@ -1,27 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""WSGI tests
-
-$Id$
-"""
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-
-def test_suite():
-    return unittest.TestSuite((
-        DocTestSuite('zope.publisher.wsgi'),
-        ))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Deleted: Zope3/trunk/src/zope/publisher/wsgi.py
===================================================================
--- Zope3/trunk/src/zope/publisher/wsgi.py	2005-04-12 20:32:33 UTC (rev 29955)
+++ Zope3/trunk/src/zope/publisher/wsgi.py	2005-04-12 20:34:35 UTC (rev 29956)
@@ -1,212 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""A WSGI Application wrapper for zope
-
-$Id$
-"""
-
-from zope.interface import implements
-from zope.publisher.publish import publish
-from zope.publisher.http import HTTPRequest
-from zope.publisher.interfaces.http import IHeaderOutput
-from zope.publisher.browser import BrowserRequest
-from zope.publisher.xmlrpc import XMLRPCRequest
-
-class WsgiOutput(object):
-    """This class handles the output generated by
-    the publisher. It is used to collect the headers
-    and as an outstream to output the response body.
-
-    When write is first called by the response, it initiates
-    the reponse by invoking the WSGI start_response callable.
-
-    Create a mock implementation of the wsgi write callable
-    >>> from StringIO import StringIO
-    >>> data = StringIO('')
-    >>> def start_response(status, headers):
-    ...     data.write('status and headers.')
-    ...     return data.write
-    ...
-
-    create an instance
-    >>> output = WsgiOutput(start_response)
-
-    Set the response status
-    >>> output.setResponseStatus("200", "OK")
-    >>> output._statusString
-    '200 OK'
-    
-    Set the headers as a mapping
-    >>> output.setResponseHeaders({'a':'b', 'c':'d'})
-
-    They must be returned as a list of tuples
-    >>> output.getHeaders()
-    [('a', 'b'), ('c', 'd')]
-    
-    calling setResponseHeaders again adds new values 
-    >>> output.setResponseHeaders({'x':'y', 'c':'d'})
-    >>> h = output.getHeaders()
-    >>> h.sort()
-    >>> h
-    [('a', 'b'), ('c', 'd'), ('x', 'y')]
-
-    Headers that can potentially repeat are added using
-    appendResponseHeaders
-    >>> output.appendResponseHeaders(['foo: bar'])
-    >>> h = output.getHeaders()
-    >>> h.sort()
-    >>> h    
-    [('a', 'b'), ('c', 'd'), ('foo', ' bar'), ('x', 'y')]
-    >>> output.appendResponseHeaders(['foo: bar'])
-    >>> h = output.getHeaders()
-    >>> h.sort()
-    >>> h    
-    [('a', 'b'), ('c', 'd'), ('foo', ' bar'), ('foo', ' bar'), ('x', 'y')]
-
-    Headers containing a colon should also work
-    >>> output.appendResponseHeaders(['my: brain:hurts'])
-    >>> h = output.getHeaders()
-    >>> h.sort()
-    >>> h    
-    [('a', 'b'), ('c', 'd'), ('foo', ' bar'), \
-('foo', ' bar'), ('my', ' brain:hurts'), ('x', 'y')]
-
-    The headers should not be written to the output
-    >>> output.wroteResponseHeader()
-    False
-    >>> data.getvalue()
-    ''
-    
-    now write something
-    >>> output.write('Now for something')
-
-    The headers should be sent and the data written to the stream
-    >>> output.wroteResponseHeader()
-    True
-    >>> data.getvalue()
-    'status and headers.Now for something'
-
-    calling write again the headers should not be sent again
-    >>> output.write(' completly different!')
-    >>> data.getvalue()
-    'status and headers.Now for something completly different!'
-    """
-
-    def __init__(self, start_response):
-        self._headers = {}
-        self._accumulatedHeaders = []
-        self._statusString = ""
-        self._headersSent = False
-
-        self.wsgi_write = None
-        self.start_response = start_response
-
-    def setResponseStatus(self,status, reason):
-        """Sets the status code and the accompanying message.
-        """
-        self._statusString = str(status)+' '+reason
-
-    def setResponseHeaders(self, mapping):
-        """Sets headers.  The headers must be Correctly-Cased.
-        """
-        self._headers.update(mapping)
-
-    def appendResponseHeaders(self, lst):
-        """Sets headers that can potentially repeat.
-
-        Takes a list of strings.
-        """
-        self._accumulatedHeaders.extend(lst)
-
-    def wroteResponseHeader(self):
-        """Returns a flag indicating whether the response
-
-        header has already been sent.
-        """
-        return self._headersSent
-
-    def setAuthUserName(self, name):
-        """Sets the name of the authenticated user so the name can be logged.
-        """
-        pass
-
-    def getHeaders(self):
-        """return the response headers as a list of tuples according
-        to the WSGI spec
-        """
-        response_headers = self._headers.items()
-
-        accum = [ tuple(line.split(':',1)) for line in self._accumulatedHeaders]
-            
-        response_headers.extend(accum)
-        return response_headers
-
-
-    def write(self, data):
-        """write the response.
-        If the reponse has not begun, call the wsgi servers
-        'start_reponse' callable to begin the response
-        """
-        if not self._headersSent:
-            self.wsgi_write = self.start_response(self._statusString,
-                                         self.getHeaders())
-            self._headersSent = True
-
-        self.wsgi_write(data)
-
-
-class PublisherApp(object):
-    """A WSGI application implemenation for the zope publisher
-
-    Instances of this class can be used as a WSGI application
-    object.
-
-    The class relies on a properly initialized request factory.
-    
-    """
-    
-
-    def __init__(self, publication):
-        self.publication = publication
-
-    def __call__(self, env, start_response,
-                 _browser_methods = ('GET', 'POST', 'HEAD'),
-                 ):
-        """makes instances a WSGI callable application object
-        """
-        
-        wsgi_output = WsgiOutput(start_response)
-        input_stream = env['wsgi.input']
-
-        method = env.get('REQUEST_METHOD', 'GET').upper()
-        if method in _browser_methods:
-            if (method == 'POST' and
-                env.get('CONTENT_TYPE', '').startswith('text/xml')
-                ):
-                request = XMLRPCRequest(input_stream, wsgi_output, env)
-            else:
-                request = BrowserRequest(input_stream, wsgi_output, env)
-        else:
-            request = HTTPRequest(input_stream, wsgi_output, env)
-
-        request.setPublication(self.publication)
-        request.response.setHeaderOutput(wsgi_output)
-
-        publish(request)
-
-        request.close()
-
-        # since the response is written using the WSGI write callable
-        # return an empty iterable (see 
-        return ""

Deleted: Zope3/trunk/src/zope/publisher/wsgi.txt
===================================================================
--- Zope3/trunk/src/zope/publisher/wsgi.txt	2005-04-12 20:32:33 UTC (rev 29955)
+++ Zope3/trunk/src/zope/publisher/wsgi.txt	2005-04-12 20:34:35 UTC (rev 29956)
@@ -1,43 +0,0 @@
-=====================
-Zope WSGI Application
-=====================
-
-About
------
-This package contains a WSGI application for Zope.
-
-WSGI is the Python Web Server Gateway Interface, an
-upcoming PEP to standardize the interface between web servers
-and python applications to promote portability.
-
-For more information, refer to the WSGI specification: http://www.python.org/peps/pep-0333.html
-
-Usage
------
-To use Zope as a WSGI application, the following steps must be taken
-
-* configure and setup Zope
-
-* create an instance of ``zope.app.wsgi.PublisherApp`` must be created
-  with a refernce to an open database
-
-* This instance must be set as the WSGI servers application object
-
-
-Example::
-
-    from zope.app.server.main import setup, load_options
-    from zope.app.wsgi import PublisherApp
-
-    args = ["-C/path/to/zope.conf"]
-    db = setup(load_options(args))
-
-    my_app = PublisherApp(db)
-
-    wsgi_server.set_app(my_app)
-
-This assumes, that Zope is available on the ``PYTHONPATH``.
-Note that you may have to edit ``zope.conf`` to provide
-an absolute path for ``site.zcml``.
-
-

Copied: Zope3/trunk/src/zope/server/http/wsgihttpserver.py (from rev 29953, Zope3/branches/srichter-wsgi-zserver/src/zope/server/http/wsgihttpserver.py)


Property changes on: Zope3/trunk/src/zope/server/http/wsgihttpserver.py
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Zope3-Checkins mailing list