Belle II Software development
DataStorePrinter Class Reference

Public Member Functions

def __init__ (self, name, simple, withArgument=None, array=True)
 
def add_member (self, name, arguments=None, print_callback=None, display=None)
 
def print (self)
 
def print_untested (self)
 

Public Attributes

 name
 class name of the datastore object
 
 array
 if True we print a StoreArray, otherwise a single StoreObjPtr
 
 object_members
 list of object members to call and print their results
 

Protected Member Functions

def _printObj (self, obj, index=None)
 
def _printResult (self, result, depth=0, weight=None)
 

Detailed Description

Class to print contents of a StoreObjPtr or StoreArray.

This class is inteded to print the contents of dataobjects to the standard
output to monitor changes to the contents among versions.

For example:

>>> printer = DataStorePrinter("MCParticle", ["getVertex"], {"hasStatus": [1, 2, 4]})
>>> printer.print()

will loop over all MCParticle instances in the MCParticles StoreArray and
print someting like ::

    MCParticle#0
      getVertex(): (0,0,0)
      hasStatus(1): True
      hasStatus(2): False
      hasStatus(4): False

for each MCparticle

Definition at line 42 of file datastoreprinter.py.

Constructor & Destructor Documentation

◆ __init__()

def __init__ (   self,
  name,
  simple,
  withArgument = None,
  array = True 
)
Initialize

Args:
    name (str): class name of the DataStore object
    simple (list): list of member names to print which do not need any additional
        arguments
    withArgument (dict or None): dictionary of member names and a list of
        all argument combinations to call them.
    array (bool): if True we print a StoreArray, otherwise a single StoreObjPtr

Definition at line 66 of file datastoreprinter.py.

66 def __init__(self, name, simple, withArgument=None, array=True):
67 """
68 Initialize
69
70 Args:
71 name (str): class name of the DataStore object
72 simple (list): list of member names to print which do not need any additional
73 arguments
74 withArgument (dict or None): dictionary of member names and a list of
75 all argument combinations to call them.
76 array (bool): if True we print a StoreArray, otherwise a single StoreObjPtr
77 """
78
79 self.name = name
80
81 self.array = array
82
83 self.object_members = []
84
85 # add the simple members to the list of members to call with empty
86 # arguments
87 for member in simple:
88 self.object_members.append((member, [], None, None))
89
90 # and add the members with Argument
91 if withArgument:
92 for member, arguments in withArgument.items():
93 for args in arguments:
94 # convert args to a list
95 if not isinstance(args, list) or isinstance(args, tuple):
96 args = [args]
97 # and add (name,args,display,callback) tuple
98 self.object_members.append((member, args, None, None))
99
100 # sort them by member name to have fixed order: python sort is
101 # guaranteed to be stable so different calls to the same member will
102 # remain in same relative order
103 self.object_members.sort(key=lambda x: x[0])
104

Member Function Documentation

◆ _printObj()

def _printObj (   self,
  obj,
  index = None 
)
protected
Print all defined members for each object with given index.
If we print a StoreObjPtr then index is None and this function is called
once. If we print StoreArrays this function is called once for each
entry in the array with index set to the position in the array

Definition at line 164 of file datastoreprinter.py.

164 def _printObj(self, obj, index=None):
165 """Print all defined members for each object with given index.
166 If we print a StoreObjPtr then index is None and this function is called
167 once. If we print StoreArrays this function is called once for each
168 entry in the array with index set to the position in the array
169 """
170 # print array index? If yes then add it to the output
171 if index is not None:
172 index = f"#{int(index)}"
173 else:
174 index = ""
175
176 print(f"{self.name}{index}:")
177
178 # loop over all defined member/argument combinations
179 # and print "member(arguments): result" for each
180 for name, arguments, callback, display in self.object_members:
181 # if arguments is callable it means we need to call it to determine
182 # the arguments
183 if callable(arguments):
184 all_args = arguments(obj, name)
185 # None means we don't calle the member this time
186 if all_args is None:
187 continue
188 # list is one set of arguments, tuple(list) is n set of
189 # arguments. So convert list into tuple of length 1 to call
190 # member once
191 if isinstance(all_args, list):
192 all_args = (all_args,)
193 else:
194 # if arguments is not callable we assume it's one set of
195 # arguments
196 all_args = (arguments,)
197
198 for args in all_args:
199 result = getattr(obj, name)(*args)
200 # display can be used to override what is printed for the member. If
201 # so, use it here
202 if display is not None:
203 print(" " + display + ": ", end="")
204 else:
205 # otherwise just print name and arguments
206 print(f" {name}({','.join(map(str, args))}): ", end="")
207 # if a callback is set the callback is used to print the result
208 if callback is not None:
209 print("", end="", flush=True)
210 callback(name, args, result)
211 # otherwise use default function
212 else:
213 self._printResult(result)
214

