The Gaudi Framework  v36r6 (b1ee9983)
GaudiKernel.ProcessJobOptions.JobOptsParser Class Reference
Collaboration diagram for GaudiKernel.ProcessJobOptions.JobOptsParser:

Public Member Functions

def __init__ (self)
 
def parse (self, file)
 

Public Attributes

 units
 
 defines
 

Static Public Attributes

 comment = re.compile(r"(//.*)$")
 
 comment_in_string = re.compile(r'(["\']).*//.*\1')
 
 directive = re.compile(r"^\s*#\s*([\w!]+)\s*(.*)\s*$")
 
tuple comment_ml = (re.compile(r"/\*"), re.compile(r"\*/"))
 
string statement_sep = ";"
 
 reference = re.compile(r"^@([\w.]*)$")
 

Private Member Functions

def _include (self, file, function)
 
def _parse_units (self, file)
 
def _eval_statement (self, statement)
 

Detailed Description

Definition at line 174 of file ProcessJobOptions.py.

Constructor & Destructor Documentation

◆ __init__()

def GaudiKernel.ProcessJobOptions.JobOptsParser.__init__ (   self)

Definition at line 184 of file ProcessJobOptions.py.

184  def __init__(self):
185  # parser level states
186  self.units = {}
187  self.defines = {}
188  if sys.platform != "win32":
189  self.defines["WIN32"] = True
190 

Member Function Documentation

◆ _eval_statement()

def GaudiKernel.ProcessJobOptions.JobOptsParser._eval_statement (   self,
  statement 
)
private

Definition at line 343 of file ProcessJobOptions.py.

343  def _eval_statement(self, statement):
344  from GaudiKernel.Proxy.Configurable import (
345  Configurable,
346  ConfigurableGeneric,
347  PropertyReference,
348  )
349 
350  # statement = statement.replace("\n","").strip()
351  _log.info("%s%s", statement, self.statement_sep)
352 
353  property, value = statement.split("=", 1)
354 
355  inc = None
356  if property[-1] in ["+", "-"]:
357  inc = property[-1]
358  property = property[:-1]
359 
360  property = property.strip()
361  value = value.strip()
362 
363  # find the configurable to apply the property to
364  # parent_cfg = None
365  # while '.' in property:
366  # component, property = property.split('.',1)
367  # if parent_cfg:
368  # if hasattr(parent_cfg,component):
369  # cfg = getattr(parent_cfg,component)
370  # else:
371  # cfg = ConfigurableGeneric(component)
372  # setattr(parent_cfg,component,cfg)
373  # else:
374  # cfg = ConfigurableGeneric(component)
375  # parent_cfg = cfg
376 
377  # remove spaces around dots
378  property = ".".join([w.strip() for w in property.split(".")])
379  component, property = property.rsplit(".", 1)
380  if component in Configurable.allConfigurables:
381  cfg = Configurable.allConfigurables[component]
382  else:
383  cfg = ConfigurableGeneric(component)
384 
385  # value = os.path.expandvars(value)
386  value = value.replace("true", "True").replace("false", "False")
387  if value[0] == "{":
388  # Try to guess if the values looks like a dictionary
389  if ":" in value and not (
390  value[: value.index(":")].count('"') % 2
391  or value[: value.index(":")].count("'") % 2
392  ):
393  # for dictionaries, keep the surrounding {}
394  value = "{" + value[1:-1].replace("{", "[").replace("}", "]") + "}"
395  else: # otherwise replace all {} with []
396  value = value.replace("{", "[").replace("}", "]")
397 
398  # We must escape '\' because eval tends to interpret them
399  value = value.replace("\\", "\\\\")
400  # Restore special cases ('\n', '\t' and '\"') (see GAUDI-1001)
401  value = (
402  value.replace(r"\\n", r"\n").replace(r"\\t", r"\t").replace(r'\\"', r"\"")
403  )
404  # replace r'\n' and r'\t' that are outside double quoted strings
405  value = '"'.join(
406  [
407  (v if i % 2 else re.sub(r"\\[nt]", " ", v))
408  for i, v in enumerate(value.split('"'))
409  ]
410  )
411 
412  # interprete the @ operator
413  m = self.reference.match(value)
414  if m:
415  # this allows late binding of references
416  value = PropertyReference(m.group(1))
417  else:
418  value = eval(value, self.units)
419 
420  # if type(value) is str : value = os.path.expandvars(value)
421  # elif type(value) is list : value = [ type(item) is str and os.path.expandvars(item) or item for item in value ]
422 
423  if property not in cfg.__slots__ and not hasattr(cfg, property):
424  # check if the case of the property is wrong (old options are case insensitive)
425  lprop = property.lower()
426  for p in cfg.__slots__:
427  if lprop == p.lower():
428  _log.warning(
429  "property '%s' was requested for %s, but the correct spelling is '%s'",
430  property,
431  cfg.name(),
432  p,
433  )
434  property = p
435  break
436 
437  # consider the += and -=
438  if inc == "+":
439  if hasattr(cfg, property):
440  prop = getattr(cfg, property)
441  if type(prop) == dict:
442  for k in value:
443  prop[k] = value[k]
444  else:
445  prop += value
446  else:
447  setattr(cfg, property, value)
448  elif inc == "-":
449  if hasattr(cfg, property):
450  prop = getattr(cfg, property)
451  if type(prop) is dict:
452  for k in value:
453  if k in prop:
454  del prop[k]
455  else:
456  _log.warning(
457  "key '%s' not in %s.%s", k, cfg.name(), property
458  )
459  else:
460  for k in value:
461  if k in prop:
462  prop.remove(k)
463  else:
464  _log.warning(
465  "value '%s' not in %s.%s", k, cfg.name(), property
466  )
467  else:
468  setattr(cfg, property, value)
469 
470 

