Mercurial > fife-parpg
comparison clients/editor/scripts/settings.py @ 255:51cc05d862f2
Merged editor_rewrite branch to trunk.
This contains changes that may break compatibility against existing clients.
For a list of changes that may affect your client, see: http://wiki.fifengine.de/Changes_to_pychan_and_FIFE_in_editor_rewrite_branch
author | cheesesucker@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 08 Jun 2009 16:00:02 +0000 |
parents | |
children | 987a4ea829c1 |
comparison
equal
deleted
inserted
replaced
254:10b5f7f36dd4 | 255:51cc05d862f2 |
---|---|
1 import shutil | |
2 import os | |
3 try: | |
4 import xml.etree.cElementTree as ET | |
5 except: | |
6 import xml.etree.ElementTree as ET | |
7 | |
8 class Settings(object): | |
9 """ This class provides an interface for retrieving and putting settings | |
10 to an XML-file. | |
11 | |
12 Only one instance of this class may exist, or a RuntimeWarning exception | |
13 will be raised. Use Settings.instance or Editor.getSettings() to retrieve | |
14 an instance of this class. | |
15 """ | |
16 instance = None # Points to the first initialized instance of this class | |
17 def __init__(self, *args, **kwargs): | |
18 if Settings.instance is not None: | |
19 raise RuntimeWarning("Settings instance has already been initialized! Use Editor.getSettings instead") | |
20 | |
21 Settings.instance = self | |
22 | |
23 if os.path.exists('settings.xml') is False: | |
24 shutil.copyfile('settings-dist.xml', 'settings.xml') | |
25 | |
26 self.tree = ET.parse('settings.xml') | |
27 self.root_element = self.tree.getroot() | |
28 self.validateTree() | |
29 | |
30 def validateTree(self): | |
31 """ Iterates the settings tree and prints warning when an invalid tag is found """ | |
32 for c in self.root_element.getchildren(): | |
33 if c.tag != "Module": | |
34 print "Invalid tag in settings.xml. Expected Module, got: ", c.tag | |
35 elif c.get("name", "") == "": | |
36 print "Invalid tag in settings.xml. Module name is empty." | |
37 else: | |
38 for e in c.getchildren(): | |
39 if e.tag != "Setting": | |
40 print "Invalid tag in settings.xml in module: ",c.tag, | |
41 print ". Expected Setting, got: ", e.tag | |
42 elif c.get("name", "") == "": | |
43 print "Invalid tag in settings.xml in module: ",c.tag, | |
44 print ". Setting name is empty", e.tag | |
45 | |
46 def getModuleTree(self, module): | |
47 """ Returns a module element from the settings tree. If no module with the specified | |
48 name exists, a new element will be created. """ | |
49 if not isinstance(module, str) and not isinstance(module, unicode): | |
50 raise AttributeError("Settings:getModuleTree: Invalid type for module argument.") | |
51 | |
52 for c in self.root_element.getchildren(): | |
53 if c.tag == "Module" and c.get("name", "") == module: | |
54 return c | |
55 | |
56 # Create module | |
57 return ET.SubElement(self.root_element, "Module", {"name":module}) | |
58 | |
59 def get(self, module, name, defaultValue=None): | |
60 """ Gets the value of a specified setting | |
61 | |
62 defaultValue is returned if the setting does not exist | |
63 """ | |
64 if not isinstance(name, str) and not isinstance(name, unicode): | |
65 raise AttributeError("Settings:get: Invalid type for name argument.") | |
66 | |
67 moduleTree = self.getModuleTree(module) | |
68 element = None | |
69 for e in moduleTree.getchildren(): | |
70 if e.tag == "Setting" and e.get("name", "") == name: | |
71 element = e | |
72 break | |
73 else: | |
74 return defaultValue | |
75 | |
76 e_value = element.text | |
77 e_strip = element.get("strip", "1").strip().lower() | |
78 e_type = str(element.get("type", "str")).strip() | |
79 | |
80 if e_value is None: | |
81 return defaultValue | |
82 | |
83 # Strip value | |
84 if e_strip == "" or e_strip == "false" or e_strip == "no" or e_strip == "0": | |
85 e_strip = False | |
86 else: e_strip = True | |
87 | |
88 if e_type == "str" or e_type == "unicode": | |
89 if e_strip: e_value = e_value.strip() | |
90 else: | |
91 e_value = e_value.strip() | |
92 | |
93 # Return value | |
94 if e_type == 'int': | |
95 return int(e_value) | |
96 elif e_type == 'float': | |
97 return float(e_value) | |
98 elif e_type == 'bool': | |
99 e_value = e_value.lower() | |
100 if e_value == "" or e_value == "false" or e_value == "no" or e_value == "0": | |
101 return False | |
102 else: | |
103 return True | |
104 elif e_type == 'str': | |
105 return str(e_value) | |
106 elif e_type == 'unicode': | |
107 return unicode(e_value) | |
108 elif e_type == 'list': | |
109 return self._deserializeList(e_value) | |
110 elif e_type == 'dict': | |
111 return self._deserializeDict(e_value) | |
112 | |
113 def set(self, module, name, value, extra_attrs={}): | |
114 """ | |
115 Sets a setting to specified value. | |
116 | |
117 Parameters: | |
118 module (str|unicode): Module where the setting should be set | |
119 name (str|unicode): Name of setting | |
120 value: Value to assign to setting | |
121 extra_attrs (dict): Extra attributes to be stored in the XML-file | |
122 """ | |
123 if not isinstance(name, str) and not isinstance(name, unicode): | |
124 raise AttributeError("Settings:set: Invalid type for name argument.") | |
125 | |
126 moduleTree = self.getModuleTree(module) | |
127 e_type = "str" | |
128 | |
129 if isinstance(value, bool): # This must be before int | |
130 e_type = "bool" | |
131 value = str(value) | |
132 elif isinstance(value, int): | |
133 e_type = "int" | |
134 value = str(value) | |
135 elif isinstance(value, float): | |
136 e_type = "float" | |
137 value = str(value) | |
138 elif isinstance(value, unicode): | |
139 e_type = "unicode" | |
140 value = unicode(value) | |
141 elif isinstance(value, list): | |
142 e_type = "list" | |
143 value = self._serializeList(value) | |
144 elif isinstance(value, dict): | |
145 e_type = "dict" | |
146 value = self._serializeDict(value) | |
147 else: | |
148 e_type = "str" | |
149 value = str(value) | |
150 | |
151 for e in moduleTree.getchildren(): | |
152 if e.tag != "Setting": continue | |
153 if e.get("name", "") == name: | |
154 e.text = value | |
155 break | |
156 else: | |
157 attrs = {"name":name, "type":e_type} | |
158 for k in extra_attrs: | |
159 if k not in attrs: | |
160 attrs[k] = extra_args[k] | |
161 elm = ET.SubElement(moduleTree, "Setting", attrs) | |
162 elm.text = value | |
163 | |
164 def saveSettings(self): | |
165 """ Save settings into settings.xml """ | |
166 self._indent(self.root_element) | |
167 self.tree.write('settings.xml', 'UTF-8') | |
168 | |
169 def _indent(self, elem, level=0): | |
170 """ | |
171 Adds whitespace, so the resulting XML-file is properly indented. | |
172 Shamelessly stolen from http://effbot.org/zone/element-lib.htm | |
173 """ | |
174 i = "\n" + level*" " | |
175 if len(elem): | |
176 if not elem.text or not elem.text.strip(): | |
177 elem.text = i + " " | |
178 if not elem.tail or not elem.tail.strip(): | |
179 elem.tail = i | |
180 for elem in elem: | |
181 self._indent(elem, level+1) | |
182 if not elem.tail or not elem.tail.strip(): | |
183 elem.tail = i | |
184 else: | |
185 if level and (not elem.tail or not elem.tail.strip()): | |
186 elem.tail = i | |
187 | |
188 # FIXME: | |
189 # These serialization functions are not reliable at all | |
190 # This will only serialize the first level of a dict or list | |
191 # It will not check the types nor the content for conflicts. | |
192 # Perhaps we should add a small serialization library? | |
193 def _serializeList(self, list): | |
194 """ Serializes a list, so it can be stored in a text file """ | |
195 return " ; ".join(list) | |
196 | |
197 def _deserializeList(self, string): | |
198 """ Deserializes a list back into a list object """ | |
199 return string.split(" ; ") | |
200 | |
201 def _serializeDict(self, dict): | |
202 """ Serializes a list, so it can be stored in a text file """ | |
203 serial = "" | |
204 for key in dict: | |
205 value = dict[key] | |
206 if serial != "": serial += " ; " | |
207 serial += str(key)+" : "+str(value) | |
208 | |
209 return serial | |
210 | |
211 def _deserializeDict(self, serial): | |
212 """ Deserializes a list back into a dict object """ | |
213 dict = {} | |
214 items = serial.split(" ; ") | |
215 for i in items: | |
216 kv_pair = i.split(" : ") | |
217 dict[kv_pair[0]] = kv_pair[1] | |
218 return dict |