• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / Zope / 3956162881

pending completion
3956162881

push

github

Michael Howitz
Update to deprecation warning free releases.

4401 of 7036 branches covered (62.55%)

Branch coverage included in aggregate %.

27161 of 31488 relevant lines covered (86.26%)

0.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

36.52
/src/Zope2/Startup/serve.py
1
# (c) 2005 Ian Bicking and contributors; written for Paste
2
# (http://pythonpaste.org) Licensed under the MIT license:
3
# http://www.opensource.org/licenses/mit-license.php
4
#
5
# For discussion of daemonizing:
6
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
7
#
8
# Code taken also from QP: http://www.mems-exchange.org/software/qp/ From
9
# lib/site.py
10
#
11
# Code further taken from:
12
# https://github.com/Pylons/pyramid/blob/master/pyramid/scripts/pserve.py and
13
# https://github.com/Pylons/pyramid/blob/master/pyramid/paster.py
14
# licensed under the BSD-derived Repoze Public License
15
# (http://repoze.org/license.html).
16

17
import configparser
1✔
18
import optparse
1✔
19
import os
1✔
20
import re
1✔
21
import sys
1✔
22
from logging.config import fileConfig
1✔
23

24
from paste.deploy import loadapp
1✔
25
from paste.deploy import loadserver
1✔
26

27
import Zope2
1✔
28
from App.config import getConfiguration
1✔
29

30

31
def parse_vars(args):
1✔
32
    """
33
    Given variables like ``['a=b', 'c=d']`` turns it into ``{'a':
34
    'b', 'c': 'd'}``
35
    """
36
    result = {}
1✔
37
    for arg in args:
1✔
38
        if '=' not in arg:
1✔
39
            raise ValueError(
1✔
40
                'Variable assignment %r invalid (no "=")'
41
                % arg)
42
        name, value = arg.split('=', 1)
1✔
43
        result[name] = value
1✔
44
    return result
1✔
45

46

47
def _getpathsec(config_uri, name):
1✔
48
    if '#' in config_uri:
1✔
49
        path, section = config_uri.split('#', 1)
1✔
50
    else:
51
        path, section = config_uri, 'main'
1✔
52
    if name:
1✔
53
        section = name
1✔
54
    return path, section
1✔
55

56

57
def setup_logging(config_uri, global_conf=None,  # NOQA
1✔
58
                  fileConfig=fileConfig,
59
                  configparser=configparser):
60
    """
61
    Set up logging via :func:`logging.config.fileConfig` with the filename
62
    specified via ``config_uri`` (a string in the form
63
    ``filename#sectionname``).
64
    ConfigParser defaults are specified for the special ``__file__``
65
    and ``here`` variables, similar to PasteDeploy config loading.
66
    Extra defaults can optionally be specified as a dict in ``global_conf``.
67
    """
68
    path, _ = _getpathsec(config_uri, None)
×
69
    parser = configparser.ConfigParser()
×
70
    parser.read([path])
×
71
    if parser.has_section('loggers'):
×
72
        config_file = os.path.abspath(path)
×
73
        full_global_conf = dict(
×
74
            __file__=config_file,
75
            here=os.path.dirname(config_file))
76
        if global_conf:
×
77
            full_global_conf.update(global_conf)
×
78
        return fileConfig(
×
79
            config_file, full_global_conf, disable_existing_loggers=False)
80

81

82
class ServeCommand:
1✔
83

84
    usage = '%prog config_uri [var=value]'
1✔
85
    description = """\
1✔
86
This command serves a web application that uses a PasteDeploy
87
configuration file for the server and application.
88
You can also include variable assignments like 'http_port=8080'
89
and then use %(http_port)s in your config files.
90
    """
91
    default_verbosity = 1
1✔
92

93
    parser = optparse.OptionParser(
1✔
94
        usage,
95
        description=description
96
    )
97
    parser.add_option(
1✔
98
        '-n', '--app-name',
99
        dest='app_name',
100
        metavar='NAME',
101
        help="Load the named application (default main)")
102
    parser.add_option(
1✔
103
        '-s', '--server',
104
        dest='server',
105
        metavar='SERVER_TYPE',
106
        help="Use the named server.")
107
    parser.add_option(
1✔
108
        '--server-name',
109
        dest='server_name',
110
        metavar='SECTION_NAME',
111
        help=("Use the named server as defined in the configuration file "
112
              "(default: main)"))
113
    parser.add_option(
1✔
114
        '-v', '--verbose',
115
        default=default_verbosity,
116
        dest='verbose',
117
        action='count',
118
        help="Set verbose level (default " + str(default_verbosity) + ")")
119
    parser.add_option(
1✔
120
        '-q', '--quiet',
121
        action='store_const',
122
        const=0,
123
        dest='verbose',
124
        help="Suppress verbose output")
