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