◆ _include()

def GaudiKernel.ProcessJobOptions.JobOptsParser._include (   self,
  file,
  function 
)
private

Definition at line 191 of file ProcessJobOptions.py.

191  def _include(self, file, function):
192  file = _find_file(file)
193  if _to_be_included(file):
194  _log.info("--> Including file '%s'", file)
195  function(file)
196  _log.info("<-- End of file '%s'", file)
197 

◆ _parse_units()

def GaudiKernel.ProcessJobOptions.JobOptsParser._parse_units (   self,
  file 
)
private

Definition at line 331 of file ProcessJobOptions.py.

331  def _parse_units(self, file):
332  for line in open(file):
333  if "//" in line:
334  line = line[: line.index("//")]
335  line = line.strip()
336  if not line:
337  continue
338  nunit, value = line.split("=")
339  factor, unit = nunit.split()
340  value = eval(value) / eval(factor)
341  self.units[unit] = value
342 

◆ parse()

def GaudiKernel.ProcessJobOptions.JobOptsParser.parse (   self,
  file 
)

Definition at line 198 of file ProcessJobOptions.py.

198  def parse(self, file):
199  # states for the "translation unit"
200  statement = ""
201 
202  ifdef_level = 0
203  ifdef_skipping = False
204  ifdef_skipping_level = 0
205 
206  in_string = False
207 
208  f = open(_find_file(file))
209  l = f.readline()
210  if l.startswith("#!"):
211  # Skip the first line if it starts with "#!".
212  # It allows to use options files as scripts.
213  l = f.readline()
214 
215  while l:
216  l = (
217  l.rstrip() + "\n"
218  ) # normalize EOL chars (to avoid problems with DOS new-line on Unix)
219 
220  # single line comment
221  m = self.comment.search(l)
222  if m:
223  # check if the '//' is part of a string
224  m2 = self.comment_in_string.search(l)
225  # the '//' is part of a string if we find the quotes around it
226  # and they are not part of the comment itself
227  if not (m2 and m2.start() < m.start()):
228  # if it is not the case, we can remove the comment from the
229  # statement
230  l = l[: m.start()] + l[m.end() :]
231  # process directives
232  m = self.directive.search(l)
233  if m:
234  directive_name = m.group(1)
235  directive_arg = m.group(2).strip()
236  if directive_name == "include":
237  included_file = directive_arg.strip("'\"")
238  importOptions(included_file)
239  elif directive_name == "units":
240  units_file = directive_arg.strip("'\"")
241  self._include(units_file, self._parse_units)
242  elif directive_name in ["ifdef", "ifndef"]:
243  ifdef_skipping_level = ifdef_level
244  ifdef_level += 1
245  if directive_arg in self.defines:
246  ifdef_skipping = directive_name == "ifndef"
247  else:
248  ifdef_skipping = directive_name == "ifdef"
249  elif directive_name == "else":
250  ifdef_skipping = not ifdef_skipping
251  elif directive_name == "endif":
252  ifdef_level -= 1
253  if ifdef_skipping and ifdef_skipping_level == ifdef_level:
254  ifdef_skipping = False
255  elif directive_name == "pragma":
256  if not directive_arg:
257  l = f.readline()
258  continue
259  pragma = directive_arg.split()
260  if pragma[0] == "print":
261  if len(pragma) > 1:
262  if pragma[1].upper() in ["ON", "TRUE", "1"]:
263  PrintOn()
264  else:
265  PrintOff()
266  else:
267  _log.warning("unknown directive '%s'", directive_name)
268  l = f.readline()
269  continue
270 
271  if ifdef_skipping:
272  l = f.readline()
273  continue
274 
275  # multi-line comment
276  m = self.comment_ml[0].search(l)
277  if m:
278  l, l1 = l[: m.start()], l[m.end() :]
279  m = self.comment_ml[1].search(l1)
280  while not m:
281  l1 = f.readline()
282  if not l1:
283  break # EOF
284  m = self.comment_ml[1].search(l1)
285  if not l1 and not m:
286  raise ParserError(
287  "End Of File reached before end of multi-line comment"
288  )
289  l += l1[m.end() :]
290 
291  # if we are in a multiline string, we add to the statement
292  # everything until the next '"'
293  if in_string:
294  string_end = l.find('"')
295  if string_end >= 0:
296  statement += l[: string_end + 1]
297  l = l[string_end + 1 :]
298  in_string = False # the string ends here
299  else:
300  statement += l
301  l = ""
302  else: # check if we have a string
303  string_start = l.find('"')
304  if string_start >= 0:
305  string_end = l.find('"', string_start + 1)
306  if string_end >= 0:
307  # the string is opened and closed
308  statement += l[: string_end + 1]
309  l = l[string_end + 1 :]
310  else:
311  # the string is only opened
312  statement += l
313  in_string = True
314  l = f.readline()
315  continue
316 
317  if self.statement_sep in l:
318  i = l.index(self.statement_sep)
319  statement += l[:i]
320  self._eval_statement(statement.strip().replace("\n", "\\n"))
321  statement = l[i + 1 :]
322  # it may happen (bug #37479) that the rest of the statement
323  # contains a comment.
324  if statement.lstrip().startswith("//"):
325  statement = ""
326  else:
327  statement += l
328 
329  l = f.readline()
330 

