Index: django/core/handlers/modpython.py
===================================================================
--- django/core/handlers/modpython.py	(revision 11638)
+++ django/core/handlers/modpython.py	(working copy)
@@ -1,6 +1,16 @@
+"""
+mod_python handler for Django.
+
+Most of the code to make the handler WSGI-compliant was taken from
+<http://www.aminus.net/browser/modpython_gateway.py> and it was in the Public
+Domain.
+
+"""
 import os
 from pprint import pformat
 
+from mod_python import apache
+
 from django import http
 from django.core import signals
 from django.core.handlers.base import BaseHandler
@@ -12,6 +22,60 @@
 # settings) until after ModPythonHandler has been called; otherwise os.environ
 # won't be set up correctly (with respect to settings).
 
+
+#{ WSGI streams
+
+
+class WSGIStream(object):
+    """
+    Base class for WSGI streams.
+    
+    See: http://www.python.org/dev/peps/pep-0333/#id19
+    
+    """
+    
+    def __init__(self, req):
+        self.req = req
+
+
+class InputStream(WSGIStream):
+    
+    def close(self):
+        pass
+    
+    def read(self, size=-1):
+        return self.req.read(size)
+    
+    def readline(self, size=-1):
+        return self.req.readline(size)
+    
+    def readlines(self, hint=-1):
+        return self.req.readlines(hint)
+    
+    def __iter__(self):
+        line = self.readline()
+        while line:
+            yield line
+            # Notice this won't prefetch the next line; it only
+            # gets called if the generator is resumed.
+            line = self.readline()
+
+
+class ErrorStream(WSGIStream):
+    
+    def flush(self):
+        pass
+    
+    def write(self, msg):
+        self.req.log_error(msg)
+    
+    def writelines(self, seq):
+        self.write(''.join(seq))
+
+
+#}
+
+
 class ModPythonRequest(http.HttpRequest):
     def __init__(self, req):
         self._req = req
@@ -36,6 +100,8 @@
             # naughty, but also pretty harmless.
             self.path_info = u'/'
         self._post_parse_error = False
+        # Finally, let's load the WSGI environ:
+        self._set_environ_up()
 
     def __repr__(self):
         # Since this is called as part of error handling, we need to be very
@@ -62,7 +128,57 @@
         return smart_str(u'<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' %
                          (self.path, unicode(get), unicode(post),
                           unicode(cookies), unicode(meta)))
-
+    
+    def _set_environ_up(self):
+        """
+        Define the WSGI environment dictionary and store it in the request.
+        
+        """
+        self._req.add_common_vars()
+        options = self._req.get_options()
+        environ = dict(self._req.subprocess_env.items())
+        
+        if "SCRIPT_NAME" in options:
+            # Override SCRIPT_NAME and PATH_INFO if requested.
+            environ['SCRIPT_NAME'] = options['SCRIPT_NAME']
+            environ['PATH_INFO'] = self._req.uri[len(options['SCRIPT_NAME']):]
+        
+        environ['wsgi.input'] = InputStream(self._req)
+        environ['wsgi.errors'] = ErrorStream(self._req)
+        environ['wsgi.version'] = (1, 0)
+        environ['wsgi.run_once'] = False
+        if self._req.is_https():
+            environ['wsgi.url_scheme'] = "https"
+        else:
+            environ['wsgi.url_scheme'] = "http"
+        
+        # Threading and forking
+        try:
+            threaded = bool(apache.mpm_query(apache.AP_MPMQ_IS_THREADED))
+            forked = bool(apache.mpm_query(apache.AP_MPMQ_IS_FORKED))
+        except AttributeError:
+            threaded = options.get("multithread", "").lower()
+            if threaded == "on":
+                threaded = True
+            elif threaded == "off":
+                threaded = False
+            else:
+                raise ValueError('The "multithread" option must be either '
+                                 '"on" or "off"')
+            
+            forked = options.get("multiprocess", "").lower()
+            if forked == "on":
+                forked = True
+            elif forked == "off":
+                forked = False
+            else:
+                raise ValueError('The "multiprocess" option must be either '
+                                 '"on" or "off"')
+        environ['wsgi.multithread'] = threaded
+        environ['wsgi.multiprocess'] = forked
+        
+        self.environ = environ
+    
     def get_full_path(self):
         # RFC 3986 requires self._req.args to be in the ASCII range, but this
         # doesn't always happen, so rather than crash, we defensively encode it.
