ccplugin.py
author David Douard <david.douard@logilab.fr>
Thu, 23 Jul 2015 16:59:46 +0200
changeset 11658 a63023a8d457
parent 11652 e95725d7ce90
child 11663 6fb9d9276880
permissions -rw-r--r--
[ccplugin] fix a bug introduced in e95725d7ce90 (closes #5731783)
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):
11658
a63023a8d457 [ccplugin] fix a bug introduced in e95725d7ce90 (closes #5731783)
David Douard <david.douard@logilab.fr>
parents: 11652
diff changeset
    77
        options = options + (
11652
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