Member Data Documentation

◆ comment

GaudiKernel.ProcessJobOptions.JobOptsParser.comment = re.compile(r"(//.*)$")
static

Definition at line 175 of file ProcessJobOptions.py.

◆ comment_in_string

GaudiKernel.ProcessJobOptions.JobOptsParser.comment_in_string = re.compile(r'(["\']).*//.*\1')
static

Definition at line 178 of file ProcessJobOptions.py.

◆ comment_ml

tuple GaudiKernel.ProcessJobOptions.JobOptsParser.comment_ml = (re.compile(r"/\*"), re.compile(r"\*/"))
static

Definition at line 180 of file ProcessJobOptions.py.

◆ defines

GaudiKernel.ProcessJobOptions.JobOptsParser.defines

Definition at line 187 of file ProcessJobOptions.py.

◆ directive

GaudiKernel.ProcessJobOptions.JobOptsParser.directive = re.compile(r"^\s*#\s*([\w!]+)\s*(.*)\s*$")
static

Definition at line 179 of file ProcessJobOptions.py.

◆ reference

GaudiKernel.ProcessJobOptions.JobOptsParser.reference = re.compile(r"^@([\w.]*)$")
static

Definition at line 182 of file ProcessJobOptions.py.

◆ statement_sep

string GaudiKernel.ProcessJobOptions.JobOptsParser.statement_sep = ";"
static

Definition at line 181 of file ProcessJobOptions.py.

◆ units

GaudiKernel.ProcessJobOptions.JobOptsParser.units

Definition at line 186 of file ProcessJobOptions.py.


The documentation for this class was generated from the following file:
GaudiKernel.ProcessJobOptions._find_file
def _find_file(f)
Definition: ProcessJobOptions.py:149
GaudiKernel.ProcessJobOptions._to_be_included
def _to_be_included(f)
Definition: ProcessJobOptions.py:166
GaudiKernel.ProcessJobOptions.importOptions
def importOptions(optsfile)
Definition: ProcessJobOptions.py:541
gaudirun.type
type
Definition: gaudirun.py:160
parse
StatusCode parse(DataObjID &dest, const std::string &src)
Definition: DataObjID.cpp:57
GaudiKernel.ProcessJobOptions.PrintOff
def PrintOff(step=1)
Definition: ProcessJobOptions.py:141
GaudiKernel.ProcessJobOptions.PrintOn
def PrintOn(step=1, force=False)
Definition: ProcessJobOptions.py:137