Skip to content

Commit

Permalink
- Initial import of zope.paste
Browse files Browse the repository at this point in the history
  • Loading branch information
sidnei committed Jan 25, 2006
0 parents commit dacd71c
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 0 deletions.
39 changes: 39 additions & 0 deletions README.txt
@@ -0,0 +1,39 @@
zope.paste - wsgi applications in zope 3 using paste.deploy
===========================================================

What is it?
-----------

A simple package that enables one to configure WSGI applications to
run inside Zope 3 using `paste.deploy`_.

Why?
----

Because Zope 3 already supported WSGI applications, but didn't provide
a simple way to create and configure them.

How to use it?
--------------

Configuration is very simple. There are three steps that need to be
performed:

1. Configure a named IServerType utility

2. Change the <server> directive on <INSTANCE_HOME>/etc/zope.conf to
use the newly-created IServerType utility

3. Configure a WSGI application using `paste.deploy`_ syntax in
<INSTANCE_HOME>/etc/paste.ini

By default, we already define a utility named `Paste.Main`.

Here's an example of how to configure the `Paste.Main` application
using paste.deploy to use the Zope 3 publisher as a WSGI app:

[app:Paste.Main]
paste.app_factory = zope.paste.application:zope_publisher_app_factory


.. _paste.deploy: http://pythonpaste.org/deploy/
54 changes: 54 additions & 0 deletions setup.py
@@ -0,0 +1,54 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""zope.paste - wsgi applications in zope 3 using paste.deploy
zope.paste provides the necessary glue to enable you to use
paste.deploy to configure wsgi apps in zope 3. includes a app_factory
for the zope 3 wsgi zope.app.publisher application.
"""

classifiers = """\
Development Status :: 3 - Alpha
Environment :: Web Environment
License :: OSI Approved :: Zope Public License
Operating System :: OS Independent
Programming Language :: Python
Topic :: Internet :: WWW/HTTP
Topic :: Software Development :: Libraries :: Python Modules
"""

import os
import sys
from setuptools import setup, find_packages

# We're using the module docstring as the distutils descriptions.
doclines = __doc__.split("\n")

setup(name="zope.paste",
version="0.1",
author="Sidnei da Silva",
author_email="sidnei@enfoldsystems.com",
keywords="web wsgi application server",
url="http://cheeseshop.python.org/pypi/zope.paste",
download_url="http://cheeseshop.python.org/packages/source/z/zope.paste/zope.paste-%s.tar.gz" % VERSION,
license="Zope Public License",
platforms=["any"],
description=doclines[0],
classifiers=filter(None, classifiers.split("\n")),
long_description="\n".join(doclines[2:]),
namespace_packages=['zope'],
packages=find_packages(exclude='tests'),
package_data={'zope.paste': ['*.zcml']},
zip_safe=False,
)
1 change: 1 addition & 0 deletions version.txt
@@ -0,0 +1 @@
0.1
18 changes: 18 additions & 0 deletions zope/__init__.py
@@ -0,0 +1,18 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""
$Id$
"""
import pkg_resources
pkg_resources.declare_namespace('zope')
16 changes: 16 additions & 0 deletions zope/paste/__init__.py
@@ -0,0 +1,16 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""
$Id$
"""
66 changes: 66 additions & 0 deletions zope/paste/_server.py
@@ -0,0 +1,66 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""
$Id$
"""

from zope.interface import implements
from zope.paste.application import PasteApplication

from zope.server.http.wsgihttpserver import WSGIHTTPServer
from zope.server.http.commonaccesslogger import CommonAccessLogger

from zope.app.server.servertype import IServerType

class ServerType(object):

implements(IServerType)

def __init__(self, factory, applicationFactory, logFactory,
defaultPort, defaultVerbose, defaultIP=''):
self._factory = factory
self._applicationFactory = applicationFactory
self._logFactory = logFactory
self._defaultPort = defaultPort
self._defaultVerbose = defaultVerbose
self._defaultIP = defaultIP

# XXX Zope calls ServerType.create() with a db argument, which is
# the root ZODB database. We must get rid of this for ZODB-less
# applications.
def create(self, name, task_dispatcher, db, port=None,
verbose=None, ip=None):
'See IServerType'

application = self._applicationFactory(name)