◆ _printResult()

def _printResult (   self,
  result,
  depth = 0,
  weight = None 
)
protected
 Print the result of calling a certain member.
As we want the test to be independent of memory we have to be a bit careful
how to not just print() but check whether the object is maybe a pointer to another
DataStore object or if it is a TObject with implements Print().
Also, call recursively std::pair

Args:
    result: object to print
    depth (int): depth for recursive printing, controls the level of indent
    weight (float or None): weight to print in addition to object, only used for
    relations

Definition at line 215 of file datastoreprinter.py.

215 def _printResult(self, result, depth=0, weight=None):
216 """ Print the result of calling a certain member.
217 As we want the test to be independent of memory we have to be a bit careful
218 how to not just print() but check whether the object is maybe a pointer to another
219 DataStore object or if it is a TObject with implements Print().
220 Also, call recursively std::pair
221
222 Args:
223 result: object to print
224 depth (int): depth for recursive printing, controls the level of indent
225 weight (float or None): weight to print in addition to object, only used for
226 relations
227 """
228 # are we in recursion? if so indent the output
229 if depth:
230 print(" " * (depth + 1), end="")
231
232 if weight is not None:
233 weight = f" (weight: {weight:.6g})"
234 else:
235 weight = ""
236
237 # is it another RelationsObject? print array name and index
238 if hasattr(result, "getArrayName") and hasattr(result, "getArrayIndex"):
239 if not result:
240 print(f"-> NULL{weight}")
241 else:
242 print(f"-> {result.getArrayName()}#{int(result.getArrayIndex())}{weight}")
243 # special case for TMatrix like types to make them more space efficient
244 elif hasattr(result, "GetNrows") and hasattr(result, "GetNcols"):
245 print(weight, end="")
246 for row in range(result.GetNrows()):
247 print("\n" + " " * (depth + 2), end="")
248 for col in range(result.GetNcols()):
249 print(f"{result(row, col):13.6e} ", end="")
250
251 print()
252 # or is it a TVector3 or TLorentzVector?
253 elif isinstance(result, TVector3):
254 print("(" + ",".join(f"{result[i]:.6g}" for i in range(3)) + ")")
255 elif isinstance(result, XYZVector):
256 print("(" + ",".join(f"{Belle2.B2Vector3D(result)[i]:.6g}" for i in range(3)) + ")")
257 # print("(" + ",".join("%.6g" % x for x in [result.X(), result.Y(), result.Z()]) + ")")
258 elif isinstance(result, TLorentzVector):
259 print("(" + ",".join(f"{result[i]:.6g}" for i in range(4)) + ")")
260 # or, does it look like a std::pair?
261 elif hasattr(result, "first") and hasattr(result, "second"):
262 print(f"pair{weight}")
263 self._printResult(result.first, depth + 1)
264 self._printResult(result.second, depth + 1)
265 # or, could it be a std::vector like container? But ROOT might wrap a std::string so if it has npos assume it's a string
266 elif (hasattr(result, "size") and hasattr(result, "begin")
267 and hasattr(result, "end")) and not hasattr(result, "npos") \
268 and not isinstance(result, Const.DetectorSet):
269 print(f"size({int(result.size())}){weight}")
270 # if it is a RelationVector we also want to print the weights. So
271 # check whether we have weights and pass them to the _printResult
272 weight_getter = getattr(result, "weight", None)
273 weight = None
274 # loop over all elements and print the elements with one level more
275 # indentation
276 for i, e in enumerate(result):
277 if weight_getter is not None:
278 weight = weight_getter(i)
279 self._printResult(e, depth + 1, weight=weight)
280 # print floats with 6 valid digits
281 elif isinstance(result, float):
282 print(f"{result:.6g}{weight}")
283 # print char as int
284 elif isinstance(result, str) and len(result) == 1:
285 print(ord(result), weight, sep="")
286 # ok, in any case we can just print it
287 else:
288 print(result, weight, sep="")
289
290
291# ok, now we just need a small class to call all the printer objects for each
292# event

