cubicweb/pyramid/pyramidctl.py
author Philippe Pepiot <philippe.pepiot@logilab.fr>
Tue, 24 Oct 2017 09:50:29 +0200
branch3.25
changeset 12216 4de5927871f9
parent 12053 c3c9f2e1424c
child 12530 9d88e1177c35
child 12748 9fa65579520f
permissions -rw-r--r--
[pyramid] set waitress url_scheme to https when base-url scheme is https See https://docs.pylonsproject.org/projects/waitress/en/latest/#using-behind-a-reverse-proxy Since we do not configure trusted_proxy waitress ignore X-Forwarded-Proto header and may generate http urls (pyramid request.url) when the instance is behind a https reverse proxy. This cause cubicweb-signredrequest to not work with since it rely on the url (including scheme). Set url_scheme to 'https' when CubicWeb base-url scheme is https as a workaround.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11967
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     1
# copyright 2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     2
# copyright 2014-2016 UNLISH S.A.S. (Montpellier, FRANCE), all rights reserved.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     3
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     4
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     5
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     6
# This file is part of CubicWeb.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     7
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     8
# CubicWeb is free software: you can redistribute it and/or modify it under the
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
     9
# terms of the GNU Lesser General Public License as published by the Free
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    10
# Software Foundation, either version 2.1 of the License, or (at your option)
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    11
# any later version.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    12
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    13
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    14
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    15
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    16
# details.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    17
#
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    18
# You should have received a copy of the GNU Lesser General Public License along
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    19
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    20
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    21
"""
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    22
Provides a 'pyramid' command as a replacement to the 'start' command.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    23
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    24
The reloading strategy is heavily inspired by (and partially copied from)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    25
the pyramid script 'pserve'.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    26
"""
11967
83739be20fab [pyramid] Add a copyright and docstring to all modules
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11867
diff changeset
    27
11663
6fb9d9276880 [ccplugin] print_function
Julien Cristau <julien.cristau@logilab.fr>
parents: 11658
diff changeset
    28
from __future__ import print_function
6fb9d9276880 [ccplugin] print_function
Julien Cristau <julien.cristau@logilab.fr>
parents: 11658
diff changeset
    29
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    30
import atexit
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    31
import errno
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    32
import os
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    33
import signal
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    34
import sys
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    35
import time
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    36
import threading
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    37
import subprocess
12003
5236ce988805 [pyramid] Drop call to repository's start_looping_tasks method and warn about this
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11967
diff changeset
    38
import warnings
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    39
11867
c714e55fbce1 [cwctl] Kill deprecated ordered_instances method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11837
diff changeset
    40
from cubicweb import ExecutionError
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    41
from cubicweb.cwconfig import CubicWebConfiguration as cwcfg
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    42
from cubicweb.cwctl import CWCTL, InstanceCommand, init_cmdline_log_threshold
11681
b23d58050076 Merge cubicweb-pyramid cube
Yann Voté <yann.vote@logilab.fr>
parents: 11680
diff changeset
    43
from cubicweb.pyramid import wsgi_application_from_cwconfig
12053
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    44
from cubicweb.server import serverctl, set_debug
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    45
from cubicweb.web.webctl import WebCreateHandler
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    46
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    47
import waitress
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    48
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    49
MAXFD = 1024
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    50
11672
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
    51
DBG_FLAGS = ('RQL', 'SQL', 'REPO', 'HOOKS', 'OPS', 'SEC', 'MORE')
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
    52
LOG_LEVELS = ('debug', 'info', 'warning', 'error')
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    53
11680
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
    54
