/usr/lib/python3/dist-packages/waitress/runner.py is in python3-waitress 0.8.8-1ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | ##############################################################################
#
# Copyright (c) 2013 Zope Foundation 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.
#
##############################################################################
"""Command line runner.
"""
from __future__ import print_function, unicode_literals
import getopt
import os
import os.path
import re
import sys
from waitress import serve
from waitress.adjustments import Adjustments
HELP = """\
Usage:
{0} [OPTS] MODULE:OBJECT
Standard options:
--help
Show this information.
--call
Call the given object to get the WSGI application.
--host=ADDR
Hostname or IP address on which to listen, default is '0.0.0.0',
which means "all IP addresses on this host".
--port=PORT
TCP port on which to listen, default is '8080'
--unix-socket=PATH
Path of Unix socket. If a socket path is specified, a Unix domain
socket is made instead of the usual inet domain socket.
Not available on Windows.
--unix-socket-perms=PERMS
Octal permissions to use for the Unix domain socket, default is
'600'.
--url-scheme=STR
Default wsgi.url_scheme value, default is 'http'.
--url-prefix=STR
The ``SCRIPT_NAME`` WSGI environment value. Setting this to anything
except the empty string will cause the WSGI ``SCRIPT_NAME`` value to be
the value passed minus any trailing slashes you add, and it will cause
the ``PATH_INFO`` of any request which is prefixed with this value to
be stripped of the prefix. Default is the empty string.
--ident=STR
Server identity used in the 'Server' header in responses. Default
is 'waitress'.
Tuning options:
--threads=INT
Number of threads used to process application logic, default is 4.
--backlog=INT
Connection backlog for the server. Default is 1024.
--recv-bytes=INT
Number of bytes to request when calling socket.recv(). Default is
8192.
--send-bytes=INT
Number of bytes to send to socket.send(). Default is 18000.
Multiples of 9000 should avoid partly-filled TCP packets.
--outbuf-overflow=INT
A temporary file should be created if the pending output is larger
than this. Default is 1048576 (1MB).
--inbuf-overflow=INT
A temporary file should be created if the pending input is larger
than this. Default is 524288 (512KB).
--connection-limit=INT
Stop creating new channelse if too many are already active.
Default is 100.
--cleanup-interval=INT
Minimum seconds between cleaning up inactive channels. Default
is 30. See '--channel-timeout'.
--channel-timeout=INT
Maximum number of seconds to leave inactive connections open.
Default is 120. 'Inactive' is defined as 'has recieved no data
from the client and has sent no data to the client'.
--[no-]log-socket-errors
Toggle whether premature client disconnect tracepacks ought to be
logged. On by default.
--max-request-header-size=INT
Maximum size of all request headers combined. Default is 262144
(256KB).
--max-request-body-size=INT
Maximum size of request body. Default is 1073741824 (1GB).
--[no-]expose-tracebacks
Toggle whether to expose tracebacks of unhandled exceptions to the
client. Off by default.
--asyncore-loop-timeout=INT
The timeout value in seconds passed to asyncore.loop(). Default is 1.
--asyncore-use-poll
The use_poll argument passed to ``asyncore.loop()``. Helps overcome
open file descriptors limit. Default is False.
"""
RUNNER_PATTERN = re.compile(r"""
^
(?P<module>
[a-z_][a-z0-9_]*(?:\.[a-z_][a-z0-9_]*)*
)
:
(?P<object>
[a-z_][a-z0-9_]*(?:\.[a-z_][a-z0-9_]*)*
)
$
""", re.I | re.X)
def match(obj_name):
matches = RUNNER_PATTERN.match(obj_name)
if not matches:
raise ValueError("Malformed application '{0}'".format(obj_name))
return matches.group('module'), matches.group('object')
def resolve(module_name, object_name):
"""Resolve a named object in a module."""
# We cast each segments due to an issue that has been found to manifest
# in Python 2.6.6, but not 2.6.8, and may affect other revisions of Python
# 2.6 and 2.7, whereby ``__import__`` chokes if the list passed in the
# ``fromlist`` argument are unicode strings rather than 8-bit strings.
# The error triggered is "TypeError: Item in ``fromlist '' not a string".
# My guess is that this was fixed by checking against ``basestring``
# rather than ``str`` sometime between the release of 2.6.6 and 2.6.8,
# but I've yet to go over the commits. I know, however, that the NEWS
# file makes no mention of such a change to the behaviour of
# ``__import__``.
segments = [str(segment) for segment in object_name.split('.')]
obj = __import__(module_name, fromlist=segments[:1])
for segment in segments:
obj = getattr(obj, segment)
return obj
def show_help(stream, name, error=None): # pragma: no cover
if error is not None:
print('Error: {0}\n'.format(error), file=stream)
print(HELP.format(name), file=stream)
def run(argv=sys.argv, _serve=serve):
"""Command line runner."""
name = os.path.basename(argv[0])
try:
kw, args = Adjustments.parse_args(argv[1:])
except getopt.GetoptError as exc:
show_help(sys.stderr, name, str(exc))
return 1
if kw['help']:
show_help(sys.stdout, name)
return 0
if len(args) != 1:
show_help(sys.stderr, name, 'Specify one application only')
return 1
try:
module, obj_name = match(args[0])
except ValueError as exc:
show_help(sys.stderr, name, str(exc))
return 1
# Add the current directory onto sys.path
sys.path.append(os.getcwd())
# Get the WSGI function.
try:
app = resolve(module, obj_name)
except ImportError:
show_help(sys.stderr, name, "Bad module '{0}'".format(module))
return 1
except AttributeError:
show_help(sys.stderr, name, "Bad object name '{0}'".format(obj_name))
return 1
if kw['call']:
app = app()
# These arguments are specific to the runner, not waitress itself.
del kw['call'], kw['help']
_serve(app, **kw)
return 0
|