if port is None:
port = self._defaultPort

if ip is None:
ip = self._defaultIP

if verbose is None:
verbose = self._defaultVerbose

return self._factory(application, name, ip, port,
task_dispatcher=task_dispatcher,
verbose=verbose,
hit_log=self._logFactory(),
)

http = ServerType(WSGIHTTPServer,
PasteApplication,
CommonAccessLogger,
8380, True)
59 changes: 59 additions & 0 deletions zope/paste/_twisted.py
@@ -0,0 +1,59 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""
$Id$
"""

from twisted.web2 import iweb, log, resource, server, stream, wsgi
from twisted.web2.channel.http import HTTPFactory

from zope.interface import implements
from zope.paste.application import PasteApplication

from zope.app.twisted.http import Prebuffer
from zope.app.twisted.interfaces import IServerType
from zope.app.twisted.server import ZopeTCPServer

class ServerType(object):

implements(IServerType)

def __init__(self, factory, defaultPort, defaultIP=''):
self._factory = factory
self._defaultPort = defaultPort
self._defaultIP = defaultIP

# XXX Zope calls ServerType.create() with a db argument, which is
# the root ZODB database. We must get rid of this for ZODB-less
# applications.
def create(self, name, db, ip=None, port=None, backlog=50):
'See IServerType'
if port is None:
port = self._defaultPort

if ip is None:
ip = self._defaultIP

# Create a twisted.internet.interfaces.IServerFactory
factory = self._factory(name)
return ZopeTCPServer(name, port, factory,
interface=ip, backlog=backlog)

def createHTTPFactory(name):
resource = wsgi.WSGIResource(PasteApplication(name))
resource = log.LogWrapperResource(resource)
resource = Prebuffer(resource)
return HTTPFactory(server.Site(resource))

http = ServerType(createHTTPFactory, 8380)
64 changes: 64 additions & 0 deletions zope/paste/application.py
@@ -0,0 +1,64 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""
$Id$
"""

import os
from paste.deploy import loadapp
from zope.interface import implements

from zope.app.wsgi import interfaces
from zope.app.wsgi import WSGIPublisherApplication
from zope.app.publication.httpfactory import HTTPPublicationRequestFactory

class PasteApplication(object):
"""A WSGI application implementation hooking a paste app to the
zope publisher.
Instances of this class can be used as a WSGI application object.
The class relies on a properly initialized request factory.
"""
implements(interfaces.IWSGIApplication)

def __init__(self, name):
# `name` that gets passed here is something like:
# <utility_name>:<host>:<port> for zope.app.twisted, and just
# <utility_name> for zope.app.server. Extract just the utility
# name.
name = name.rsplit(':', 2)[0]
# XXX There's no way currently to find out where our
# INSTANCE_HOME is, so assume the cwd is the INSTANCE_HOME.
path = os.getcwd()
self.wsgi_app = loadapp('config:etc/paste.ini',
name, relative_to=path)

def __call__(self, environ, start_response):
"""See zope.app.wsgi.interfaces.IWSGIApplication"""
return self.wsgi_app(environ, start_response)

# XXX Dirty hack. Since we don't have access to the configured
# database or anything as the ZConfig options object is thrown away,
# we create the application and then stash the request factory into it
# when the database opened event gets fired.
publisher_app = WSGIPublisherApplication(None)

def zope_publisher_app_factory(global_config, **local_config):
return publisher_app

def databaseOpened(event):
global publisher_app
factory = HTTPPublicationRequestFactory(event.database)
publisher_app.requestFactory = factory
26 changes: 26 additions & 0 deletions zope/paste/configure.zcml
@@ -0,0 +1,26 @@
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:zcml="http://namespaces.zope.org/zcml">


<configure zcml:condition="have zserver">
<utility
name="Paste.Main"
component="._server.http"
provides="zope.app.server.servertype.IServerType"
/>
</configure>

<configure zcml:condition="have twisted">
<utility
name="Paste.Main"
component="._twisted.http"
provides="zope.app.twisted.interfaces.IServerType"
/>
</configure>

<subscriber
handler=".application.databaseOpened"
for="zope.app.appsetup.IDatabaseOpenedEvent"
/>

</configure>

0 comments on commit dacd71c

Please sign in to comment.