◆ add_member()

def add_member (   self,
  name,
  arguments = None,
  print_callback = None,
  display = None 
)
Add an additional member to be printed.

Args:
    name (str): name of the member
    arguments (list or callable): arguments to pass to the member when calling it
        If this is a callable object then the function is called with
        the object as first argument and the member name to be tested as
        second argument. The function is supposed to return the list of
        arguments to pass to the member when calling. Possible return
        valus for the callable are:

        * a `list` of arguments to be passed to the member. An empty
          `list` means to call the member with no arguments.
        * a `tuple` of `lists <list>` to call the member once for each
          list of arguments in the tuple
        * `None` or an empty tuple to not call the member at all
    print_callback (function or None): if not None a function to print
        the result of the member call. The function will be called with
        the arguments (name, arguments, result) and should print the
        result on stdout without any additional information.
    display (str or None): display string to use when printing member call
        info instead of function name + arguments. If it is not given
        the default output will be ``{membername}({arguments}):``
        followed by the result.

Definition at line 105 of file datastoreprinter.py.

105 def add_member(self, name, arguments=None, print_callback=None, display=None):
106 """
107 Add an additional member to be printed.
108
109 Args:
110 name (str): name of the member
111 arguments (list or callable): arguments to pass to the member when calling it
112 If this is a callable object then the function is called with
113 the object as first argument and the member name to be tested as
114 second argument. The function is supposed to return the list of
115 arguments to pass to the member when calling. Possible return
116 valus for the callable are:
117
118 * a `list` of arguments to be passed to the member. An empty
119 `list` means to call the member with no arguments.
120 * a `tuple` of `lists <list>` to call the member once for each
121 list of arguments in the tuple
122 * `None` or an empty tuple to not call the member at all
123 print_callback (function or None): if not None a function to print
124 the result of the member call. The function will be called with
125 the arguments (name, arguments, result) and should print the
126 result on stdout without any additional information.
127 display (str or None): display string to use when printing member call
128 info instead of function name + arguments. If it is not given
129 the default output will be ``{membername}({arguments}):``
130 followed by the result.
131 """
132 if arguments is None:
133 arguments = []
134 self.object_members.append((name, arguments, print_callback, display))
135 # return self for method chaining
136 return self
137

◆ print()

def print (   self)
Print all the objects currently existing

Definition at line 138 of file datastoreprinter.py.

138 def print(self):
139 """Print all the objects currently existing"""
140 if self.array:
141 data = Belle2.PyStoreArray(self.name + "s")
142 if not data.isValid():
143 print(f"No data for {self.name}")
144 else:
145 for i, obj in enumerate(data):
146 self._printObj(obj, i)
147 else:
148 obj = Belle2.PyStoreObj(self.name)
149 if not obj.isValid():
150 print(f"No data for {self.name}")
151 else:
152 if obj:
153 self._printObj(obj.obj())
154
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
a (simplified) python wrapper for StoreObjPtr.
Definition: PyStoreObj.h:67

◆ print_untested()

def print_untested (   self)
Print all the public member functions we will not test

Definition at line 155 of file datastoreprinter.py.

155 def print_untested(self):
156 """Print all the public member functions we will not test"""
157 members = get_public_members(self.name)
158 tested = {e[0] for e in self.object_members}
159 for member in members:
160 if member in tested:
161 continue
162 print(f"Untested method {self.name}::{member}")
163

Member Data Documentation

◆ array

array

if True we print a StoreArray, otherwise a single StoreObjPtr

Definition at line 81 of file datastoreprinter.py.

◆ name

name

class name of the datastore object

Definition at line 79 of file datastoreprinter.py.

◆ object_members

object_members

list of object members to call and print their results

Definition at line 83 of file datastoreprinter.py.


The documentation for this class was generated from the following file: