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 """
208 if self.user_config_file and self.write_user_config:
209 fd = open(self.user_config_file, 'wb')
210 self.iniConfig.write(fd)
211 fd.close()
212 self.write_user_config = False
213
215 """\
216 Retrieve a value type for a given section and key. The returned
217 value type is based on the default values dictionary.
218
219 @param section: the ini file section
220 @type section: C{str}
221 @param key: the ini file key in the given section
222 @type key: C{str}
223
224 @return: a Python variable type
225 @rtype: class
226
227 """
228 return type(self.defaultValues[section][key])
229
230 - def get_value(self, section, key, key_type=None):
231 """\
232 Retrieve a value for a given section and key.
233
234 @param section: the ini file section
235 @type section: C{str}
236 @param key: the ini file key in the given section
237 @type key: C{str}
238
239 @return: the value for the given section and key
240 @rtype: class
241
242 """
243 if key_type is None:
244 key_type = self.get_type(section, key)
245 if self.iniConfig.has_option(section, key):
246 if key_type is types.BooleanType:
247 return self.iniConfig.getboolean(section, key)
248 elif key_type is types.IntType:
249 return self.iniConfig.getint(section, key)
250 elif key_type is types.ListType:
251 _val = self.iniConfig.get(section, key)
252 _val = _val.strip()
253 if _val.startswith('[') and _val.endswith(']'):
254 return eval(_val)
255 elif ',' in _val:
256 _val = [ v.strip() for v in _val.split(',') ]
257 else:
258 _val = [ _val ]
259 return _val
260 else:
261 _val = self.iniConfig.get(section, key)
262 return _val.decode(utils.get_encoding())
263 get = get_value
264 __call__ = get_value
265
266 @property
268 """\
269 Returns a printable configuration file as a multi-line string.
270
271 """
272 stdout = cStringIO.StringIO()
273 self.iniConfig.write(stdout)
274 _ret_val = stdout.getvalue()
275 stdout.close()
276 return _ret_val
277