Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
253 lines (216 sloc) 7.54 KB
# (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).
import optparse
import os
import re
import sys
from logging.config import fileConfig
from paste.deploy import loadapp
from paste.deploy import loadserver
from six.moves import configparser
from App.config import getConfiguration
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, disable_existing_loggers=False)
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")
parser.add_option(
'-d', '--debug',
action='store_const',
const=1,
dest='debug',
help="Enable debug mode.")
parser.add_option(
'-e', '--debug-exceptions',
action='store_const',
const=1,
dest='debug_exceptions',
help="Enable exceptions debug mode.")
_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)
if 'debug_mode' not in vars and self.options.debug:
vars['debug_mode'] = 'true'
if 'debug_exceptions' not in vars and self.options.debug_exceptions:
vars['debug_exceptions'] = 'true'
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():
self.makePidFile()
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)
finally:
self.unlinkPidFile()
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 makePidFile(self):
options = getConfiguration()
try:
IO_ERRORS = (IOError, OSError, WindowsError)
except NameError:
IO_ERRORS = (IOError, OSError)
try:
if os.path.exists(options.pid_filename):
os.unlink(options.pid_filename)
with open(options.pid_filename, 'w') as fp:
fp.write(str(os.getpid()))
except IO_ERRORS:
pass
def unlinkPidFile(self):
options = getConfiguration()
try:
os.unlink(options.pid_filename)
except OSError:
pass
def main(argv=sys.argv, quiet=False):
command = ServeCommand(argv, quiet=quiet)
return command.run()
if __name__ == '__main__':
sys.exit(main() or 0)
You can’t perform that action at this time.