12053
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    55
class PyramidCreateHandler(serverctl.RepositoryCreateHandler,
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    56
                           WebCreateHandler):
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    57
    cfgname = 'pyramid'
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    58
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    59
    def bootstrap(self, cubes, automatic=False, inputlevel=0):
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    60
        serverctl.RepositoryCreateHandler.bootstrap(self, cubes, automatic, inputlevel)
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    61
        # Call WebCreateHandler.bootstrap to prompt about get anonymous-user.
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    62
        WebCreateHandler.bootstrap(self, cubes, automatic, inputlevel)
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    63
        self.config.write_development_ini(cubes)
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    64
c3c9f2e1424c [pyramid] Add a "pyramid" instance configuration type
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12003
diff changeset
    65
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    66
class PyramidStartHandler(InstanceCommand):
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    67
    """Start an interactive pyramid server.
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    68
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    69
    <instance>
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    70
      identifier of the instance to configure.
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    71
    """
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    72
    name = 'pyramid'
11814
ab8f652a9c99 [pyramid] Add action verb used in some messages displayed by the command
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11813
diff changeset
    73
    actionverb = 'started'
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    74
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    75
    options = (
11641
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    76
        ('no-daemon',
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    77
         {'action': 'store_true',
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    78
          'help': 'Run the server in the foreground.'}),
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    79
        ('debug-mode',
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    80
         {'action': 'store_true',
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    81
          'help': 'Activate the repository debug mode ('
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    82
                  'logs in the console and the debug toolbar).'
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    83
                  ' Implies --no-daemon'}),
11641
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    84
        ('debug',
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    85
         {'short': 'D', 'action': 'store_true',
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    86
          'help': 'Equals to "--debug-mode --no-daemon --reload"'}),
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    87
        ('reload',
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    88
         {'action': 'store_true',
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    89
          'help': 'Restart the server if any source file is changed'}),
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    90
        ('reload-interval',
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    91
         {'type': 'int', 'default': 1,
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    92
          'help': 'Interval, in seconds, between file modifications checks'}),
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    93
        ('loglevel',
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    94
         {'short': 'l', 'type': 'choice', 'metavar': '<log level>',
11672
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
    95
          'default': None, 'choices': LOG_LEVELS,
11680
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
    96
          'help': 'debug if -D is set, error otherwise; '
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
    97
                  'one of %s' % (LOG_LEVELS,),
11672
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
    98
          }),
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
    99
        ('dbglevel',
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
   100
         {'type': 'multiple_choice', 'metavar': '<dbg level>',
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
   101
          'default': None,
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
   102
          'choices': DBG_FLAGS,
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
   103
          'help': ('Set the server debugging flags; you may choose several '
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
   104
                   'values in %s; imply "debug" loglevel' % (DBG_FLAGS,)),
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   105
          }),
11648
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   106
        ('profile',
11652
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
   107
         {'action': 'store_true',
11648
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   108
          'default': False,
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   109
          'help': 'Enable profiling'}),
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   110
        ('profile-output',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   111
         {'type': 'string',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   112
          'default': None,
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   113
          'help': 'Profiling output file (default: "program.prof")'}),
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   114
        ('profile-dump-every',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   115
         {'type': 'int',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   116
          'default': None,
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   117
          'metavar': 'N',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   118
          'help': 'Dump profile stats to ouput every N requests '
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   119
                  '(default: 100)'}),
11813
8a04a2cb5ba4 [pyramid] No more need to check CW version since it's now shipped with it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   120
        ('param',
8a04a2cb5ba4 [pyramid] No more need to check CW version since it's now shipped with it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   121
         {'short': 'p',
8a04a2cb5ba4 [pyramid] No more need to check CW version since it's now shipped with it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   122
          'type': 'named',
8a04a2cb5ba4 [pyramid] No more need to check CW version since it's now shipped with it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   123
          'metavar': 'key1:value1,key2:value2',
8a04a2cb5ba4 [pyramid] No more need to check CW version since it's now shipped with it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   124
          'default': {},
8a04a2cb5ba4 [pyramid] No more need to check CW version since it's now shipped with it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11681
diff changeset
   125
          'help': 'override <key> configuration file option with <value>.'}),
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   126
    )
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   127
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   128
    _reloader_environ_key = 'CW_RELOADER_SHOULD_RUN'
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   129
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   130
    def debug(self, msg):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   131
        print('DEBUG - %s' % msg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   132
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   133
    def info(self, msg):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   134
        print('INFO - %s' % msg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   135
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   136
    def quote_first_command_arg(self, arg):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   137
        """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   138
        There's a bug in Windows when running an executable that's
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   139
        located inside a path with a space in it.  This method handles
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   140
        that case, or on non-Windows systems or an executable with no
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   141
        spaces, it just leaves well enough alone.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   142
        """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   143
        if (sys.platform != 'win32' or ' ' not in arg):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   144
            # Problem does not apply:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   145
            return arg
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   146
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   147
            import win32api
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   148
        except ImportError:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   149
            raise ValueError(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   150
                "The executable %r contains a space, and in order to "
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   151
                "handle this issue you must have the win32api module "
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   152
                "installed" % arg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   153
        arg = win32api.GetShortPathName(arg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   154
        return arg
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   155
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   156
    def _remove_pid_file(self, written_pid, filename):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   157
        current_pid = os.getpid()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   158
        if written_pid != current_pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   159
            # A forked process must be exiting, not the process that
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   160
            # wrote the PID file
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   161
            return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   162
        if not os.path.exists(filename):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   163
            return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   164
        with open(filename) as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   165
            content = f.read().strip()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   166
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   167
            pid_in_file = int(content)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   168
        except ValueError:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   169
            pass
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   170
        else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   171
            if pid_in_file != current_pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   172
                msg = "PID file %s contains %s, not expected PID %s"
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   173
                self.out(msg % (filename, pid_in_file, current_pid))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   174
                return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   175
        self.info("Removing PID file %s" % filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   176
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   177
            os.unlink(filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   178
            return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   179
        except OSError as e:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   180
            # Record, but don't give traceback
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   181
            self.out("Cannot remove PID file: (%s)" % e)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   182
        # well, at least lets not leave the invalid PID around...
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   183
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   184
            with open(filename, 'w') as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   185
                f.write('')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   186
        except OSError as e:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   187
            self.out('Stale PID left in file: %s (%s)' % (filename, e))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   188
        else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   189
            self.out('Stale PID removed')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   190
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   191
    def record_pid(self, pid_file):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   192
        pid = os.getpid()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   193
        self.debug('Writing PID %s to %s' % (pid, pid_file))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   194
        with open(pid_file, 'w') as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   195
            f.write(str(pid))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   196
        atexit.register(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   197
            self._remove_pid_file, pid, pid_file)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   198
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   199
    def daemonize(self, pid_file):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   200
        pid = live_pidfile(pid_file)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   201
        if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   202
            raise ExecutionError(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   203
                "Daemon is already running (PID: %s from PID file %s)"
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   204
                % (pid, pid_file))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   205
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   206
        self.debug('Entering daemon mode')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   207
        pid = os.fork()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   208
        if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   209
            # The forked process also has a handle on resources, so we
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   210
            # *don't* want proper termination of the process, we just
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   211
            # want to exit quick (which os._exit() does)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   212
            os._exit(0)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   213
        # Make this the session leader
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   214
        os.setsid()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   215
        # Fork again for good measure!
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   216
        pid = os.fork()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   217
        if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   218
            os._exit(0)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   219
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   220
        # @@: Should we set the umask and cwd now?
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   221
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   222
        import resource  # Resource usage information.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   223
        maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   224
        if (maxfd == resource.RLIM_INFINITY):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   225
            maxfd = MAXFD
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   226
        # Iterate through and close all file descriptors.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   227
        for fd in range(0, maxfd):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   228
            try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   229
                os.close(fd)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   230
            except OSError:  # ERROR, fd wasn't open to begin with (ignored)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   231
                pass
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   232
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   233
        if (hasattr(os, "devnull")):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   234
            REDIRECT_TO = os.devnull
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   235
        else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   236
            REDIRECT_TO = "/dev/null"
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   237
        os.open(REDIRECT_TO, os.O_RDWR)  # standard input (0)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   238
        # Duplicate standard input to standard output and standard error.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   239
        os.dup2(0, 1)  # standard output (1)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   240
        os.dup2(0, 2)  # standard error (2)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   241
11817
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   242
    def restart_with_reloader(self, filelist_path):
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   243
        self.debug('Starting subprocess with file monitor')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   244
11817
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   245
        # Create or clear monitored files list file.
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   246
        with open(filelist_path, 'w') as f:
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   247
            pass
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   248
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   249
        while True:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   250
            args = [self.quote_first_command_arg(sys.executable)] + sys.argv
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   251
            new_environ = os.environ.copy()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   252
            new_environ[self._reloader_environ_key] = 'true'
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   253
            proc = None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   254
            try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   255
                try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   256
                    proc = subprocess.Popen(args, env=new_environ)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   257
                    exit_code = proc.wait()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   258
                    proc = None
11663
6fb9d9276880 [ccplugin] print_function
Julien Cristau <julien.cristau@logilab.fr>
parents: 11658
diff changeset
   259
                    print("Process exited with", exit_code)
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   260
                except KeyboardInterrupt:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   261
                    self.info('^C caught in monitor process')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   262
                    return 1
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   263
            finally:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   264
                if proc is not None:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   265
                    proc.terminate()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   266
                    self.info(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   267
                        'Waiting for the server to stop. Hit CTRL-C to exit')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   268
                    exit_code = proc.wait()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   269
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   270
            if exit_code != 3:
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   271
                with open(filelist_path) as f:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   272
                    filelist = [line.strip() for line in f]
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   273
                if filelist:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   274
                    self.info("Reloading failed. Waiting for a file to change")
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   275
                    mon = Monitor(extra_files=filelist, nomodules=True)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   276
                    while mon.check_reload():
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   277
                        time.sleep(1)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   278
                else:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   279
                    return exit_code
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   280
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   281
            self.info('%s %s %s' % ('-' * 20, 'Restarting', '-' * 20))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   282
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   283
    def set_needreload(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   284
        self._needreload = True
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   285
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   286
    def install_reloader(self, poll_interval, extra_files, filelist_path):
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   287
        mon = Monitor(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   288
            poll_interval=poll_interval, extra_files=extra_files,
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   289
            atexit=self.set_needreload, filelist_path=filelist_path)
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   290
        mon_thread = threading.Thread(target=mon.periodic_reload)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   291
        mon_thread.daemon = True
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   292
        mon_thread.start()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   293
11647
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   294
    def configfiles(self, cwconfig):
11679
04b127f7ba4e [ccplugin] docstring clarification
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11672
diff changeset
   295
        """Generate instance configuration filenames"""
11647
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   296
        yield cwconfig.main_config_file()
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   297
        for f in (
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   298
                'sources', 'logging.conf', 'pyramid.ini', 'pyramid-debug.ini'):
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   299
            f = os.path.join(cwconfig.apphome, f)
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   300
            if os.path.exists(f):
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   301
                yield f
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   302
11639
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   303
    def i18nfiles(self, cwconfig):
11647
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   304
        """Generate instance i18n files"""
11639
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   305
        i18ndir = os.path.join(cwconfig.apphome, 'i18n')
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   306
        if os.path.exists(i18ndir):
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   307
            for lang in cwconfig.available_languages():
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   308
                f = os.path.join(i18ndir, lang, 'LC_MESSAGES', 'cubicweb.mo')
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   309
                if os.path.exists(f):
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   310
                    yield f
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   311
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   312
    def pyramid_instance(self, appid):
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   313
        self._needreload = False
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   314
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   315
        debugmode = self['debug-mode'] or self['debug']
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   316
        autoreload = self['reload'] or self['debug']
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   317
        daemonize = not (self['no-daemon'] or debugmode or autoreload)
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   318
11817
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   319
        cwconfig = cwcfg.config_for(appid, debugmode=debugmode)
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   320
        filelist_path = os.path.join(cwconfig.apphome,
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   321
                                     '.pyramid-reload-files.list')
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   322
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   323
        if autoreload and not os.environ.get(self._reloader_environ_key):
11817
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   324
            return self.restart_with_reloader(filelist_path)
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   325
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   326
        if autoreload:
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   327
            _turn_sigterm_into_systemexit()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   328
            self.debug('Running reloading file monitor')
11647
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   329
            extra_files = [sys.argv[0]]
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   330
            extra_files.extend(self.configfiles(cwconfig))
11639
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   331
            extra_files.extend(self.i18nfiles(cwconfig))
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   332
            self.install_reloader(
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   333
                self['reload-interval'], extra_files,
11817
48f6ebd33cb9 [pyramid] Install file listing monitored files in application home
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11814
diff changeset
   334
                filelist_path=filelist_path)
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   335
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   336
        if daemonize:
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   337
            self.daemonize(cwconfig['pid-file'])
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   338
            self.record_pid(cwconfig['pid-file'])
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   339
11672
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
   340
        if self['dbglevel']:
2018cdf2909e [cc] add a dbglevel cmdline option to specify the DBG_XXX flags to set
David Douard <david.douard@logilab.fr>
parents: 11664
diff changeset
   341
            self['loglevel'] = 'debug'
11680
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
   342
            set_debug('|'.join('DBG_' + x.upper() for x in self['dbglevel']))
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   343
        init_cmdline_log_threshold(cwconfig, self['loglevel'])
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   344
11648
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   345
        app = wsgi_application_from_cwconfig(
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   346
            cwconfig, profile=self['profile'],
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   347
            profile_output=self['profile-output'],
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   348
            profile_dump_every=self['profile-dump-every']
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   349
        )
11640
e45e4999dc98 Use 'wsgicors' for CORS handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11639
diff changeset
   350
11652
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
   351
        host = cwconfig['interface']
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
   352
        port = cwconfig['port'] or 8080
12216
4de5927871f9 [pyramid] set waitress url_scheme to https when base-url scheme is https
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12053
diff changeset
   353
        url_scheme = ('https' if cwconfig['base-url'].startswith('https')
4de5927871f9 [pyramid] set waitress url_scheme to https when base-url scheme is https
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12053
diff changeset
   354
                      else 'http')
11664
7567e99d6ed5 [ccplugin] get the cw repo from the wsgi app
Julien Cristau <julien.cristau@logilab.fr>
parents: 11663
diff changeset
   355
        repo = app.application.registry['cubicweb.repository']
12003
5236ce988805 [pyramid] Drop call to repository's start_looping_tasks method and warn about this
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11967
diff changeset
   356
        warnings.warn(
5236ce988805 [pyramid] Drop call to repository's start_looping_tasks method and warn about this
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11967
diff changeset
   357
            'the "pyramid" command does not start repository "looping tasks" '
5236ce988805 [pyramid] Drop call to repository's start_looping_tasks method and warn about this
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11967
diff changeset
   358
            'anymore; use the standalone "scheduler" command if needed'
5236ce988805 [pyramid] Drop call to repository's start_looping_tasks method and warn about this
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11967
diff changeset
   359
        )
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   360
        try:
12216
4de5927871f9 [pyramid] set waitress url_scheme to https when base-url scheme is https
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12053
diff changeset
   361
            waitress.serve(app, host=host, port=port, url_scheme=url_scheme)
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   362
        finally:
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   363
            repo.shutdown()
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   364
        if self._needreload:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   365
            return 3
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   366
        return 0
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   367
11821
7534b32c45e3 Fix (new) flake8 errors
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11817
diff changeset
   368
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   369
CWCTL.register(PyramidStartHandler)
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   370
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   371
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   372
def live_pidfile(pidfile):  # pragma: no cover
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   373
    """(pidfile:str) -> int | None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   374
    Returns an int found in the named file, if there is one,
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   375
    and if there is a running process with that process id.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   376
    Return None if no such process exists.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   377
    """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   378
    pid = read_pidfile(pidfile)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   379
    if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   380
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   381
            os.kill(int(pid), 0)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   382
            return pid
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   383
        except OSError as e:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   384
            if e.errno == errno.EPERM:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   385
                return pid
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   386
    return None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   387
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   388
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   389
def read_pidfile(filename):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   390
    if os.path.exists(filename):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   391
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   392
            with open(filename) as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   393
                content = f.read()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   394
            return int(content.strip())
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   395
        except (ValueError, IOError):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   396
            return None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   397
    else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   398
        return None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   399
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   400
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   401
def _turn_sigterm_into_systemexit():
11680
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
   402
    """Attempts to turn a SIGTERM exception into a SystemExit exception."""
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   403
    try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   404
        import signal
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   405
    except ImportError:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   406
        return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   407
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   408
    def handle_term(signo, frame):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   409
        raise SystemExit
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   410
    signal.signal(signal.SIGTERM, handle_term)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   411
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   412
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   413
class Monitor(object):
11680
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
   414
    """A file monitor and server stopper.
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   415
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   416
    It is a simplified version of pyramid pserve.Monitor, with little changes:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   417
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   418
    -   The constructor takes extra_files, atexit, nomodules and filelist_path
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   419
    -   The process is stopped by auto-kill with signal SIGTERM
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   420
    """
11680
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
   421
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   422
    def __init__(self, poll_interval=1, extra_files=[], atexit=None,
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   423
                 nomodules=False, filelist_path=None):
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   424
        self.module_mtimes = {}
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   425
        self.keep_running = True
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   426
        self.poll_interval = poll_interval
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   427
        self.extra_files = extra_files
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   428
        self.atexit = atexit
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   429
        self.nomodules = nomodules
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   430
        self.filelist_path = filelist_path
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   431
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   432
    def _exit(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   433
        if self.atexit:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   434
            self.atexit()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   435
        os.kill(os.getpid(), signal.SIGTERM)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   436
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   437
    def periodic_reload(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   438
        while True:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   439
            if not self.check_reload():
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   440
                self._exit()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   441
                break
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   442
            time.sleep(self.poll_interval)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   443
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   444
    def check_reload(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   445
        filenames = list(self.extra_files)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   446
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   447
        if not self.nomodules:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   448
            for module in list(sys.modules.values()):
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   449
                try:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   450
                    filename = module.__file__
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   451
                except (AttributeError, ImportError):
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   452
                    continue
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   453
                if filename is not None:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   454
                    filenames.append(filename)
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   455
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   456
        for filename in filenames:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   457
            try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   458
                stat = os.stat(filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   459
                if stat:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   460
                    mtime = stat.st_mtime
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   461
                else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   462
                    mtime = 0
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   463
            except (OSError, IOError):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   464
                continue
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   465
            if filename.endswith('.pyc') and os.path.exists(filename[:-1]):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   466
                mtime = max(os.stat(filename[:-1]).st_mtime, mtime)
11680
e1caf133b81c [ccplugin] flake8
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 11679
diff changeset
   467
            if filename not in self.module_mtimes:
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   468
                self.module_mtimes[filename] = mtime
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   469
            elif self.module_mtimes[filename] < mtime:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   470
                print('%s changed; reloading...' % filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   471
                return False
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   472
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   473
        if self.filelist_path:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   474
            with open(self.filelist_path) as f:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   475
                filelist = set((line.strip() for line in f))
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   476
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   477
            filelist.update(filenames)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   478
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   479
            with open(self.filelist_path, 'w') as f:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   480
                for filename in filelist:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   481
                    f.write('%s\n' % filename)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   482
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   483
        return True