1. Wojciech Malinowski
  2. Webware


Webware / WebKit / Adapters / WSGIAdapter.py

#!/usr/bin/env python


This is the WSGI Adapter for the WebKit AppServer.

The socket address of the WebKit AppServer can be specified
with the Host and AdapterPort settings in the configuration file
called 'WSGIAdapter.config' (default is localhost on port 8086).

Note that this adapter script and the AppServer must be running
with marshal-compatible Python versions (check marshal.version).

Contributed to Webware for Python by Christoph Zwerschke, 04/2010.


# If you used the MakeAppWorkDir.py script to make a separate
# application working directory, specify it here:
workDir = None

# If the Webware installation is located somewhere else,
# then set the webwareDir variable to point to it here:
webwareDir = None

import os, sys

if not webwareDir:
    webwareDir = os.path.dirname(os.path.dirname(
sys.path.insert(0, webwareDir)
webKitDir = os.path.join(webwareDir, 'WebKit')
sys.path.insert(0, webKitDir)
if not workDir:
    workDir = webKitDir

from WebKit.Adapters.Adapter import Adapter

class StdErr(object):
    """Auxiliary store for temporary redirection of sys.stderr."""
    def __init__(self, stderr):
        if stderr:
            self.stderr, sys.stderr = sys.stderr, stderr
            self.stderr = None
    def close(self):
        if self.stderr:
            self.stderr, sys.stderr = None, self.stderr
    def __del__(self):

class WSGIAdapter(Adapter):
    """WSGI application interfacing to the Webware application server."""

    def __call__(self, environ, start_response):
        """The actual WSGI application."""
        err = StdErr(environ.get('wsgi.errors', None))
            inp = environ.get('wsgi.input', None)
            if inp is not None:
                    inp_len = int(environ['CONTENT_LENGTH'])
                    if inp_len <= 0:
                        raise ValueError
                except (KeyError, ValueError):
                    inp = None
                        inp = inp.read(inp_len)
                    except IOError:
                        inp = None
            # we pass only environment variables that can be marshalled
            environ = dict(item for item in environ.iteritems()
                if isinstance(item[1], (bool, int, long, float,
                    str, unicode, tuple, list, set, frozenset, dict)))
            response = self.getChunksFromAppServer(environ, inp or '')
            header = []
            for chunk in response:
                if header is None:
                    yield chunk
                    chunk = chunk.split('\r\n\r\n', 1)
                    if len(chunk) > 1:
                        chunk = chunk[1]
                        header = ''.join(header).split('\r\n')
                        status = header.pop(0).split(': ', 1)[-1]
                        header = [tuple(line.split(': ', 1)) for line in header]
                        start_response(status, header)
                        header = None
                        if chunk:
                            yield chunk
            # This is a workaround for Python 2.4 which does not allow a
            # yield statement to live in a try block with a finally clause.
            # Note that this also works if the generator is simply abandoned
            # even though Python 2.4 does not raise a GeneratorExit, because
            # if the generator is deleted, the local variable err also gets
            # deleted and its close() method will be called by its destructor.
            raise # re-raise the original exception

# Create one WSGI application instance:

wsgiAdapter = WSGIAdapter(workDir)

application = wsgiAdapter # the name expected by mod_wsgi