Belle II Software  release-05-02-19
testing_payloads.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 """
5 Script to upload local database to ConditionsDB.
6 
7 This script takes a local database file and will upload all payloads defined in
8 this file to the ConditionsDB and create iovs for each payload. It assumes that
9 all tags already exist.
10 """
11 
12 import os
13 from basf2 import B2ERROR, LogLevel, logging
14 from . import file_checksum
15 from B2Tools.b2root import normalize_file
16 
17 
19  """Class to keep information about an entry in the testing payloads storage file"""
20 
21  def __init__(self, line, basedir):
22  """Create new entry from line in testing payloads storage file"""
23  try:
24  name, revision, iov = line.split()
25  except ValueError:
26  raise ValueError("line must be of the form 'dbstore/<payloadname> <revision> "
27  "<firstExp>,<firstRun>,<finalExp>,<finalRun>'")
28  try:
29 
30  self.revision = int(revision)
31  except ValueError:
32  raise ValueError("revision must be an integer")
33 
34  try:
35 
36  self.module = name.split("/")[1]
37  except IndexError:
38  raise ValueError("payload name must be of the form dbstore/<payloadname>")
39 
40  try:
41  iov = [int(e) for e in iov.split(",")]
42  except ValueError:
43  raise ValueError("experiment and run numbers must be integers")
44 
45  if len(iov) != 4:
46  raise ValueError("IoV needs to be four values (firstExp,firstRun,finalExp,finalRun)")
47 
48 
49  self.filename = os.path.join(basedir, f"dbstore_{self.module}_rev_{self.revision}.root")
50 
51  self.firstRun = {"exp": iov[0], "run": iov[1]}
52 
53  self.finalRun = {"exp": iov[2], "run": iov[3]}
54 
55  self.__checksum = None
56 
57  self.__id = (self.module,) + tuple(iov)
58 
59  self.payload = None
60 
61  self.iov = None
62 
63  def normalize(self, name=None, root_version=61408):
64  """Normalize the root file to have the same checksum for the same content"""
65  normalize_file(self.filename, in_place=True, name=name, root_version=root_version)
66  self.__checksum = file_checksum(self.filename)
67 
68  @property
69  def checksum(self):
70  """Return checksum, calculated on first access"""
71  if self.__checksum is None:
72  self.__checksum = file_checksum(self.filename)
73  return self.__checksum
74 
75  def __repr__(self):
76  """Convert to useful string representation"""
77  return repr(self.__id + (self.filename,))
78 
79  def __eq__(self, other):
80  """Compare to other entries, only consider package, module and iov for equality"""
81  return self.__id == other.__id
82 
83  def __le__(self, other):
84  """Compare to other entries, only consider package, module and iov for equality"""
85  return self.__id <= other.__id
86 
87  def __lt__(self, other):
88  """Compare to other entries, only consider package, module and iov for equality"""
89  return self.__id < other.__id
90 
91  def __hash__(self):
92  """Provide hash function to be able to create a set"""
93  return hash(self.__id)
94 
95  @property
96  def iov_tuple(self):
97  """Return a tuple with the valid exp,run range"""
98  return self.firstRun['exp'], self.firstRun['run'], self.finalRun['exp'], self.finalRun['run']
99 
100  def iov_str(self):
101  """String representation of IoV"""
102  return f"{self.firstRun['exp']}/{self.firstRun['run']} - {self.finalRun['exp']}/{self.finalRun['run']}"
103 
104 
105 def parse_testing_payloads_file(filename, check_existing=True):
106  """
107  Parse a testing payload storage file
108 
109  This is the python equivalent of TestingPayloadStorage::read implemented in
110  python. Each line in in the file should be of the form
111 
112  "dbstore/{payloadname} {revision} {firstExp},{firstRun},{finalExp},{finalRun}"
113 
114  Comments can be started using "#", everything including this character to
115  the end of the line will be ignored.
116 
117  Parameters:
118  filename (str): filename of the testing payload storage file to parse
119  check_existing (bool): if True check if the payloads actually exist where
120  they should be
121 
122  Returns:
123  a list of TestingPayloadEntry objects or None if there were any errors
124  """
125 
126  # make sure the testing payload storage file exists
127  if not os.path.exists(filename):
128  B2ERROR("Given database file does not exist")
129  return None
130 
131  # set the directory
132  payload_dir = os.path.dirname(filename)
133 
134  # remember the list of errors before start of the function to see if we
135  # create any new ones
136  old_error_count = logging.log_stats[LogLevel.ERROR]
137  entries = []
138  with open(filename) as dbfile:
139  for lineno, line in enumerate(dbfile, 1):
140  # ignore comments
141  line = line.split("#", 1)[0].strip()
142  # and empty lines
143  if not line:
144  continue
145  # parse the line
146  try:
147  entry = TestingPayloadEntry(line, payload_dir)
148  except ValueError as e:
149  B2ERROR("{filename}:{line} error: {error}".format(
150  filename=filename, line=lineno, error=e
151  ))
152  continue
153 
154  if check_existing and not os.path.exists(entry.filename):
155  B2ERROR("{filename}:{line} error: cannot find payload file {missing}".format(
156  filename=filename, line=lineno, missing=entry.filename
157  ))
158  continue
159 
160  entries.append(entry)
161 
162  # ok, if we had any errors so far, exit
163  if logging.log_stats[LogLevel.ERROR] > old_error_count:
164  return None
165 
166  return entries
conditions_db.testing_payloads.TestingPayloadEntry.iov_tuple
def iov_tuple(self)
Definition: testing_payloads.py:96
conditions_db.testing_payloads.TestingPayloadEntry.iov_str
def iov_str(self)
Definition: testing_payloads.py:100
conditions_db.testing_payloads.TestingPayloadEntry.__lt__
def __lt__(self, other)
Definition: testing_payloads.py:87
conditions_db.testing_payloads.TestingPayloadEntry.module
module
module name
Definition: testing_payloads.py:36
conditions_db.testing_payloads.TestingPayloadEntry.__repr__
def __repr__(self)
Definition: testing_payloads.py:75
conditions_db.testing_payloads.TestingPayloadEntry.checksum
def checksum(self)
Definition: testing_payloads.py:69
conditions_db.testing_payloads.TestingPayloadEntry.__hash__
def __hash__(self)
Definition: testing_payloads.py:91
conditions_db.testing_payloads.TestingPayloadEntry.__checksum
__checksum
variable for checksum, calculated on first access
Definition: testing_payloads.py:55
conditions_db.testing_payloads.TestingPayloadEntry.finalRun
finalRun
experiment/run of the final run
Definition: testing_payloads.py:53
conditions_db.testing_payloads.TestingPayloadEntry.normalize
def normalize(self, name=None, root_version=61408)
Definition: testing_payloads.py:63
conditions_db.testing_payloads.TestingPayloadEntry.__le__
def __le__(self, other)
Definition: testing_payloads.py:83
conditions_db.testing_payloads.TestingPayloadEntry.payload
payload
payload id, to be filled later
Definition: testing_payloads.py:59
conditions_db.testing_payloads.TestingPayloadEntry.__id
__id
object to uniquely identify this entry (payload + iov)
Definition: testing_payloads.py:57
conditions_db.testing_payloads.TestingPayloadEntry.__init__
def __init__(self, line, basedir)
Definition: testing_payloads.py:21
conditions_db.testing_payloads.TestingPayloadEntry.filename
filename
filename
Definition: testing_payloads.py:49
conditions_db.testing_payloads.TestingPayloadEntry.firstRun
firstRun
experiment/run of the first run
Definition: testing_payloads.py:51
conditions_db.testing_payloads.TestingPayloadEntry.__eq__
def __eq__(self, other)
Definition: testing_payloads.py:79
B2Tools.b2root
Definition: b2root.py:1
conditions_db.testing_payloads.TestingPayloadEntry.revision
revision
revision stored in the file
Definition: testing_payloads.py:30
conditions_db.testing_payloads.TestingPayloadEntry
Definition: testing_payloads.py:18
conditions_db.testing_payloads.TestingPayloadEntry.iov
iov
iov id, to be filled later
Definition: testing_payloads.py:61