CMS 3D CMS Logo

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