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 X2GoProcessIniFile - helper class for parsing .ini files
28
29 """
30 __NAME__ = 'x2goinifiles-pylib'
31
32
33 import os
34 import ConfigParser
35 import types
36 import cStringIO
37 import copy
38
39
40 from defaults import LOCAL_HOME as _current_home
41 import log
42 import utils
45 """
46 Base class for processing the different ini files used by X2Go
47 clients. Primarily used to standardize the content of the different
48 X2Go client ini file (settings, printing, sessions, xconfig).
49
50 If entries are omitted in an ini file, they are filled with
51 default values (as hard coded in Python X2Go), so the resulting objects
52 always contain the same fields.
53
54 """
55 defaultValues = {
56 'none': {
57 'none': 'empty',
58 },
59 }
60 write_user_config = False
61 user_config_file = None
62
64 """\
65 @param config_files: a list of configuration file names (e.g. a global filename and a user's home
66 directory filename)
67 @type config_files: C{list}
68 @param defaults: a cascaded Python dicitionary structure with ini file defaults (to override
69 Python X2Go's hard coded defaults in L{defaults}
70 @type defaults: C{dict}
71 @param logger: you can pass an L{X2GoLogger} object to the
72 L{X2GoIniFile} constructor
73 @type logger: L{X2GoLogger} instance
74 @param loglevel: if no L{X2GoLogger} object has been supplied a new one will be
75 constructed with the given loglevel
76 @type loglevel: C{int}
77
78 """
79
80 if not config_files:
81 config_files = []
82
83 if logger is None:
84 self.logger = log.X2GoLogger(loglevel=loglevel)
85 else:
86 self.logger = copy.deepcopy(logger)
87 self.logger.tag = __NAME__
88
89 self.config_files = config_files
90
91 if utils._checkIniFileDefaults(defaults):
92 self.defaultValues = defaults
93
94
95
96
97
98 self.iniConfig = ConfigParser.SafeConfigParser(self.defaultValues)
99 self.iniConfig.optionxform = str
100
101 _create_file = False
102 for file_name in self.config_files:
103 if file_name.startswith(_current_home):
104 if not os.path.exists(file_name):
105 utils.touch_file(file_name)
106 _create_file = True
107 break
108
109 self.load()
110
111 if _create_file:
112 self.write_user_config = True
113 self.write()
114
116 """\
117 R(e-r)ead configuration file(s).
118
119 """
120 self.logger('proposed config files are %s' % self.config_files, loglevel=log.loglevel_INFO, )
121 _found_config_files = self.iniConfig.read(self.config_files)
122 self.logger('config files found: %s' % _found_config_files or 'none', loglevel=log.loglevel_INFO, )
123
124 for file_name in _found_config_files:
125 if file_name.startswith(os.path.normpath(_current_home)):
126
127 self.user_config_file = file_name
128 break
129
130 self.config_files = _found_config_files
131 self._fill_defaults()
132
134 result = 'X2GoIniFile('
135 for p in dir(self):
136 if '__' in p or not p in self.__dict__ or type(p) is types.InstanceType: continue
137 result += p + '=' + str(self.__dict__[p]) + ','
138 result = result.strip(',')
139 return result + ')'
140
142 """\
143 Stores a value for a given section and key.
144
145 This methods affects a SafeConfigParser object held in
146 RAM. No configuration file is affected by this
147 method. To write the configuration to disk use
148 the L{write()} method.
149
150 @param section: the ini file section
151 @type section: C{str}
152 @param key: the ini file key in the given section
153 @type key: C{str}
154 @param value: the value for the given section and key
155 @type value: C{str}, C{list}, C{booAl}, ...
156
157 """
158 if type(value) == type(u''):
159 value = value.encode(utils.get_encoding())
160 if type(value) is types.BooleanType:
161 self.iniConfig.set(section, key, str(int(value)))
162 elif type(value) in (types.ListType, types.TupleType):
163 self.iniConfig.set(section, key, ", ".join(value))
164 else:
165 self.iniConfig.set(section, key, str(value))
166
168 """\
169 Fills a C{SafeConfigParser} object with the default ini file
170 values as pre-defined in Python X2Go or. This SafeConfigParser
171 object is held in RAM. No configuration file is affected by this
172 method.
173
174 """
175 for section, sectionvalue in self.defaultValues.items():
176 for key, value in sectionvalue.items():
177 if self.iniConfig.has_option(section, key): continue
178 if not self.iniConfig.has_section(section):
179 self.iniConfig.add_section(section)
180 self._storeValue(section, key, value)
181
183 """\
184 Change a value for a given section and key. This method
185 does not have any effect on configuration files.
186
187 @param section: the ini file section
188 @type section: C{str}
189 @param key: the ini file key in the given section
190 @type key: C{str}
191 @param value: the value for the given section and key
192 @type value: C{str}, C{list}, C{bool}, ...
193
194 """
195 if not self.iniConfig.has_section(section):
196 self.iniConfig.add_section(section)
197 self._storeValue(section, key, value)
198 self.write_user_config = True
199
201 """\
202 Write the ini file modifications (SafeConfigParser object) from RAM to disk.
203
204 For writing the first of the C{config_files} specified on instance construction
205 that is writable will be used.
206
207 @return: C{True} if the user config file has been successfully writte, C{False} otherwise.
208 @rtype: C{bool}
209
210 """
211 if self.user_config_file and self.write_user_config:
212 try:
213 fd = open(self.user_config_file, 'wb')
214 self.iniConfig.write(fd)
215 fd.close()
216 self.write_user_config = False
217 return True
218 except Exception, e:
219 print e
220 return False
221
223 """\
224 Retrieve a value type for a given section and key. The returned
225 value type is based on the default values dictionary.
226
227 @param section: the ini file section
228 @type section: C{str}
229 @param key: the ini file key in the given section
230 @type key: C{str}
231
232 @return: a Python variable type
233 @rtype: class
234
235 """
236 return type(self.defaultValues[section][key])
237
238 - def get_value(self, section, key, key_type=None):
239 """\
240 Retrieve a value for a given section and key.
241
242 @param section: the ini file section
243 @type section: C{str}
244 @param key: the ini file key in the given section
245 @type key: C{str}
246
247 @return: the value for the given section and key
248 @rtype: class
249
250 """
251 if key_type is None:
252 key_type = self.get_type(section, key)
253 if self.iniConfig.has_option(section, key):
254 if key_type is types.BooleanType:
255 return self.iniConfig.getboolean(section, key)
256 elif key_type is types.IntType:
257 return self.iniConfig.getint(section, key)
258 elif key_type is types.ListType:
259 _val = self.iniConfig.get(section, key)
260 _val = _val.strip()
261 if _val.startswith('[') and _val.endswith(']'):
262 return eval(_val)
263 elif ',' in _val:
264 _val = [ v.strip() for v in _val.split(',') ]
265 else:
266 _val = [ _val ]
267 return _val
268 else:
269 _val = self.iniConfig.get(section, key)
270 return _val.decode(utils.get_encoding())
271 get = get_value
272 __call__ = get_value
273
274 @property
276 """\
277 Returns a printable configuration file as a multi-line string.
278
279 """
280 stdout = cStringIO.StringIO()
281 self.iniConfig.write(stdout)
282 _ret_val = stdout.getvalue()
283 stdout.close()
284 return _ret_val
285