Gaudi Framework, version v24r2

Home   Generated: Wed Dec 4 2013
 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 
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 
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 
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 
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 
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 
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 
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 
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 
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+'".'

Generated at Wed Dec 4 2013 14:33:06 for Gaudi Framework, version v24r2 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004