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