[z3-checkins] r10647 - in z3/modzope/trunk/src/modzope: . apache
mod_python
philikon at codespeak.net
philikon at codespeak.net
Fri Apr 15 00:46:15 MEST 2005
Author: philikon
Date: Fri Apr 15 00:46:15 2005
New Revision: 10647
Added:
z3/modzope/trunk/src/modzope/TODO
z3/modzope/trunk/src/modzope/schema.xml
z3/modzope/trunk/src/modzope/wsgi.py (contents, props changed)
z3/modzope/trunk/src/modzope/wsgizope.py (contents, props changed)
Removed:
z3/modzope/trunk/src/modzope/apache/
z3/modzope/trunk/src/modzope/mod_python/
Modified:
z3/modzope/trunk/src/modzope/app.py
Log:
Total revamp of modzope using WSGI (PEP333). Now that Zope 3 trunk has
a supposedly working implementation of an WSGI application, this seemed
possible.
This uses Phillip Eby's wsgiref reference implementation and some example
code from the web-sig mailinglist regarding using mod_python as a WSGI
server.
The now remaining code is
a) startup code (app.py, schema.xml)
b) glue between mod_python's WSGI handler and Zope's WSGI app (wsgizope.py)
If it would only work...
Added: z3/modzope/trunk/src/modzope/TODO
==============================================================================
--- (empty file)
+++ z3/modzope/trunk/src/modzope/TODO Fri Apr 15 00:46:15 2005
@@ -0,0 +1,8 @@
+TODO
+----
+
+- somehow, the file names specified in modzope.conf are not
+ interpreted as relative to the location of modzope.conf but relative
+ to / !
+
+- nothing works, the system hangs when issuing a request
Modified: z3/modzope/trunk/src/modzope/app.py
==============================================================================
--- z3/modzope/trunk/src/modzope/app.py (original)
+++ z3/modzope/trunk/src/modzope/app.py Fri Apr 15 00:46:15 2005
@@ -1,82 +1,55 @@
##############################################################################
#
-# Copyright (c) 2004 Philipp "philiKON" von Weitershausen
+# Copyright (c) 2005 Philipp "philiKON" von Weitershausen
# 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.
+# 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.
#
##############################################################################
-"""Modzope application.
+"""Application initialization
$Id: app.py 218 2004-05-24 04:48:56Z philipp $
"""
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.publish import publish as _publish
-
+import sys
+import os.path
import zope.app.appsetup
-import zope.app.debug
-import zope.app.event
-from zope.app.publication.browser import BrowserPublication
-
-class Application(object):
- """Modzope application
-
- The application takes care of ZCML configuration, database(s) and
- publishing a request.
- """
-
- def __init__(self, db_file, config_file):
- zope.app.appsetup.config(config_file)
- # already publishes IDatabaseOpenedEvent
- self.db = zope.app.appsetup.database(db_file)
- zope.app.event.publish(None, zope.app.appsetup.ProcessStarting())
-
- # XXX use IHTTPRequest, HTTPPublication as default?!?
- def _request(self, context, request_type=IBrowserRequest,
- publication=BrowserPublication):
- pub = publication(self.db)
- request = request_type(context)
- request.setPublication(pub)
- return request
-
- def publish(self, context, *args, **kw):
- #XXX take a few arguments more in order to decide which
- # request/publication to use
- request = self._request(context)
-
- # _publish executes request.close() at which point the
- # response is gone so, let's save it here.
- response = request.response
- _publish(request)
- return response
-
- def run(self, context, *args, **kw):
- self.publish(context, *args, **kw)
-
-class DebugApplication(Application, zope.app.debug.Debugger):
- """Application object useful for debugging"""
-
-_application = None
-
-def getApplication(context):
- global _application
- if _application is not None:
- return _application
+from zope.event import notify
+from zope.app.server.main import ZopeOptions
+from zope.app.wsgi import WSGIPublisherApplication
+
+class ModzopeOptions(ZopeOptions):
+
+ # XXX
+ configfile = "/Users/philipp/dev/Zope3/modzope-demosite/modzope.conf"
+
+def load_options(args=[]):
+ options = ModzopeOptions()
+ options.schemadir = os.path.dirname(os.path.abspath(__file__))
+ options.realize(args)
+ options = options.configroot
+
+ if options.path:
+ sys.path[:0] = [os.path.abspath(p) for p in options.path]
+ return options
+
+def setup(options):
+ sys.setcheckinterval(options.check_interval)
+ zope.app.appsetup.config(options.site_definition)
+ db = options.database.open()
+ notify(zope.app.appsetup.interfaces.DatabaseOpened(db))
+ notify(zope.app.appsetup.interfaces.ProcessStarting())
+ return db
+def setupApplication(config=None):
# waargh
- import sys
sys.argv = []
+ # XXX get load_option args from apache conf?
+ db = setup(load_options())
+ return WSGIPublisherApplication(db)
- import os.path
- config = context.get_options()
- sitepath = config.get('sitepath', '')
- db = config.get('dbfile', os.path.join(sitepath, 'Data.fs'))
- config_file = config.get('siteconfig', os.path.join(sitepath, 'site.zcml'))
-
- _application = Application(db, config_file)
- return _application
+application = setupApplication()
Added: z3/modzope/trunk/src/modzope/schema.xml
==============================================================================
--- (empty file)
+++ z3/modzope/trunk/src/modzope/schema.xml Fri Apr 15 00:46:15 2005
@@ -0,0 +1,62 @@
+<schema>
+ <description>
+ Zope 3 configuration schema.
+
+ This schema describes the configuration options available to a
+ site administrator via the zope.conf configuration file.
+ </description>
+
+ <!-- database and storage types -->
+ <import package="ZODB" />
+
+ <!-- logging configuration -->
+ <import package="ZConfig.components.logger" />
+ <import package="zope.app.server" file="accesslog.xml" />
+
+ <sectiontype name="server" datatype="zope.app.server.server.ServerFactory">
+ <key name="type" required="yes" />
+ <key name="address" datatype="inet-address" />
+ <key name="verbose" datatype="boolean" />
+ </sectiontype>
+
+ <section type="ZODB.database" name="*" required="yes"
+ attribute="database">
+ <description>
+ The main application database that should be used.
+ </description>
+ </section>
+
+ <key name="site-definition" default="site.zcml">
+ <description>
+ The name of the top-level ZCML file that defines the component
+ configuration used for this site.
+ </description>
+ </key>
+
+ <key name="interrupt-check-interval" datatype="integer" default="120"
+ attribute="check_interval">
+ <description>
+ Value passed to Python's sys.setcheckinterval() function.
+
+ This integer value determines how often the interpreter checks
+ for periodic things such as thread switches and signal handlers.
+ Setting it to a larger value may increase performance for
+ programs using threads. Setting it to a value <= 0 checks every
+ virtual instruction, maximizing responsiveness as well as
+ overhead.
+ </description>
+ </key>
+
+ <multikey name="path" datatype="string">
+ <description>
+ This specifies additional paths directories which are inserted into
+ the beginning of Python's module search path. The set of directories
+ specified is inserted into the beginning of the module search path in
+ the order which they are specified here. Note that the processing of
+ this directive may happen too late under some circumstances; it is
+ recommended that you use the PYTHONPATH environment variable if
+ using this directive doesn't work for you.
+ </description>
+ <metadefault>$softwarehome/src</metadefault>
+ </multikey>
+</schema>
Added: z3/modzope/trunk/src/modzope/wsgi.py
==============================================================================
--- (empty file)
+++ z3/modzope/trunk/src/modzope/wsgi.py Fri Apr 15 00:46:15 2005
@@ -0,0 +1,112 @@
+##############################################################################
+#
+# Copyright (c) 2005 Philipp "philiKON" von Weitershausen
+# 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.
+#
+##############################################################################
+"""WSGI glue for mod_python
+
+This aims to implement the WSGI spec v1.0, a.k.a. PEP 333
+(see http://python.org/peps/pep-0333.html)
+
+Largely based on the example by Robert Brewer, posted at
+http://mail.python.org/pipermail/web-sig/2004-October/000980.html
+
+$Id$
+"""
+import sys
+from wsgiref.handlers import BaseCGIHandler
+from mod_python import apache
+
+class ModPythonInputStream(object):
+
+ def __init__(self, request):
+ self.request = request
+
+ def read(self, size=-1):
+ return self.request.read(size)
+
+ def readline(self):
+ return self.request.readline()
+
+ def readlines(self, hint=-1):
+ return self.request.readlines(hint)
+
+ def __iter__(self):
+ return iter(self.request.readlines())
+
+class ModPythonErrorStream(object):
+ """Error stream
+
+ This enables logging to a custom error log file as defined with a
+ ErrorLog directive. Errors are printed to sys.stderr end up in
+ the global apache error log file."""
+
+ def __init__(self, request):
+ self.request = request
+ config = request.get_config()
+ self.debug = bool(config.get("PythonDebug", False))
+
+ def flush(self):
+ pass
+
+ def write(self, msg):
+ self.request.log_error(msg)
+ if self.debug:
+ self.request.write(msg)
+
+ def writelines(self, seq):
+ self.write('\r\n'.join(seq))
+
+class ModPythonHandler(BaseCGIHandler):
+
+ def __init__(self, request):
+ options = request.get_options()
+
+ try:
+ mpm_query = apache.mpm_query
+ except AttributeError:
+ # Threading and forking
+ threaded = options.get('multithread', '')
+ forked = options.get('multiprocess', '')
+ if not (threaded and forked):
+ raise ValueError("You must provide 'multithread' and "
+ "'multiprocess' PythonOptions when "
+ "running mod_python < 3.1")
+ threaded = threaded.lower() in ('on', 't', 'true', '1')
+ forked = forked.lower() in ('on', 't', 'true', '1')
+ else:
+ threaded = mpm_query(apache.AP_MPMQ_IS_THREADED)
+ forked = mpm_query(apache.AP_MPMQ_IS_FORKED)
+
+ apache_env = apache.build_cgi_env(request)
+
+ BaseCGIHandler.__init__(
+ self, stdin=ModPythonInputStream(req), stdout=None,
+ stderr=ModPythonErrorStream(req), environ=env,
+ multiprocess=forked, multithread=threaded)
+ self.request = request
+ self._write = request.write
+
+ def _flush(self):
+ pass
+
+ #XXX what about status?
+ def send_headers(self):
+ self.cleanup_headers()
+ self.headers_sent = True
+ self.request.status = int(self.status[:3])
+ for name, value in self.headers.items():
+ if name.lower() == 'content-length':
+ self.request.set_content_length(int(value))
+ elif name.lower() == 'content-type':
+ self.request.content_type = value
+ else:
+ self.request.headers_out[name] = value
Added: z3/modzope/trunk/src/modzope/wsgizope.py
==============================================================================
--- (empty file)
+++ z3/modzope/trunk/src/modzope/wsgizope.py Fri Apr 15 00:46:15 2005
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# Copyright (c) 2005 Philipp "philiKON" von Weitershausen
+# 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.
+#
+##############################################################################
+"""Handler that connects mod_python to Zope's WSGI application
+
+$Id$
+"""
+from mod_python import apache
+from modzope.wsgi import ModPythonHandler
+from modzope.app import application
+
+def handler(request):
+ handler = ModPythonHandler(request)
+ handler.run(application)
+ return apache.OK
More information about the z3-checkins
mailing list