| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Variable.py
Go to the documentation of this file.
1 '''
2 Created on Jun 27, 2011
3
4 @author: mplajner
5 '''
6 import re
7 import os
8 import logging
9 from os.path import normpath
10 from zipfile import is_zipfile
11
12 class VariableProcessor(object):
13 '''
14 Base class for the objects used to process the variables.
15 '''
16 def __init__(self, env):
17 '''
18 @param env: dictionary with the reference environment to use
19 '''
20 if env is None:
21 env = {}
22 self._env = env
23
24 def isTarget(self, variable):
25 '''
26 Return True if this processor can operate on the given variable.
27 '''
28 return True
29
30 def process(self, variable, value):
31 '''
32 Process the variable.
33
34 @param value: the content of the variable to be processed
35 @return: the processed value
36 '''
37 # by default do nothing
38 return value
39
40 def __call__(self, variable, value):
41 return self.process(variable, value)
42
43 class ListProcessor(VariableProcessor):
44 '''
45 Base class for processors operating only on lists.
46 '''
47 def isTarget(self, variable):
48 '''
49 Return True if this variable is a list.
50 '''
51 return isinstance(variable, List)
52
53 class ScalarProcessor(VariableProcessor):
54 '''
55 Base class for processors operating only on scalars.
56 '''
57 def isTarget(self, variable):
58 '''
59 Return True if this variable is a scalar.
60 '''
61 return isinstance(variable, Scalar)
62
63 class EnvExpander(VariableProcessor):
64 '''
65 Variable processor to expand the reference to environment variables.
66 '''
67 def __init__(self, env):
68 super(EnvExpander, self).__init__(env)
69 self._exp = re.compile(r"\$([A-Za-z_][A-Za-z0-9_]*)|\$\(([A-Za-z_][A-Za-z0-9_]*)\)|\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$\{(\.)\}")
70
71 def isTarget(self, variable):
72 return (super(EnvExpander, self).isTarget(variable)
73 and variable.expandVars)
74
75 def _repl(self, value):
76 m = self._exp.search(value)
77 if m:
78 try:
79 value = (value[:m.start()]
80 + str(self._env[filter(None, m.groups())[0]])
81 + value[m.end():])
82 except KeyError, k:
83 logging.debug('KeyError: %s unknown while expanding %s', k, value)
84 return value
85 return self._repl(value)
86 else:
87 return value
88
89 def process(self, variable, value):
90 if isinstance(value, str):
91 value = self._repl(value)
92 else:
93 # expand only in the elements that are new
94 old_values = set(variable.val)
95 value = map(lambda v: v if v in old_values else self._repl(v), value)
96 return value
97
98 class PathNormalizer(VariableProcessor):
99 '''
100 Call os.path.normpath for all the entries of the variable.
101 '''
102 def process(self, variable, value):
103 if isinstance(value, str):
104 if '://' not in value: # this might be a URL
105 value = normpath(value)
106 else:
107 value = [normpath(v) for v in value if v]
108 return value
109
110 class DuplicatesRemover(ListProcessor):
111 '''
112 Remove duplicates entries from lists.
113 '''
114 def process(self, variable, value):
115 val = []
116 for s in value:
117 if s not in val:
118 val.append(s)
119 return val
120
121 class EmptyDirsRemover(ListProcessor):
122 '''
123 Remove empty or not existing directories from lists.
124 '''
125 def process(self, variable, value):
126 from os.path import isdir
127 from os import listdir
128 return [s for s in value if s.endswith('.zip') or (isdir(s) and listdir(s))]
129
130 class UsePythonZip(ListProcessor):
131 '''
132 Use .zip files instead of regular directories in PYTHONPATH when possible.
133 '''
134 def isTarget(self, variable):
135 return (super(UsePythonZip, self).isTarget(variable)
136 and variable.varName == 'PYTHONPATH')
137
138 def process(self, variable, value):
139 val = []
140 for s in value:
141 z = s + '.zip'
142 if is_zipfile(z):
143 val.append(z)
144 else:
145 val.append(s)
146 return val
147
148 # Default (minimal) set of processors.
149 processors = [ EnvExpander, PathNormalizer, DuplicatesRemover,
150 # special processors
151 EmptyDirsRemover, UsePythonZip
152 ]
153
154 # FIXME: these are back-ward compatibility hacks: we need a proper way to add/remove processors
155 if ('no-strip-path' in os.environ.get('CMTEXTRATAGS', '')
156 or 'GAUDI_NO_STRIP_PATH' in os.environ
157 or 'LB_NO_STRIP_PATH' in os.environ):
158 processors.remove(EmptyDirsRemover)
159
160 if 'no-pyzip' in os.environ.get('CMTEXTRATAGS', ''):
161 processors.remove(UsePythonZip)
162
163 class VariableBase(object):
164 '''
165 Base class for the classes used to manipulate the environment.
166 '''
167
168 def __init__(self, name, local=False):
169 self.varName = name
170 self.local = local
171 self.expandVars = True
172 self.log = logging.getLogger('Variable')
173
174 def process(self, value, env):
175 '''
176 Call all the processors defined in the processors list on 'value'.
177
178 @return: the processed value
179 '''
180 for p in [c(env) for c in processors]:
181 if p.isTarget(self):
182 value = p(self, value)
183 return value
184
185 class List(VariableBase):
186 '''
187 Class for manipulating with environment lists.
188
189 It holds its name and values represented by a list.
190 Some operations are done with separator, which is usually colon. For windows use semicolon.
191 '''
192
193 def __init__(self, name, local=False):
194 super(List, self).__init__(name, local)
195 self.val = []
196
197 def name(self):
198 '''Returns the name of the List.'''
199 return self.varName
200
201 def set(self, value, separator=':', environment=None):
202 '''Sets the value of the List. Any previous value is overwritten.'''
203 if isinstance(value, str):
204 value = value.split(separator)
205 self.val = self.process(value, environment)
206
207 def unset(self, value, separator=':', environment=None):# pylint: disable=W0613
208 '''Sets the value of the List to empty. Any previous value is overwritten.'''
209 self.val = []
210
211 def value(self, asString=False, separator=':'):
212 '''Returns values of the List. Either as a list or string with desired separator.'''
213 if asString:
214 return separator.join(self.val)
215 else:
216 # clone the list
217 return list(self.val)
218
219 def remove_regexp(self, value, separator = ':'):
220 self.remove(value, separator, True)
221
222 def remove(self, value, separator=':', regexp=False):
223 '''Removes value(s) from List. If value is not found, removal is canceled.'''
224 if regexp:
225 value = self.search(value, True)
226
227 elif isinstance(value,str):
228 value = value.split(separator)
229
230 for i in range(len(value)):
231 val = value[i]
232 if val not in value:
233 self.log.info('Value "%s" not found in List: "%s". Removal canceled.', val, self.varName)
234 while val in self.val:
235 self.val.remove(val)
236
237
238 def append(self, value, separator=':', environment=None):
239 '''Adds value(s) at the end of the list.'''
240 if isinstance(value, str):
241 value = value.split(separator)
242 self.val = self.process(self.val + value, environment)
243
244 def prepend(self, value, separator=':', environment=None):
245 '''Adds value(s) at the beginning of the list.
246 resolve references and duplications'''
247 if isinstance(value, str):
248 value = value.split(separator)
249 self.val = self.process(value + self.val, environment)
250
251 def search(self, expr, regExp):
252 '''Searches in List's values for a match
253
254 Use string value or set regExp to True.
255 In the first case search is done only for an exact match for one of List`s value ('^' and '$' added).
256 '''
257 if not regExp:
258 expr = '^' + expr + '$'
259 v = re.compile(expr)
260 res = []
261 for val in self.val:
262 if v.search(val):
263 res.append(val)
264
265 return res
266
267 def __getitem__(self, key):
268 return self.val[key]
269
270 def __setitem__(self, key, value):
271 if value in self.val:
272 self.log.info('Var: "%s" value: "%s". Addition canceled because of duplicate entry.', self.varName, value)
273 else:
274 self.val.insert(key, value)
275
276 def __delitem__(self, key):
277 self.remove(self.val[key])
278
279 def __iter__(self):
280 for i in self.val:
281 yield i
282
283 def __contains__(self, item):
284 return item in self.val
285
286 def __len__(self):
287 return len(self.val)
288
289 def __str__(self):
290 return ':'.join(self.val)
291
292
293 class Scalar(VariableBase):
294 '''Class for manipulating with environment scalars.'''
295
296 def __init__(self, name, local=False):
297 super(Scalar, self).__init__(name, local)
298 self.val = ''
299
300 def name(self):
301 '''Returns the name of the scalar.'''
302 return self.varName
303
304 def set(self, value, separator=':', environment=None):# pylint: disable=W0613
305 '''Sets the value of the scalar. Any previous value is overwritten.'''
306 self.val = self.process(value, environment)
307
308 def unset(self, value, separator=':', environment=None):# pylint: disable=W0613
309 '''Sets the value of the variable to empty. Any previous value is overwritten.'''
310 self.val = ''
311
312 def value(self, asString=False, separator=':'):# pylint: disable=W0613
313 '''Returns values of the scalar.'''
314 return self.val
315
316 def remove_regexp(self, value, separator=':'):
317 self.remove(value, separator, True)
318
319 def remove(self, value, separator=':', regexp=True):# pylint: disable=W0613
320 '''Removes value(s) from the scalar. If value is not found, removal is canceled.'''
321 value = self.search(value)
322 for val in value:
323 self.val = self.val.replace(val, '')
324
325 def append(self, value, separator=':', environment=None):# pylint: disable=W0613
326 '''Adds value(s) at the end of the scalar.'''
327 self.val += self.process(value, environment)
328
329 def prepend(self, value, separator=':', environment=None):# pylint: disable=W0613
330 '''Adds value(s) at the beginning of the scalar.'''
331 self.val = self.process(value, environment) + self.val
332
333 def search(self, expr):
334 '''Searches in scalar`s values for a match'''
335 return re.findall(expr, self.val)
336
337 def __str__(self):
338 return self.val
339
340 class EnvError(Exception):
341 '''Class which defines errors for locals operations.'''
342 def __init__(self, value, code):
343 super(EnvError, self).__init__()
344 self.val = value
345 self.code = code
346 def __str__(self):
347 if self.code == 'undefined':
348 return 'Reference to undefined environment element: "'+self.val +'".'
349 elif self.code == 'ref2var':
350 return 'Reference to list from the middle of string.'
351 elif self.code == 'redeclaration':
352 return 'Wrong redeclaration of environment element "'+self.val+'".'