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 return result + ')'
139
141 """\
142 Stores a value for a given section and key.
143
144 This methods affects a SafeConfigParser object held in
145 RAM. No configuration file is affected by this
146 method. To write the configuration to disk use
147 the L{write()} method.
148
149 @param section: the ini file section
150 @type section: C{str}
151 @param key: the ini file key in the given section
152 @type key: C{str}
153 @param value: the value for the given section and key
154 @type value: C{str}, C{list}, C{booAl}, ...
155
156 """
157 if type(value) == type(u''):
158 value = value.encode(utils.get_encoding())
159 if type(value) is types.BooleanType:
160 self.iniConfig.set(section, key, str(int(value)))
161 elif type(value) in (types.ListType, types.TupleType):
162 self.iniConfig.set(section, key, ", ".join(value))
163 else:
164 self.iniConfig.set(section, key, str(value))
165
167 """\
168 Fills a C{SafeConfigParser} object with the default ini file
169 values as pre-defined in Python X2Go or. This SafeConfigParser
170 object is held in RAM. No configuration file is affected by this
171 method.
172
173 """
174 for section, sectionvalue in self.defaultValues.items():
175 for key, value in sectionvalue.items():
176 if self.iniConfig.has_option(section, key): continue
177 if not self.iniConfig.has_section(section):
178 self.iniConfig.add_section(section)
179 self._storeValue(section, key, value)
180
182 """\
183 Change a value for a given section and key. This method
184 does not have any effect on configuration files.
185
186 @param section: the ini file section
187 @type section: C{str}
188 @param key: the ini file key in the given section
189 @type key: C{str}
190 @param value: the value for the given section and key
191 @type value: C{str}, C{list}, C{bool}, ...
192
193 """
194 if not self.iniConfig.has_section(section):
195 self.iniConfig.add_section(section)
196 self._storeValue(section, key, value)
197 self.write_user_config = True
198
200 """\
201 Write the ini file modifications (SafeConfigParser object) from RAM to disk.
202
203 For writing the first of the C{config_files} specified on instance construction
204 that is writable will be used.
205
206 """
207 if self.user_config_file and self.write_user_config:
208 fd = open(self.user_config_file, 'wb')
209 self.iniConfig.write(fd)
210 fd.close()
211 self.write_user_config = False
212
214 """\
215 Retrieve a value type for a given section and key. The returned
216 value type is based on the default values dictionary.
217
218 @param section: the ini file section
219 @type section: C{str}
220 @param key: the ini file key in the given section
221 @type key: C{str}
222
223 @return: a Python variable type
224 @rtype: class
225
226 """
227 return type(self.defaultValues[section][key])
228
229 - def get_value(self, section, key, key_type=None):
230 """\
231 Retrieve a value for a given section and key.
232
233 @param section: the ini file section
234 @type section: C{str}
235 @param key: the ini file key in the given section
236 @type key: C{str}
237
238 @return: the value for the given section and key
239 @rtype: class
240
241 """
242 if key_type is None:
243 key_type = self.get_type(section, key)
244 if self.iniConfig.has_option(section, key):
245 if key_type is types.BooleanType:
246 return self.iniConfig.getboolean(section, key)
247 elif key_type is types.IntType:
248 return self.iniConfig.getint(section, key)
249 elif key_type is types.ListType:
250 _val = self.iniConfig.get(section, key)
251 _val = _val.strip()
252 if _val.startswith('[') and _val.endswith(']'):
253 return eval(_val)
254 elif ',' in _val:
255 _val = [ v.strip() for v in _val.split(',') ]
256 else:
257 _val = [ _val ]
258 return _val
259 else:
260 _val = self.iniConfig.get(section, key)
261 return _val.decode(utils.get_encoding())
262 get = get_value
263 __call__ = get_value
264
265 @property
267 """\
268 Returns a printable configuration file as a multi-line string.
269
270 """
271 stdout = cStringIO.StringIO()
272 self.iniConfig.write(stdout)
273 _ret_val = stdout.getvalue()
274 stdout.close()
275 return _ret_val
276