125
    parser.add_option(
1✔
126
        '-d', '--debug',
127
        action='store_const',
128
        const=1,
129
        dest='debug',
130
        help="Enable debug mode.")
131
    parser.add_option(
1✔
132
        '-e', '--debug-exceptions',
133
        action='store_const',
134
        const=1,
135
        dest='debug_exceptions',
136
        help="Enable exceptions debug mode.")
137

138
    _scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)
1✔
139

140
    def __init__(self, argv, quiet=False):
1✔
141
        self.options, self.args = self.parser.parse_args(argv[1:])
1✔
142
        if quiet:
1✔
143
            self.options.verbose = 0
1✔
144

145
    def out(self, msg):
1✔
146
        if self.options.verbose > 0:
1✔
147
            print(msg)
1✔
148

149
    def get_options(self):
1✔
150
        restvars = self.args[1:]
×
151
        return parse_vars(restvars)
×
152

153
    def run(self):
1✔
154
        if not self.args:
×
155
            self.out('You must give a config file')
×
156
            return 2
×
157
        app_spec = self.args[0]
×
158
        app_name = self.options.app_name
×
159

160
        vars = self.get_options()
×
161

162
        if not self._scheme_re.search(app_spec):
×
163
            app_spec = 'config:' + app_spec
×
164
        server_name = self.options.server_name
×
165
        if self.options.server:
×
166
            server_spec = 'egg:Zope2'
×
167
            assert server_name is None
×
168
            server_name = self.options.server
×
169
        else:
170
            server_spec = app_spec
×
171
        base = os.getcwd()
×
172

173
        log_fn = app_spec
×
174
        if log_fn.startswith('config:'):
×
175
            log_fn = app_spec[len('config:'):]
×
176
        elif log_fn.startswith('egg:'):
×
177
            log_fn = None
×
178
        if log_fn:
×
179
            log_fn = os.path.join(base, log_fn)
×
180
            setup_logging(log_fn, global_conf=vars)
×
181

182
        server = self.loadserver(server_spec, name=server_name,
×
183
                                 relative_to=base, global_conf=vars)
184

185
        if 'debug_mode' not in vars and self.options.debug:
×
186
            vars['debug_mode'] = 'true'
×
187
        if 'debug_exceptions' not in vars and self.options.debug_exceptions:
×
188
            vars['debug_exceptions'] = 'true'
×
189
        app = self.loadapp(app_spec, name=app_name, relative_to=base,
×
190
                           global_conf=vars)
191

192
        if self.options.verbose > 0:
×
193
            if hasattr(os, 'getpid'):
×
194
                msg = 'Starting server in PID %i.' % os.getpid()
×
195
            else:
196
                msg = 'Starting server.'
×
197
            self.out(msg)
×
198

199
        def serve():
×
200
            self.makePidFile()
×
201

202
            try:
×
203
                server(app)
×
204
            except (SystemExit, KeyboardInterrupt) as e:
×
205
                if self.options.verbose > 1:
×
206
                    raise
×
207
                if str(e):
×
208
                    msg = ' ' + str(e)
×
209
                else:
210
                    msg = ''
×
211
                self.out('Exiting%s (-v to see traceback)' % msg)
×
212
            finally:
213
                for db in Zope2.opened:
×
214
                    db.close()
×
215
                self.unlinkPidFile()
×
216

217
        serve()
×
218

219
    def loadapp(self, app_spec, name, relative_to, **kw):
1✔
220
        return loadapp(app_spec, name=name, relative_to=relative_to, **kw)
×
221

222
    def loadserver(self, server_spec, name, relative_to, **kw):
1✔
223
        return loadserver(
×
224
            server_spec, name=name, relative_to=relative_to, **kw)
225

226
    def makePidFile(self):
1✔
227
        options = getConfiguration()
×
228
        try:
×
229
            IO_ERRORS = (IOError, OSError, WindowsError)
×
230
        except NameError:
×
231
            IO_ERRORS = (IOError, OSError)
×
232

233
        try:
×
234
            if os.path.exists(options.pid_filename):
×
235
                os.unlink(options.pid_filename)
×
236
            with open(options.pid_filename, 'w') as fp:
×
237
                fp.write(str(os.getpid()))
×
238
        except IO_ERRORS:
×
239
            pass
×
240

241
    def unlinkPidFile(self):
1✔
242
        options = getConfiguration()
×
243
        try:
×
244
            os.unlink(options.pid_filename)
×
245
        except OSError:
×
246
            pass
×
247

248

249
def main(argv=sys.argv, quiet=False):
1✔
250
    command = ServeCommand(argv, quiet=quiet)
×
251
    return command.run()
×
252

253

254
if __name__ == '__main__':
255
    sys.exit(main() or 0)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc