Belle II Software  release-08-01-10
pickable_basf2.py
1 #!/usr/bin/env python3
2 
3 
10 
11 """
12 Pickable basf2
13 Import this module at the top of your steering file to get a (more) pickable version of basf2.
14 This is useful if you want to pickle the path using --dump-path and execute it later using --execute-path.
15 Usually all calls to functions in basf2 like use_central_database are forgotten if you only save the path.
16 With this module, these functions are executed again if you execute the pickled path using --execute-path.
17 
18 Technically this works by recording all calls to basf2 functions.
19 If you have other code which should be pickled as well you can wrap it in the make_code_pickable function.
20 
21 If you want to exclude some functions, delete them from this module using
22 del pickable_basf2.functionname
23 """
24 
25 
26 import sys
27 import pickle
28 import inspect
29 import unittest.mock as mock
30 sys.modules['original_basf2'] = sys.modules['basf2'] # noqa
31 import original_basf2
32 
33 
35  """ Drop-in replacement of the basf2 module, which keeps track of all functions calls """
36 
37  def __getattr__(self, name):
38  """ Return attribute with the given name in the basf2 namespace """
39  return getattr(original_basf2, name)
40 
41 
42 
43 basf2_state_recorder = BASF2StateRecorder()
44 
45 manager = mock.Mock()
46 
47 
48 def process(path, max_event=0):
49  """ Process call which pickles the recorded state in addition to the path """
50  sys.modules['basf2'] = original_basf2
51  original_basf2.process(path, max_event)
52  state = list(map(tuple, manager.mock_calls))
53  pickle_path = original_basf2.get_pickle_path()
54  print("Path", path)
55  print("State", state)
56  if pickle_path != '' and path is not None:
57  serialized = original_basf2.serialize_path(path)
58  serialized['state'] = state
59  pickle.dump(serialized, open(pickle_path, 'bw'))
60  sys.modules['basf2'] = basf2_state_recorder
61 
62 
63 for name, x in original_basf2.__dict__.items():
64  # We record function and fake Boost.Python.function objects
65  if inspect.isfunction(x) or isinstance(x, type(original_basf2.find_file)):
66 
67  mock_x = mock.Mock(x, side_effect=x)
68  manager.attach_mock(mock_x, name)
69  setattr(basf2_state_recorder, name, mock_x)
70  # Other names we have to set as well, because otherwise they won't be important by from basf2 import *
71  else:
72  setattr(basf2_state_recorder, name, x)
73 
74 
75 basf2_state_recorder.process = process
76 # and replace the module
77 sys.modules['basf2'] = basf2_state_recorder
78 sys.modules['pickable_basf2'] = basf2_state_recorder