Commit 72ae9a1b authored by Hanno Schlichting's avatar Hanno Schlichting

Add a new `runwsgi` script to serve PasteDeploy files.

This is a very limited copy of Pyramid's pserve script.
parent 8e31fae5
...@@ -51,6 +51,8 @@ Bugs Fixed ...@@ -51,6 +51,8 @@ Bugs Fixed
Features Added Features Added
++++++++++++++ ++++++++++++++
- Add a new `runwsgi` script to serve PasteDeploy files.
- Depend on and automatically set up `five.globalrequest`. - Depend on and automatically set up `five.globalrequest`.
- Optimized the `OFS.ObjectManager.__contains__` method to do the - Optimized the `OFS.ObjectManager.__contains__` method to do the
......
...@@ -146,7 +146,7 @@ used. ...@@ -146,7 +146,7 @@ used.
A fully-annotated sample can be found in the Zope2 egg:: A fully-annotated sample can be found in the Zope2 egg::
$ cat eggs/Zope2--*/Zope2/utilities/skel/etc/zope.conf.in $ cat eggs/Zope2--*/Zope2/utilities/skel/etc/example.conf.in
<rest of the stuff that goes into a zope.conf, e.g. databases and log files.> <rest of the stuff that goes into a zope.conf, e.g. databases and log files.>
......
...@@ -153,6 +153,6 @@ Start the WSGI Server ...@@ -153,6 +153,6 @@ Start the WSGI Server
.. code-block:: sh .. code-block:: sh
$ bin/paster serve etc/zope.wsgi $ bin/runwsgi -v etc/zope.ini
Starting server in PID 24934. Starting server in PID 24934.
serving on http://127.0.0.1:8080 serving on http://127.0.0.1:8080
...@@ -9,7 +9,6 @@ Missing==3.1 ...@@ -9,7 +9,6 @@ Missing==3.1
MultiMapping==3.0 MultiMapping==3.0
Paste==2.0.3 Paste==2.0.3
PasteDeploy==1.5.2 PasteDeploy==1.5.2
PasteScript==2.0.2
Persistence==3.0a1 Persistence==3.0a1
Products.BTreeFolder2==3.0 Products.BTreeFolder2==3.0
Products.ExternalMethod==3.0 Products.ExternalMethod==3.0
...@@ -37,7 +36,6 @@ python-gettext==3.0 ...@@ -37,7 +36,6 @@ python-gettext==3.0
pytz==2016.6.1 pytz==2016.6.1
repoze.retry==1.4 repoze.retry==1.4
repoze.tm2==2.1 repoze.tm2==2.1
repoze.who==2.3
six==1.10.0 six==1.10.0
tempstorage==3.0 tempstorage==3.0
transaction==1.6.1 transaction==1.6.1
......
...@@ -120,6 +120,7 @@ setup( ...@@ -120,6 +120,7 @@ setup(
], ],
'console_scripts': [ 'console_scripts': [
'mkzopeinstance=Zope2.utilities.mkzopeinstance:main', 'mkzopeinstance=Zope2.utilities.mkzopeinstance:main',
'runwsgi=Zope2.Startup.serve:main',
'runzope=Zope2.Startup.run:run', 'runzope=Zope2.Startup.run:run',
'zopectl=Zope2.Startup.zopectl:run', 'zopectl=Zope2.Startup.zopectl:run',
'zpasswd=Zope2.utilities.zpasswd:main', 'zpasswd=Zope2.utilities.zpasswd:main',
......
...@@ -271,9 +271,9 @@ def publish_module(environ, start_response, ...@@ -271,9 +271,9 @@ def publish_module(environ, start_response,
try: try:
response = _publish(request, 'Zope2') response = _publish(request, 'Zope2')
except Unauthorized, v: except Unauthorized as v:
response._unauthorized() response._unauthorized()
except Redirect, v: except Redirect as v:
response.redirect(v) response.redirect(v)
# Start the WSGI server response # Start the WSGI server response
......
# (c) 2005 Ian Bicking and contributors; written for Paste
# (http://pythonpaste.org) Licensed under the MIT license:
# http://www.opensource.org/licenses/mit-license.php
#
# For discussion of daemonizing:
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
#
# Code taken also from QP: http://www.mems-exchange.org/software/qp/ From
# lib/site.py
#
# Code further taken from:
# https://github.com/Pylons/pyramid/blob/master/pyramid/scripts/pserve.py and
# https://github.com/Pylons/pyramid/blob/master/pyramid/paster.py
# licensed under the BSD-derived Repoze Public License
# (http://repoze.org/license.html).
from logging.config import fileConfig
import optparse
import os
import re
import sys
from paste.deploy import loadserver
from paste.deploy import loadapp
try:
import configparser
except ImportError:
import ConfigParser as configparser
def parse_vars(args):
"""
Given variables like ``['a=b', 'c=d']`` turns it into ``{'a':
'b', 'c': 'd'}``
"""
result = {}
for arg in args:
if '=' not in arg:
raise ValueError(
'Variable assignment %r invalid (no "=")'
% arg)
name, value = arg.split('=', 1)
result[name] = value
return result
def _getpathsec(config_uri, name):
if '#' in config_uri:
path, section = config_uri.split('#', 1)
else:
path, section = config_uri, 'main'
if name:
section = name
return path, section
def setup_logging(config_uri, global_conf=None, # NOQA
fileConfig=fileConfig,
configparser=configparser):
"""
Set up logging via :func:`logging.config.fileConfig` with the filename
specified via ``config_uri`` (a string in the form
``filename#sectionname``).
ConfigParser defaults are specified for the special ``__file__``
and ``here`` variables, similar to PasteDeploy config loading.
Extra defaults can optionally be specified as a dict in ``global_conf``.
"""
path, _ = _getpathsec(config_uri, None)
parser = configparser.ConfigParser()
parser.read([path])
if parser.has_section('loggers'):
config_file = os.path.abspath(path)
full_global_conf = dict(
__file__=config_file,
here=os.path.dirname(config_file))
if global_conf:
full_global_conf.update(global_conf)
return fileConfig(config_file, full_global_conf)
class ServeCommand(object):
usage = '%prog config_uri [var=value]'
description = """\
This command serves a web application that uses a PasteDeploy
configuration file for the server and application.
You can also include variable assignments like 'http_port=8080'
and then use %(http_port)s in your config files.
"""
default_verbosity = 1
parser = optparse.OptionParser(
usage,
description=description
)
parser.add_option(
'-n', '--app-name',
dest='app_name',
metavar='NAME',
help="Load the named application (default main)")
parser.add_option(
'-s', '--server',
dest='server',
metavar='SERVER_TYPE',
help="Use the named server.")
parser.add_option(
'--server-name',
dest='server_name',
metavar='SECTION_NAME',
help=("Use the named server as defined in the configuration file "
"(default: main)"))
parser.add_option(
'-v', '--verbose',
default=default_verbosity,
dest='verbose',
action='count',
help="Set verbose level (default " + str(default_verbosity) + ")")
parser.add_option(
'-q', '--quiet',
action='store_const',
const=0,
dest='verbose',
help="Suppress verbose output")
_scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)
def __init__(self, argv, quiet=False):
self.options, self.args = self.parser.parse_args(argv[1:])
if quiet:
self.options.verbose = 0
def out(self, msg):
if self.options.verbose > 0:
print(msg)
def get_options(self):
restvars = self.args[1:]
return parse_vars(restvars)
def run(self):
if not self.args:
self.out('You must give a config file')
return 2
app_spec = self.args[0]
app_name = self.options.app_name
vars = self.get_options()
if not self._scheme_re.search(app_spec):
app_spec = 'config:' + app_spec
server_name = self.options.server_name
if self.options.server:
server_spec = 'egg:Zope2'
assert server_name is None
server_name = self.options.server
else:
server_spec = app_spec
base = os.getcwd()
log_fn = app_spec
if log_fn.startswith('config:'):
log_fn = app_spec[len('config:'):]
elif log_fn.startswith('egg:'):
log_fn = None
if log_fn:
log_fn = os.path.join(base, log_fn)
setup_logging(log_fn, global_conf=vars)
server = self.loadserver(server_spec, name=server_name,
relative_to=base, global_conf=vars)
app = self.loadapp(app_spec, name=app_name, relative_to=base,
global_conf=vars)
if self.options.verbose > 0:
if hasattr(os, 'getpid'):
msg = 'Starting server in PID %i.' % os.getpid()
else:
msg = 'Starting server.'
self.out(msg)
def serve():
try:
server(app)
except (SystemExit, KeyboardInterrupt) as e:
if self.options.verbose > 1:
raise
if str(e):
msg = ' ' + str(e)
else:
msg = ''
self.out('Exiting%s (-v to see traceback)' % msg)
serve()
def loadapp(self, app_spec, name, relative_to, **kw):
return loadapp(app_spec, name=name, relative_to=relative_to, **kw)
def loadserver(self, server_spec, name, relative_to, **kw):
return loadserver(
server_spec, name=name, relative_to=relative_to, **kw)
def main(argv=sys.argv, quiet=False):
command = ServeCommand(argv, quiet=quiet)
return command.run()
if __name__ == '__main__':
sys.exit(main() or 0)
...@@ -16,7 +16,6 @@ Missing = 3.1 ...@@ -16,7 +16,6 @@ Missing = 3.1
MultiMapping = 3.0 MultiMapping = 3.0
Paste = 2.0.3 Paste = 2.0.3
PasteDeploy = 1.5.2 PasteDeploy = 1.5.2
PasteScript = 2.0.2
Persistence = 3.0a1 Persistence = 3.0a1
persistent = 4.2.1 persistent = 4.2.1
Products.BTreeFolder2 = 3.0 Products.BTreeFolder2 = 3.0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment