CMS 3D CMS Logo

helperFunctions.py
Go to the documentation of this file.
1 import os
2 import ROOT
3 import sys
4 from TkAlExceptions import AllInOneError
5 
6 ####################--- Helpers ---############################
7 def replaceByMap(target, the_map):
8  """This function replaces `.oO[key]Oo.` by `the_map[key]` in target.
9 
10  Arguments:
11  - `target`: String which contains symbolic tags of the form `.oO[key]Oo.`
12  - `the_map`: Dictionary which has to contain the `key`s in `target` as keys
13  """
14 
15  result = target
16  for key in the_map:
17  lifeSaver = 10e3
18  iteration = 0
19  while ".oO[" in result and "]Oo." in result:
20  for key in the_map:
21  try:
22  result = result.replace(".oO["+key+"]Oo.",the_map[key])
23  except TypeError: #try a dict
24  try:
25  for keykey, value in the_map[key].iteritems():
26  result = result.replace(".oO[" + key + "['" + keykey + "']]Oo.", value)
27  result = result.replace(".oO[" + key + '["' + keykey + '"]]Oo.', value)
28  except AttributeError: #try a list
29  try:
30  for index, value in enumerate(the_map[key]):
31  result = result.replace(".oO[" + key + "[" + str(index) + "]]Oo.", value)
32  except TypeError:
33  raise TypeError("Something is wrong in replaceByMap! Need a string, dict, or list, but the_map(%s)=%s!"%(repr(key), repr(the_map[key])))
34  iteration += 1
35  if iteration > lifeSaver:
36  problematicLines = ""
37  for line in result.splitlines():
38  if ".oO[" in result and "]Oo." in line:
39  problematicLines += "%s\n"%line
40  msg = ("Oh Dear, there seems to be an endless loop in "
41  "replaceByMap!!\n%s\n%s"%(problematicLines, the_map))
42  raise AllInOneError(msg)
43  return result
44 
45 
46 def getCommandOutput2(command):
47  """This function executes `command` and returns it output.
48 
49  Arguments:
50  - `command`: Shell command to be invoked by this function.
51  """
52 
53  child = os.popen(command)
54  data = child.read()
55  err = child.close()
56  if err:
57  raise RuntimeError('%s failed w/ exit code %d' % (command, err))
58  return data
59 
60 
61 def castorDirExists(path):
62  """This function checks if the directory given by `path` exists.
63 
64  Arguments:
65  - `path`: Path to castor directory
66  """
67 
68  if path[-1] == "/":
69  path = path[:-1]
70  containingPath = os.path.join( *path.split("/")[:-1] )
71  dirInQuestion = path.split("/")[-1]
72  try:
73  rawLines = getCommandOutput2("rfdir /"+containingPath).splitlines()
74  except RuntimeError:
75  return False
76  for line in rawLines:
77  if line.split()[0][0] == "d":
78  if line.split()[8] == dirInQuestion:
79  return True
80  return False
81 
82 def replacelast(string, old, new, count = 1):
83  """Replace the last occurances of a string"""
84  return new.join(string.rsplit(old,count))
85 
86 fileExtensions = ["_cfg.py", ".sh", ".root"]
87 
88 def addIndex(filename, njobs, index = None):
89  if index is None:
90  return [addIndex(filename, njobs, i) for i in range(njobs)]
91  if njobs == 1:
92  return filename
93 
94  fileExtension = None
95  for extension in fileExtensions:
96  if filename.endswith(extension):
97  fileExtension = extension
98  if fileExtension is None:
99  raise AllInOneError(fileName + " does not end with any of the extensions "
100  + str(fileExtensions))
101  return replacelast(filename, fileExtension, "_" + str(index) + fileExtension)
102 
103 def parsecolor(color):
104  try: #simplest case: it's an int
105  return int(color)
106  except ValueError:
107  pass
108 
109  try: #kRed, kBlue, ...
110  color = str(getattr(ROOT, color))
111  return int(color)
112  except (AttributeError, ValueError):
113  pass
114 
115  if color.count("+") + color.count("-") == 1: #kRed+5, kGreen-2
116  if "+" in color: #don't want to deal with nonassociativity of -
117  split = color.split("+")
118  color1 = parsecolor(split[0])
119  color2 = parsecolor(split[1])
120  return color1 + color2
121 
122  if "-" in color:
123  split = color.split("-")
124  color1 = parsecolor(split[0])
125  color2 = parsecolor(split[1])
126  return color1 - color2
127 
128  raise AllInOneError("color has to be an integer, a ROOT constant (kRed, kBlue, ...), or a two-term sum or difference (kGreen-5)!")
129 
130 def parsestyle(style):
131  try: #simplest case: it's an int
132  return int(style)
133  except ValueError:
134  pass
135 
136  try: #kStar, kDot, ...
137  style = str(getattr(ROOT,style))
138  return int(style)
139  except (AttributeError, ValueError):
140  pass
141 
142  raise AllInOneError("style has to be an integer or a ROOT constant (kDashed, kStar, ...)!")
143 
145  result = [cls]
146  for subcls in cls.__subclasses__():
147  result += recursivesubclasses(subcls)
148  return result
149 
150 def cache(function):
151  cache = {}
152  def newfunction(*args, **kwargs):
153  try:
154  return cache[args, tuple(sorted(kwargs.iteritems()))]
155  except TypeError:
156  print args, tuple(sorted(kwargs.iteritems()))
157  raise
158  except KeyError:
159  cache[args, tuple(sorted(kwargs.iteritems()))] = function(*args, **kwargs)
160  return newfunction(*args, **kwargs)
161  newfunction.__name__ = function.__name__
162  return newfunction
163 
164 def boolfromstring(string, name):
165  """
166  Takes a string from the configuration file
167  and makes it into a bool
168  """
169  #try as a string, not case sensitive
170  if string.lower() == "true": return True
171  if string.lower() == "false": return False
172  #try as a number
173  try:
174  return str(bool(int(string)))
175  except ValueError:
176  pass
177  #out of options
178  raise ValueError("{} has to be true or false!".format(name))
179 
180 
181 def pythonboolstring(string, name):
182  """
183  Takes a string from the configuration file
184  and makes it into a bool string for a python template
185  """
186  return str(boolfromstring(string, name))
187 
188 def cppboolstring(string, name):
189  """
190  Takes a string from the configuration file
191  and makes it into a bool string for a C++ template
192  """
193  return pythonboolstring(string, name).lower()
194 
195 def conddb(*args):
196  """
197  Wrapper for conddb, so that you can run
198  conddb("--db", "myfile.db", "listTags"),
199  like from the command line, without explicitly
200  dealing with all the functions in CondCore/Utilities.
201  getcommandoutput2(conddb ...) doesn't work, it imports
202  the wrong sqlalchemy in CondCore/Utilities/python/conddblib.py
203  """
204  from tempfile import NamedTemporaryFile
205 
206  with open(getCommandOutput2("which conddb").strip()) as f:
207  conddb = f.read()
208 
209  def sysexit(number):
210  if number != 0:
211  raise AllInOneError("conddb exited with status {}".format(number))
212  namespace = {"sysexit": sysexit, "conddboutput": ""}
213 
214  conddb = conddb.replace("sys.exit", "sysexit")
215 
216  bkpargv = sys.argv
217  sys.argv[1:] = args
218  bkpstdout = sys.stdout
219  with NamedTemporaryFile(bufsize=0) as sys.stdout:
220  exec conddb in namespace
221  namespace["main"]()
222  with open(sys.stdout.name) as f:
223  result = f.read()
224 
225  sys.argv[:] = bkpargv
226  sys.stdout = bkpstdout
227 
228  return result
Definition: vlib.h:256
def parsestyle(style)
def pythonboolstring(string, name)
def getCommandOutput2(command)
def cppboolstring(string, name)
def addIndex(filename, njobs, index=None)
def replacelast(string, old, new, count=1)
def cache(function)
def replaceByMap(target, the_map)
— Helpers —############################
def boolfromstring(string, name)
def parsecolor(color)
def castorDirExists(path)
def recursivesubclasses(cls)