12 basf2.pickle_path - Functions necessary to pickle and unpickle a Path
13 =====================================================================
15 This module contains all the functiones necessary to serialize and deserialize
16 a full path with all modules, parameters, sub paths, conditions and so on. This
17 can be used in conjunction with ``basf2 --dump-path`` and ``basf2
18 --execute-path`` to save a full configuration to file and execute it later.
22 import pickle
as _pickle
27 def serialize_value(module, parameter):
28 """Serialize a single basf2 module parameter"""
29 if parameter.name ==
'path' and module.type() ==
'SubEvent':
30 return serialize_path(parameter.values)
32 return parameter.values
35 def deserialize_value(module, parameter_state):
36 """Deserialize a single basf2 module paramater"""
37 if parameter_state[
'name'] ==
'path' and module.type() ==
'SubEvent':
38 return deserialize_path(parameter_state[
'values'])
40 return parameter_state[
'values']
43 def serialize_conditions(module):
44 """Serialize all conditions attached to a basf2 module"""
47 for condition
in module.get_all_conditions():
48 condition_list.append({
'value': condition.get_value(),
49 'operator': int(condition.get_operator()),
50 'path': serialize_path(condition.get_path()),
51 'option': int(condition.get_after_path())})
56 def deserialize_conditions(module, module_state):
57 """Deserialize all conditions for a given basf2 module"""
58 conditions = module_state[
'condition']
59 for cond
in conditions:
60 module.if_value(str(pybasf2.ConditionOperator.values[cond[
'operator']]) + str(cond[
'value']),
61 deserialize_path(cond[
'path']), pybasf2.AfterConditionPath.values[cond[
'option']])
64 def serialize_module(module):
65 """Serialize a basf2 module into a python dictionary. Doesn't work for python modules"""
66 if module.type() ==
'' or module.type() ==
'PyModule':
68 f
"Module '{module.name()}' doesn't have a type or is a Python module! Note that --dump-path cannot work properly " +
69 "with basf2 modules written in Python.")
71 'name': module.name(),
72 'type': module.type(),
73 'flag': module.has_properties(pybasf2.ModulePropFlags.PARALLELPROCESSINGCERTIFIED),
74 'parameters': [{
'name': parameter.name,
'values': serialize_value(module, parameter)}
75 for parameter
in module.available_params()
76 if parameter.setInSteering
or module.type() ==
'SubEvent'],
77 'condition': serialize_conditions(module)
if module.has_condition()
else None}
80 def deserialize_module(module_state):
81 """Deserialize a basf2 module from a python dictionary"""
82 module = pybasf2._register_module(module_state[
'type'])
83 module.set_name(module_state[
'name'])
84 if 'condition' in module_state
and module_state[
'condition']
is not None:
85 deserialize_conditions(module, module_state)
86 if 'flag' in module_state
and module_state[
'flag']:
88 module.set_property_flags(pybasf2.ModulePropFlags.PARALLELPROCESSINGCERTIFIED)
89 for parameter_state
in module_state[
'parameters']:
90 module.param(parameter_state[
'name'],
91 deserialize_value(module, parameter_state))
95 def serialize_path(path):
96 """Serialize a basf2 Path into a python dictionary"""
97 return {
'modules': [serialize_module(module)
for module
in path.modules()]}
100 def deserialize_path(path_state):
101 """Deserialize a basf2 Path from a python dictionary"""
102 path = pybasf2.Path()
103 for module_state
in path_state[
'modules']:
104 module = deserialize_module(module_state)
105 path.add_module(module)
109 def get_path_from_file(path_filename):
110 """Read a path from a given pickle file"""
111 with open(path_filename,
'br')
as f:
112 return deserialize_path(_pickle.load(f))
115 def write_path_to_file(path, filename):
116 """Write a path to a given pickle file"""
117 with open(filename,
'bw')
as f:
118 _pickle.dump(serialize_path(path), f)
121 def check_pickle_path(path):
122 """Check if the path to be executed should be pickled or unpickled.
123 This function is used by basf2.process to handle the ``--dump-path`` and
124 ``--execute-path`` arguments to ``basf2``
127 pickle_filename = pybasf2.get_pickle_path()
128 if pickle_filename ==
'':
132 if _os.path.isfile(pickle_filename)
and path
is None:
133 path = get_path_from_file(pickle_filename)
134 with open(pickle_filename,
"br")
as f:
135 loaded = _pickle.load(f)
136 if 'state' in loaded:
137 pybasf2.B2INFO(
"Pickled path contains a state object. Activating pickled state.")
138 for name, args, kwargs
in loaded[
'state']:
139 getattr(_sys.modules[__name__], name)(*args, **kwargs)
143 elif path
is not None:
144 write_path_to_file(path, pickle_filename)
147 pybasf2.B2FATAL(
"Couldn't open path-file '" + pickle_filename +
"' and no steering file provided.")
150 def make_code_pickable(code):
152 Sometimes it is necessary to execute code which won't be pickled if a user dumps the basf2 path
153 and wants to execute it later. Using the pickable_basf2 module all calls to basf2 functions
154 are recorded. Now if a user has to execute code outside of basf2, e.g. modifying objects in the ROOT namespace,
155 this won't be pickled. By wrapping the code in this function it is technically a call to a basf2 function
156 and will be pickled again. Problem solved.
158 exec(code, globals())