ccplugin.py
author David Douard <david.douard@logilab.fr>
Thu, 25 Jun 2015 22:57:15 +0200
changeset 11652 e95725d7ce90
parent 11648 9a112017974a
child 11658 a63023a8d457
permissions -rw-r--r--
Allow to override config file options by cmdline arguments (closes #5724484) For the sake of consistency with cw, the 'profile' option's short name has been removed, so we can use the lower 'p' for this purpose (for consistency with cubicweb). Requires CubicWeb 3.21 to work.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
     1
"""
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
     2
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
     3
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
     4
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
     5
the pyramid script 'pserve'.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
     6
"""
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
     7
import atexit
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
     8
import errno
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
     9
import os
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    10
import signal
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    11
import sys
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
    12
import tempfile
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    13
import time
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    14
import threading
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    15
import subprocess
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    16
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    17
from cubicweb import BadCommandUsage, ExecutionError
11652
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    18
from cubicweb.__pkginfo__ import numversion as cwversion
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    19
from cubicweb.cwconfig import CubicWebConfiguration as cwcfg
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    20
from cubicweb.cwctl import CWCTL, InstanceCommand, init_cmdline_log_threshold
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    21
11644
41bd2b316228 Move the cors middleware initialisation to pyramid-cubicweb to reduce code duplication
Christophe de Vienne <christophe@unlish.com>
parents: 11641
diff changeset
    22
from pyramid_cubicweb import wsgi_application_from_cwconfig
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    23
import waitress
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    24
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    25
MAXFD = 1024
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    26
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    27
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    28
class PyramidStartHandler(InstanceCommand):
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    29
    """Start an interactive pyramid server.
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    30
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    31
    This command requires http://hg.logilab.org/review/pyramid_cubicweb/
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    32
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    33
    <instance>
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    34
      identifier of the instance to configure.
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    35
    """
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    36
    name = 'pyramid'
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    37
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    38
    options = (
11641
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    39
        ('no-daemon',
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    40
         {'action': 'store_true',
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    41
          '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
    42
        ('debug-mode',
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    43
         {'action': 'store_true',
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    44
          'help': 'Activate the repository debug mode ('
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    45
                  '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
    46
                  ' Implies --no-daemon'}),
11641
3d4e7be2e3c3 Add a --no-daemon option
Christophe de Vienne <christophe@unlish.com>
parents: 11640
diff changeset
    47
        ('debug',
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    48
         {'short': 'D', 'action': 'store_true',
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    49
          '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
    50
        ('reload',
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    51
         {'action': 'store_true',
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    52
          '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
    53
        ('reload-interval',
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    54
         {'type': 'int', 'default': 1,
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    55
          'help': 'Interval, in seconds, between file modifications checks'}),
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    56
        ('loglevel',
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    57
         {'short': 'l', 'type': 'choice', 'metavar': '<log level>',
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    58
          'default': None, 'choices': ('debug', 'info', 'warning', 'error'),
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    59
          'help': 'debug if -D is set, error otherwise',
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    60
          }),
11648
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    61
        ('profile',
11652
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    62
         {'action': 'store_true',
11648
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    63
          'default': False,
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    64
          'help': 'Enable profiling'}),
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    65
        ('profile-output',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    66
         {'type': 'string',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    67
          'default': None,
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    68
          'help': 'Profiling output file (default: "program.prof")'}),
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    69
        ('profile-dump-every',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    70
         {'type': 'int',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    71
          'default': None,
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    72
          'metavar': 'N',
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    73
          'help': 'Dump profile stats to ouput every N requests '
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
    74
                  '(default: 100)'}),
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    75
    )
11652
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    76
    if cwversion >= (3, 21, 0):
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    77
        options = PyramidStartHandler.options + (
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    78
        ('param',
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    79
         {'short': 'p', 'type': 'named', 'metavar': 'key1:value1,key2:value2',
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    80
          'default': {},
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    81
          'help': 'override <key> configuration file option with <value>.',
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    82
         }),
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
    83
        )
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
    84
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    85
    _reloader_environ_key = 'CW_RELOADER_SHOULD_RUN'
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
    86
    _reloader_filelist_environ_key = 'CW_RELOADER_FILELIST'
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    87
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    88
    def debug(self, msg):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    89
        print('DEBUG - %s' % msg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    90
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    91
    def info(self, msg):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    92
        print('INFO - %s' % msg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    93
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    94
    def ordered_instances(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    95
        instances = super(PyramidStartHandler, self).ordered_instances()
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    96
        if (self['debug-mode'] or self['debug'] or self['reload']) \
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    97
                and len(instances) > 1:
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
    98
            raise BadCommandUsage(
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
    99
                '--debug-mode, --debug and --reload can be used on a single '
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   100
                'instance only')
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   101
        return instances
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   102
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   103
    def quote_first_command_arg(self, arg):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   104
        """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   105
        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
   106
        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
   107
        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
   108
        spaces, it just leaves well enough alone.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   109
        """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   110
        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
   111
            # Problem does not apply:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   112
            return arg
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   113
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   114
            import win32api
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   115
        except ImportError:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   116
            raise ValueError(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   117
                "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
   118
                "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
   119
                "installed" % arg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   120
        arg = win32api.GetShortPathName(arg)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   121
        return arg
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   122
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   123
    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
   124
        current_pid = os.getpid()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   125
        if written_pid != current_pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   126
            # 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
   127
            # wrote the PID file
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   128
            return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   129
        if not os.path.exists(filename):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   130
            return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   131
        with open(filename) as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   132
            content = f.read().strip()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   133
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   134
            pid_in_file = int(content)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   135
        except ValueError:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   136
            pass
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   137
        else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   138
            if pid_in_file != current_pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   139
                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
   140
                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
   141
                return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   142
        self.info("Removing PID file %s" % filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   143
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   144
            os.unlink(filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   145
            return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   146
        except OSError as e:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   147
            # Record, but don't give traceback
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   148
            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
   149
        # 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
   150
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   151
            with open(filename, 'w') as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   152
                f.write('')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   153
        except OSError as e:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   154
            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
   155
        else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   156
            self.out('Stale PID removed')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   157
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   158
    def record_pid(self, pid_file):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   159
        pid = os.getpid()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   160
        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
   161
        with open(pid_file, 'w') as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   162
            f.write(str(pid))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   163
        atexit.register(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   164
            self._remove_pid_file, pid, pid_file)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   165
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   166
    def daemonize(self, pid_file):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   167
        pid = live_pidfile(pid_file)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   168
        if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   169
            raise ExecutionError(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   170
                "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
   171
                % (pid, pid_file))
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   172
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   173
        self.debug('Entering daemon mode')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   174
        pid = os.fork()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   175
        if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   176
            # 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
   177
            # *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
   178
            # 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
   179
            os._exit(0)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   180
        # Make this the session leader
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   181
        os.setsid()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   182
        # Fork again for good measure!
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   183
        pid = os.fork()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   184
        if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   185
            os._exit(0)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   186
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   187
        # @@: 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
   188
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   189
        import resource  # Resource usage information.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   190
        maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   191
        if (maxfd == resource.RLIM_INFINITY):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   192
            maxfd = MAXFD
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   193
        # Iterate through and close all file descriptors.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   194
        for fd in range(0, maxfd):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   195
            try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   196
                os.close(fd)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   197
            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
   198
                pass
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   199
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   200
        if (hasattr(os, "devnull")):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   201
            REDIRECT_TO = os.devnull
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   202
        else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   203
            REDIRECT_TO = "/dev/null"
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   204
        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
   205
        # 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
   206
        os.dup2(0, 1)  # standard output (1)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   207
        os.dup2(0, 2)  # standard error (2)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   208
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   209
    def restart_with_reloader(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   210
        self.debug('Starting subprocess with file monitor')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   211
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   212
        with tempfile.NamedTemporaryFile(delete=False) as f:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   213
            filelist_path = f.name
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   214
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   215
        while True:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   216
            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
   217
            new_environ = os.environ.copy()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   218
            new_environ[self._reloader_environ_key] = 'true'
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   219
            new_environ[self._reloader_filelist_environ_key] = filelist_path
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   220
            proc = None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   221
            try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   222
                try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   223
                    proc = subprocess.Popen(args, env=new_environ)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   224
                    exit_code = proc.wait()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   225
                    proc = None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   226
                    print "Process exited with ", exit_code
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   227
                except KeyboardInterrupt:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   228
                    self.info('^C caught in monitor process')
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   229
                    return 1
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   230
            finally:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   231
                if proc is not None:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   232
                    proc.terminate()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   233
                    self.info(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   234
                        '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
   235
                    exit_code = proc.wait()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   236
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   237
            if exit_code != 3:
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   238
                with open(filelist_path) as f:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   239
                    filelist = [line.strip() for line in f]
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   240
                if filelist:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   241
                    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
   242
                    mon = Monitor(extra_files=filelist, nomodules=True)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   243
                    while mon.check_reload():
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   244
                        time.sleep(1)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   245
                else:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   246
                    return exit_code
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   247
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   248
            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
   249
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   250
    def set_needreload(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   251
        self._needreload = True
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   252
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   253
    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
   254
        mon = Monitor(
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   255
            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
   256
            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
   257
        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
   258
        mon_thread.daemon = True
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   259
        mon_thread.start()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   260
11647
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   261
    def configfiles(self, cwconfig):
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   262
        """Generate instance configuration files"""
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   263
        yield cwconfig.main_config_file()
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   264
        for f in (
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   265
                'sources', 'logging.conf', 'pyramid.ini', 'pyramid-debug.ini'):
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   266
            f = os.path.join(cwconfig.apphome, f)
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   267
            if os.path.exists(f):
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   268
                yield f
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   269
11639
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   270
    def i18nfiles(self, cwconfig):
11647
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   271
        """Generate instance i18n files"""
11639
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   272
        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
   273
        if os.path.exists(i18ndir):
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   274
            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
   275
                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
   276
                if os.path.exists(f):
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   277
                    yield f
f38ec5e29de3 Watch for i18n files changes for auto-reload
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11638
diff changeset
   278
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   279
    def pyramid_instance(self, appid):
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   280
        self._needreload = False
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   281
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   282
        debugmode = self['debug-mode'] or self['debug']
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   283
        autoreload = self['reload'] or self['debug']
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   284
        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
   285
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   286
        if autoreload and not os.environ.get(self._reloader_environ_key):
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   287
            return self.restart_with_reloader()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   288
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   289
        cwconfig = cwcfg.config_for(appid, debugmode=debugmode)
11652
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
   290
        if cwversion >= (3, 21, 0):
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
   291
            cwconfig.cmdline_options = self.config.param
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   292
        if autoreload:
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   293
            _turn_sigterm_into_systemexit()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   294
            self.debug('Running reloading file monitor')
11647
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   295
            extra_files = [sys.argv[0]]
7f2cfe9f79cb Monitor more configuration files
Christophe de Vienne <christophe@unlish.com>
parents: 11645
diff changeset
   296
            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
   297
            extra_files.extend(self.i18nfiles(cwconfig))
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   298
            self.install_reloader(
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   299
                self['reload-interval'], extra_files,
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   300
                filelist_path=os.environ.get(
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   301
                    self._reloader_filelist_environ_key))
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   302
11645
2a949974002d --debug now activates all debug options
Christophe de Vienne <christophe@unlish.com>
parents: 11644
diff changeset
   303
        if daemonize:
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   304
            self.daemonize(cwconfig['pid-file'])
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   305
            self.record_pid(cwconfig['pid-file'])
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   306
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   307
        init_cmdline_log_threshold(cwconfig, self['loglevel'])
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   308
11648
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   309
        app = wsgi_application_from_cwconfig(
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   310
            cwconfig, profile=self['profile'],
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   311
            profile_output=self['profile-output'],
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   312
            profile_dump_every=self['profile-dump-every']
9a112017974a Add profiling options
Christophe de Vienne <christophe@unlish.com>
parents: 11647
diff changeset
   313
        )
11640
e45e4999dc98 Use 'wsgicors' for CORS handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11639
diff changeset
   314
11652
e95725d7ce90 Allow to override config file options by cmdline arguments (closes #5724484)
David Douard <david.douard@logilab.fr>
parents: 11648
diff changeset
   315
        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
   316
        port = cwconfig['port'] or 8080
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   317
        repo = cwconfig.repository()
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   318
        try:
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   319
            repo.start_looping_tasks()
11640
e45e4999dc98 Use 'wsgicors' for CORS handling.
Christophe de Vienne <christophe@unlish.com>
parents: 11639
diff changeset
   320
            waitress.serve(app, host=host, port=port)
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   321
        finally:
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   322
            repo.shutdown()
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   323
        if self._needreload:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   324
            return 3
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   325
        return 0
11633
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   326
ffe4040cf4a2 Implements the 'pyramid' command.
Christophe de Vienne <christophe@unlish.com>
parents:
diff changeset
   327
CWCTL.register(PyramidStartHandler)
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   328
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   329
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   330
def live_pidfile(pidfile):  # pragma: no cover
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   331
    """(pidfile:str) -> int | None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   332
    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
   333
    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
   334
    Return None if no such process exists.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   335
    """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   336
    pid = read_pidfile(pidfile)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   337
    if pid:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   338
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   339
            os.kill(int(pid), 0)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   340
            return pid
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   341
        except OSError as e:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   342
            if e.errno == errno.EPERM:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   343
                return pid
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   344
    return None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   345
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   346
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   347
def read_pidfile(filename):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   348
    if os.path.exists(filename):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   349
        try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   350
            with open(filename) as f:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   351
                content = f.read()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   352
            return int(content.strip())
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   353
        except (ValueError, IOError):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   354
            return None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   355
    else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   356
        return None
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   357
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   358
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   359
def _turn_sigterm_into_systemexit():
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   360
    """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   361
    Attempts to turn a SIGTERM exception into a SystemExit exception.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   362
    """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   363
    try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   364
        import signal
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   365
    except ImportError:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   366
        return
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   367
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   368
    def handle_term(signo, frame):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   369
        raise SystemExit
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   370
    signal.signal(signal.SIGTERM, handle_term)
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
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   373
class Monitor(object):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   374
    """
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   375
    A file monitor and server stopper.
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   376
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   377
    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
   378
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   379
    -   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
   380
    -   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
   381
    """
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   382
    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
   383
                 nomodules=False, filelist_path=None):
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   384
        self.module_mtimes = {}
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   385
        self.keep_running = True
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   386
        self.poll_interval = poll_interval
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   387
        self.extra_files = extra_files
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   388
        self.atexit = atexit
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   389
        self.nomodules = nomodules
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   390
        self.filelist_path = filelist_path
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   391
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   392
    def _exit(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   393
        if self.atexit:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   394
            self.atexit()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   395
        os.kill(os.getpid(), signal.SIGTERM)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   396
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   397
    def periodic_reload(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   398
        while True:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   399
            if not self.check_reload():
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   400
                self._exit()
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   401
                break
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   402
            time.sleep(self.poll_interval)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   403
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   404
    def check_reload(self):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   405
        filenames = list(self.extra_files)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   406
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   407
        if not self.nomodules:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   408
            for module in list(sys.modules.values()):
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   409
                try:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   410
                    filename = module.__file__
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   411
                except (AttributeError, ImportError):
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   412
                    continue
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   413
                if filename is not None:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   414
                    filenames.append(filename)
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
        for filename in filenames:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   417
            try:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   418
                stat = os.stat(filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   419
                if stat:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   420
                    mtime = stat.st_mtime
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   421
                else:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   422
                    mtime = 0
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   423
            except (OSError, IOError):
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   424
                continue
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   425
            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
   426
                mtime = max(os.stat(filename[:-1]).st_mtime, mtime)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   427
            if not filename in self.module_mtimes:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   428
                self.module_mtimes[filename] = mtime
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   429
            elif self.module_mtimes[filename] < mtime:
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   430
                print('%s changed; reloading...' % filename)
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   431
                return False
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   432
11638
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   433
        if self.filelist_path:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   434
            with open(self.filelist_path) as f:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   435
                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
   436
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   437
            filelist.update(filenames)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   438
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   439
            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
   440
                for filename in filelist:
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   441
                    f.write('%s\n' % filename)
12de153c0d0e Auto-reload now survives failed reload
Christophe de Vienne <christophe@unlish.com>
parents: 11637
diff changeset
   442
11637
a9cde6a3394c Implements auto-reload and daemon mode.
Christophe de Vienne <christophe@unlish.com>
parents: 11633
diff changeset
   443
        return True