Belle II Software light-2405-quaxo
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 40 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 64 of file datastoreprinter.py.

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

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 156 of file datastoreprinter.py.

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

◆ _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 207 of file datastoreprinter.py.

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

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

◆ print()

def print (   self)
Print all the objects currently existing

Definition at line 136 of file datastoreprinter.py.

136 def print(self):
137 """Print all the objects currently existing"""
138 if self.array:
139 data = Belle2.PyStoreArray(self.name + "s")
140 for i, obj in enumerate(data):
141 self._printObj(obj, i)
142 else:
143 obj = Belle2.PyStoreObj(self.name)
144 if obj:
145 self._printObj(obj.obj())
146
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 147 of file datastoreprinter.py.

147 def print_untested(self):
148 """Print all the public member functions we will not test"""
149 members = get_public_members(self.name)
150 tested = {e[0] for e in self.object_members}
151 for member in members:
152 if member in tested:
153 continue
154 print(f"Untested method {self.name}::{member}")
155

Member Data Documentation

◆ array

array

if True we print a StoreArray, otherwise a single StoreObjPtr

Definition at line 79 of file datastoreprinter.py.

◆ name

name

class name of the datastore object

Definition at line 77 of file datastoreprinter.py.

◆ object_members

object_members

list of object members to call and print their results

Definition at line 81 of file datastoreprinter.py.


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