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':
67 raise RuntimeError(
"Module '%s' doesn't have a type or is a Python module! Note that --dump-path cannot work"
68 "properly with basf2 modules written in Python." % (module.name()))
70 'name': module.name(),
71 'type': module.type(),
72 'flag': module.has_properties(pybasf2.ModulePropFlags.PARALLELPROCESSINGCERTIFIED),
73 'parameters': [{
'name': parameter.name,
'values': serialize_value(module, parameter)}
74 for parameter
in module.available_params()
75 if parameter.setInSteering
or module.type() ==
'SubEvent'],
76 'condition': serialize_conditions(module)
if module.has_condition()
else None}
79 def deserialize_module(module_state):
80 """Deserialize a basf2 module from a python dictionary"""
81 module = pybasf2._register_module(module_state[
'type'])
82 module.set_name(module_state[
'name'])
83 if 'condition' in module_state
and module_state[
'condition']
is not None:
84 deserialize_conditions(module, module_state)
85 if 'flag' in module_state
and module_state[
'flag']:
87 module.set_property_flags(pybasf2.ModulePropFlags.PARALLELPROCESSINGCERTIFIED)
88 for parameter_state
in module_state[
'parameters']:
89 module.param(parameter_state[
'name'],
90 deserialize_value(module, parameter_state))
94 def serialize_path(path):
95 """Serialize a basf2 Path into a python dictionary"""
96 return {
'modules': [serialize_module(module)
for module
in path.modules()]}
99 def deserialize_path(path_state):
100 """Deserialize a basf2 Path from a python dictionary"""
101 path = pybasf2.Path()
102 for module_state
in path_state[
'modules']:
103 module = deserialize_module(module_state)
104 path.add_module(module)
108 def get_path_from_file(path_filename):
109 """Read a path from a given pickle file"""
110 with open(path_filename,
'br')
as f:
111 return deserialize_path(_pickle.load(f))
114 def write_path_to_file(path, filename):
115 """Write a path to a given pickle file"""
116 with open(filename,
'bw')
as f:
117 _pickle.dump(serialize_path(path), f)
120 def check_pickle_path(path):
121 """Check if the path to be executed should be pickled or unpickled.
122 This function is used by basf2.process to handle the ``--dump-path`` and
123 ``--execute-path`` arguments to ``basf2``
126 pickle_filename = pybasf2.get_pickle_path()
127 if pickle_filename ==
'':
131 if _os.path.isfile(pickle_filename)
and path
is None:
132 path = get_path_from_file(pickle_filename)
133 with open(pickle_filename,
"br")
as f:
134 loaded = _pickle.load(f)
135 if 'state' in loaded:
136 pybasf2.B2INFO(
"Pickled path contains a state object. Activating pickled state.")
137 for name, args, kwargs
in loaded[
'state']:
138 getattr(_sys.modules[__name__], name)(*args, **kwargs)
142 elif path
is not None:
143 write_path_to_file(path, pickle_filename)
146 pybasf2.B2FATAL(
"Couldn't open path-file '" + pickle_filename +
"' and no steering file provided.")
149 def make_code_pickable(code):
151 Sometimes it is necessary to execute code which won't be pickled if a user dumps the basf2 path
152 and wants to execute it later. Using the pickable_basf2 module all calls to basf2 functions
153 are recorded. Now if a user has to execute code outside of basf2, e.g. modifying objects in the ROOT namespace,
154 this won't be pickled. By wrapping the code in this function it is technically a call to a basf2 function
155 and will be pickled again. Problem solved.
157 exec(code, globals())