1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18 Autoreload of python code
19 =========================
20
21 This module provides logic to implemented the autoreload mechanism. This is
22 implemented by forking early, remembering the module's mtimes and dealing
23 with changed mtimes by going back right before the fork point.
24 """
25 __author__ = u"Andr\xe9 Malo"
26 __docformat__ = "restructuredtext en"
27
28 import os as _os
29 import sys as _sys
30 import time as _time
31
32
34 """
35 Reload requested exception
36
37 :CVariables:
38 - `CODE`: Exit code for the child process
39
40 :Types:
41 - `CODE`: ``int``
42 """
43 CODE = 9
44
46 """ Initialization """
47 SystemExit.__init__(self, self.CODE)
48
49
51 """ Autoreload logic container """
52 _check_mtime, _before = None, None
53
55 """
56 Initialization
57
58 :Parameters:
59 - `config`: Configuration
60 - `opts`: Command line options
61 - `args`: Positioned command line arguments
62
63 :Types:
64 - `config`: `wtf.config.Config`
65 - `opts`: ``optparse.OptionContainer``
66 - `args`: ``list``
67 """
68 autoreload = config.wtf('autoreload', False)
69 if autoreload:
70 self._check_mtime = _time.time()
71 self._before = set(_sys.modules.iterkeys())
72 self.check = self._check
73 else:
74 self.check = lambda: ()
75
77 """
78 Check the need of reloading in case autoreload has been turned on
79
80 This method takes a snapshot of the current sys.modules, mtimes
81 are compared with an older snapshot and on differences true is
82 returned. False otherwise.
83
84 :return: Names of the changed modules (empty if nothing's changed)
85 :rtype: ``iterable``
86 """
87 check_mtime, changed = _time.time(), []
88 for name, mod in _sys.modules.items():
89 if mod is None or name in self._before:
90 continue
91 mtime = self._mtime(mod)
92 if mtime is None:
93 continue
94 if mtime > self._check_mtime:
95 changed.append(name)
96 self._check_mtime = check_mtime
97 return changed
98
100 """
101 Determine the mtime of a module
102
103 :Parameters:
104 - `mod`: The module to inspect
105
106 :Types:
107 - `mod`: ``module``
108
109 :return: The mtime or ``None`` if it couldn't be determined (``float``
110 or ``int``, depending on the ``os.stat_float_times`` setting)
111 :rtype: number
112 """
113 filename = getattr(mod, '__file__', None)
114 if filename is not None:
115 try:
116 if filename.endswith('.pyo') or filename.endswith('.pyc'):
117 newname = filename[:-1]
118 return _os.stat(newname).st_mtime
119 raise OSError()
120 except OSError:
121 try:
122 return _os.stat(filename).st_mtime
123 except OSError:
124 pass
125 return None
126