ya2 · news · projects · code · about

removed uml diagrams
[pmachines.git] / ya2 / dictfile.py
1 import sys
2 from logging import info
3 from os import makedirs
4 from os.path import dirname
5 from collections.abc import Mapping
6 from configparser import ConfigParser
7 from json import load, dumps
8 from ya2.gameobject import GameObject
9 from ya2.lib.p3d.p3d import LibP3d
10
11
12 class DctFile(GameObject):
13
14 def __init__(self, fpath, default_dct=None, persistent=True):
15 GameObject.__init__(self)
16 default_dct = default_dct or {}
17 if sys.platform == 'darwin' and LibP3d.runtime():
18 fpath = dirname(__file__) + '/' + fpath
19 self.fpath = fpath
20 self.persistent = persistent
21 try:
22 #with open(fpath) as json: fdct = load(json)
23 config = ConfigParser()
24 config.read(fpath)
25 fdct = {section: dict(config.items(section)) for section in config.sections()}
26 fdct = self.__typed_dct(fdct)
27 self.dct = self.__add_default(default_dct, fdct)
28 except IOError: self.dct = default_dct
29
30 @staticmethod
31 def __typed_dct(dct):
32 def convert_single_val(val):
33 try: return int(val)
34 except ValueError:
35 try: return float(val)
36 except ValueError:
37 if not val or val[0] != '[':
38 return val
39 else:
40 raise ValueError
41 def converted(val):
42 try: return convert_single_val(val)
43 except ValueError:
44 return [elm.strip() for elm in val[1:-1].split(',')]
45 new_dct = {}
46 for section, sec_dct in dct.items():
47 for key, val in sec_dct.items():
48 if section not in new_dct:
49 new_dct[section] = {}
50 new_dct[section][key] = converted(val)
51 return new_dct
52
53 @staticmethod
54 def __add_default(dct, upd):
55 for key, val in upd.items():
56 if isinstance(val, Mapping):
57 dct[key] = DctFile.__add_default(dct.get(key, {}), val)
58 else: dct[key] = upd[key]
59 return dct
60
61 @staticmethod
62 def deepupdate(dct, new_dct):
63 for key, val in new_dct.items():
64 if isinstance(val, Mapping):
65 dct[key] = DctFile.deepupdate(dct.get(key, {}), val)
66 else: dct[key] = val
67 return dct
68
69 def store(self):
70 info('storing %s' % self.fpath)
71 if not self.persistent: return
72 #json_str = dumps(self.dct, sort_keys=True, indent=4,
73 # separators=(',', ': '))
74 #with open(self.fpath, 'w') as json: json.write(json_str)
75 fdct = {}
76 for section, sec_dct in self.dct.items():
77 if section not in fdct:
78 fdct[section] = {}
79 for key, val in sec_dct.items():
80 if type(val) == list:
81 fdct[section][key] = '[%s]' % ', '.join(val)
82 else:
83 fdct[section][key] = val
84 config = ConfigParser()
85 for key in self.dct:
86 config[key] = fdct[key]
87 if dirname(self.fpath):
88 makedirs(dirname(self.fpath), exist_ok=True)
89 with open(self.fpath, 'w') as ini_file:
90 config.write(ini_file)
91
92 def __getitem__(self, arg): return self.dct[arg]
93
94 def __setitem__(self, arg, val): self.dct[arg] = val
95
96 def __delitem__(self, arg): del self.dct[arg]