Belle II Software  release-05-01-25
utilities.py
1 import basf2
2 
3 import os
4 import os.path
5 import sys
6 import argparse
7 import collections
8 
9 
10 class ArgumentParser(argparse.ArgumentParser):
11 
12  """An argparse.Argument parse slightly changed such
13  that it always prints an extended help message incase of a parsing error."""
14 
15  def error(self, message):
16  """Method invoked when a parsing error occured.
17  Writes an extended help over the base ArgumentParser.
18  """
19  self.print_help()
20  sys.stderr.write('error: %s\n' % message)
21  sys.exit(2)
22 
23 
24 class NonstrictChoices(list):
25 
26  """Class that instances can be given to an argparse.ArgumentParser.add_argument as choices keyword argument.
27 
28  The explicit choices stated during construction of this object are just suggestions but all other values are
29  excepted as well.
30  """
31 
32  def __contains__(self, value):
33  """Test for correctness of the choices.
34  Always returns true since all choices should be valid not only the ones stated at construction of this object.
35  """
36  return True
37 
38  def __iter__(self):
39  """Displays all explicit values and a final "..." to indicate more choices might be possible."""
40  # Append an ellipses to indicate that there are more choices.
41  copy = list(super().__iter__())
42  copy.append('...')
43  return iter(copy)
44 
45  def __str__(self):
46  """Displays all explicit values and a final "..." to indicate more choices might be possible."""
47  # Append an ellipses to indicate that there are more choices.
48  copy = list(self)
49  copy.append('...')
50  return str(copy)
51 
52 
53 def find_file(file_path):
54  # dec_file_path = Belle2.FileSystem.findFile(generator_module)
55  belle2_local_dir = os.environ.get("BELLE2_LOCAL_DIR", None)
56  if belle2_local_dir:
57  local_file_path = os.path.join(belle2_local_dir, file_path)
58  if os.path.exists(local_file_path) and os.path.isfile(local_file_path):
59  return local_file_path
60 
61  belle2_central_dir = os.environ.get("BELLE2_RELEASE_DIR", None)
62  if belle2_central_dir:
63  central_file_path = os.path.join(belle2_central_dir, file_path)
64  if os.path.exists(central_file_path) and os.path.isfile(central_file_path):
65  return central_file_path
66 
67  if os.path.exists(file_path) and os.path.isfile(file_path):
68  return file_path
69 
70  return None
71 
72 
73 def extend_path(path,
74  module,
75  module_by_short_name={},
76  allow_function_import=False):
77  """Convenience adder function that can resolve addtional short hand module names from a dictionary"""
78  if isinstance(module, basf2.Module):
79  # A module instance
80  path.add_module(module)
81 
82  elif isinstance(module, str):
83  # A module name of a short name as defined in the forwarded dictionary
84  if allow_function_import:
85  if "." in module:
86  # Allow imports from the local directory
87  sys.path.append(os.getcwd())
88 
89  py_module_name, function_name = module.rsplit(".", 1)
90  try:
91  import importlib
92  py_module = importlib.import_module(py_module_name)
93  except ImportError:
94  pass
95  else:
96  py_function = getattr(py_module, function_name)
97  py_function(path)
98  return
99 
100  if module in module_by_short_name:
101  short_name = module
102  module = module_by_short_name[short_name]
103  # module is a short name
104  # resolve it and add it
105  extend_path(path, module, module_by_short_name)
106  else:
107  # module is a module name from basf2
108  path.add_module(module)
109 
110  elif callable(module):
111  # A convenience function or a module class
112  try:
113  if issubclass(module, basf2.Module):
114  # module is a module class
115  # create an instance and add it to the path
116  module_instance = module()
117  path.add_module(module_instance)
118  return
119  except TypeError:
120  pass
121 
122  # module is not a module class
123  # try it as a convenience function that add modules to the path
124  module(path)
125 
126  elif isinstance(module, collections.Iterable):
127  # A list of modules or basf2.Path
128  modules = module
129  for module in modules:
130  extend_path(path, module, module_by_short_name)
131  else:
132  message_template = """
133 '%s of type %s is neither
134 * a module instance
135 * a module (python) class
136 * a module name
137 * a add_* function
138 * a short name resolveable from %s.'
139 * an iterable of the above (e.g. basf2.Path)
140 """
141  raise ValueError(message_template % (module,
142  type(module),
143  module_by_short_name.keys()))
144 
145 
146 def get_module_param(module, name):
147  parameters = module.available_params()
148  for parameter in parameters:
149  if name == parameter.name:
150  return parameter.values
151  else:
152  raise AttributeError('%s module does not have a parameter named %s' % (module, name))
tracking.run.utilities.ArgumentParser.error
def error(self, message)
Definition: utilities.py:15
tracking.run.utilities.NonstrictChoices.__contains__
def __contains__(self, value)
Definition: utilities.py:32
tracking.run.utilities.ArgumentParser
Definition: utilities.py:10
tracking.run.utilities.NonstrictChoices.__str__
def __str__(self)
Definition: utilities.py:45
tracking.run.utilities.NonstrictChoices.__iter__
def __iter__(self)
Definition: utilities.py:38
tracking.run.utilities.NonstrictChoices
Definition: utilities.py:24