forked from teepark/reconfig
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreconfig.py
78 lines (61 loc) · 2.16 KB
/
reconfig.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# vim: fileencoding=utf8:et:sw=4:ts=8:sts=4
import signal
import yaml
try:
from yaml import CSafeLoader as SafeLoader
except ImportError:
from yaml import SafeLoader
ADDED = 1
MODIFIED = 2
REMOVED = 3
class Config(object):
def __init__(self, filepath, sig=signal.SIGUSR1):
self._filepath = filepath
self._signal = sig
self._loaded = False
self._data = {}
self._watchers = {}
def load(self):
with open(self._filepath, 'r') as fp:
raw = fp.read()
newconfig = yaml.load(raw, Loader=SafeLoader)
oldconfig = self._data.copy()
for name, value in newconfig.iteritems():
self._set(name, value)
for name, value in oldconfig.iteritems():
if name not in newconfig:
del self._data[name]
for watcher in self._watchers.get(name, []):
watcher(name, value, None, REMOVED)
if not self._loaded and self._signal is not None:
signal.signal(self._signal, self._sighandler)
self._loaded = True
def get(self, name, default=None):
return self._data.get(name, default)
__getitem__ = get
def watch(self, name, handler=None):
if handler is None:
# support @conf.watch(name) decorator usage
return lambda h: self.watch(name, h)
self._watchers.setdefault(name, []).append(handler)
def unwatch(self, name, handler):
for i, watch in enumerate(self._watchers.get(name, [])):
if watch is handler:
self._watchers[name].pop(i)
return True
return False
def _sighandler(self, signum, frame):
self.load()
def _set(self, name, value):
was_present = False
old = None
if name in self._data:
was_present = True
old = self._data[name]
self._data[name] = value
if not was_present:
for watcher in self._watchers.get(name, []):
watcher(name, None, value, ADDED)
elif old != value:
for watcher in self._watchers.get(name, []):
watcher(name, old, value, MODIFIED)