-
Notifications
You must be signed in to change notification settings - Fork 0
/
json_backed_dict.py
74 lines (63 loc) · 2.34 KB
/
json_backed_dict.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
import os, shutil, json, tempfile
class JSONBackedDict(dict):
"""
inherits from dict but only supports bare init (can not populate dict at init)
rewrites the json backing with every setitem
"""
def __init__(self, filename="", encoder=None):
dict.__init__(self)
self.filename = filename
self.encoder = encoder
if os.path.exists(self.filename):
self._read()
else:
self._write()
def _write(self):
fd_out, fd_out_name = tempfile.mkstemp()
fd_in_name = self.filename
with os.fdopen(fd_out, "w") as outfile:
outfile.write(json.dumps(self, cls=self.encoder))
# then rename the temporary file to the backing file name...
shutil.move(fd_out_name, fd_in_name)
def _read(self, overwrite=True):
if overwrite:
self.clear()
with open(self.filename, "r") as f:
self.update(json.loads(f.read()))
def __getitem__(self, key):
# convert on retrieve:
value = dict.__getitem__(self, key)
if isinstance(value, dict) and not isinstance(value, JSONBackedSubDict):
value = JSONBackedSubDict(self, input_dict=value)
self[key] = value
return value
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
self._write()
def update(self, *args, **kwargs):
if args:
if len(args) > 1:
raise TypeError("update expected at most 1 arguments, "
"got %d" % len(args))
other = dict(args[0])
for key in other:
self[key] = other[key]
for key in kwargs:
self[key] = kwargs[key]
def setdefault(self, *args, **kw):
dict.setdefault(self, *args, **kw)
self._write()
def __delitem__(self, key):
dict.__delitem__(self, key)
self._write()
def pop(self, *args, **kw):
val = dict.pop(self, *args, **kw)
self._write()
return val
class JSONBackedSubDict(JSONBackedDict):
def __init__(self, root_dict, input_dict=None):
input_dict = input_dict or {}
dict.__init__(self, input_dict)
self.root_dict = root_dict
def _write(self):
self.root_dict._write()