DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
configuration_handler.py
Go to the documentation of this file.
1import os
2from typing import Any, Dict, List
3
4import conffwk
5
6
8 # Contains the full configuration of a single configuration instance
9 def __init__(self, configuration_file_name: str):
10 """Configuration handler object, essentially a wrapper around a conffwk.Configuration object
11
12 Arguments:
13 configuration_file_name -- name of the configuration .database.xml file to open
14 """
15
16 # Load configuration
17 self._configuration = self.__open_configuration(configuration_file_name)
18
19 # To be filled with ALL config objects (as DALs)
20 self._loaded_dals = []
21 # Fills self._loaded_dals,
23
24 def __open_configuration(self, configuration_file_name: str)->conffwk.Configuration:
25 '''Opens configuration object safely '''
26 if not os.path.isfile(configuration_file_name):
27 raise Exception(f"Cannot find file: {configuration_file_name}")
28
29 try:
30 configuration = conffwk.Configuration(f"oksconflibs:{configuration_file_name}")
31 except Exception as e:
32 raise e
33
34 return configuration
35
36 def __cache_all_conf_objects(self)->None:
37 """Adds all loaded dals to self._loaded_dals
38 """
39 for conf_class in self._configuration.classes():
40 for conf_obj in self._configuration.get_dals(conf_class):
41 if conf_obj in self._loaded_dals: continue
42
43 self._loaded_dals.append(conf_obj)
44
45 #============================== Getters + Setters ==============================#
46 def get_relationships_for_conf_object(self, conf_object)->List[Any]:
47 """For a given configuration object, return all related objects
48
49 Arguments:
50 conf_object -- Any DAL object
51
52 Returns:
53 List of related objects
54 """
55 relations = self.get_related_classes(conf_object.className())
56
57 relations_list = []
58
59 # Loop over relations
60 for rel, rel_info in relations.items():
61 rel_val = getattr(conf_object, rel)
62 # Hacky but pybind got fussy about casting list(dal)
63 if not isinstance(rel_val, list):
64 rel_val = [rel_val]
65
66 relations_list.append({rel: [v for v in rel_val if v is not None], 'rel_info': rel_info})
67
68 return relations_list
69
70 def get_conf_objects_class(self, conf_class: str):
71 """Get all configuration objects of a given class
72
73 Arguments:
74 conf_class -- Coniguration class to get objects of
75
76 Returns:
77 List of configuration objects of the given class
78 """
79 return self._configuration.get_dals(conf_class)
80
81 def get_all_conf_classes(self)->Dict[str, Any]:
82 """Gets all classes + objects of that class in the configuration
83
84 Returns:
85 dictionary of class : dal objects
86 """
87 return {conf_class: self.get_conf_objects_class(conf_class)
88 for conf_class in self._configuration.classes()}
89
90 def get_related_classes(self, class_id: str)->List[str]:
91 """Get all related to classes to a given input class
92
93 Arguments:
94 class_id -- Name of class
95
96 Returns:
97 List of all related classses
98 """
99 return self._configuration.relations(class_id, True)
100
101 def get_inherited_classes(self, class_id: str)->List[str]:
102 inherited_classes = [class_ for class_ in self._configuration.classes()\
103 if self._configuration.is_subclass(class_, class_id)]
104 return inherited_classes
105
106
107 @property
108 def configuration(self)->conffwk.Configuration:
109 """Access the underlying configuration object
110 """
111 return self._configuration
112
113 @configuration.setter
114 def configuration(self)->None:
115 """dummy method in case I try to do something silly
116 """
117 raise NotImplementedError(f"Configuration object is not mutable, please create new object")
118
119 @property
120 def conf_obj_list(self):
121 """List of loaded in dals
122 """
123 return self._loaded_dals
124
125 def get_obj(self, class_id: str, uid: str):
126 """Get a particular configuration object
127
128 Arguments:
129 class_id -- Class name
130 uid -- Unique object ID
131
132 Returns:
133 DAL object satisfying the input
134 """
135 return self.configurationconfiguration.get_obj(class_id, uid)
136
137 def commit(self, update_message: str):
138 """Commit changes to the database
139
140 Arguments:
141 update_message -- Add message to the update
142 """
143 self.configurationconfiguration.commit(update_message)
144
145 @property
146 def n_dals(self)->int:
147 """Lists the total number of loaded objects
148 _description_
149 """
150 return len(self._loaded_dals)
151
152 def add_new_conf_obj(self, class_id: str, uid: str):
153 """Add new configuration object
154
155 Arguments:
156 class_id -- Class name
157 uid -- Unique object ID
158 """
159 self.configurationconfiguration.create_obj(class_id, uid, at=self.configurationconfiguration.active_database)
160 config_as_dal = self.configurationconfiguration.get_dal(class_id, uid)
161 self.configurationconfiguration.update_dal(config_as_dal)
162 self._loaded_dals.append(config_as_dal)
163
164 def destroy_conf_obj(self, class_id: str, uid: str):
165 """Destroy a configuration object
166
167 Arguments:
168 class_id -- class name
169 uid -- unique object ID
170 """
171 dal = self.configurationconfiguration.get_dal(class_id, uid)
172 self.configurationconfiguration.destroy_dal(dal)
173 self._loaded_dals.remove(dal)
174
175 def modify_relationship(self, class_id, uid, relationship_name: str, updated_value,
176 append: bool=False):
177 """Modify TODO: EDIT THIS
178
179 :param class_id: _description_
180 :type class_id: _type_
181 :param uid: _description_
182 :type uid: _type_
183 :param relationship_name: _description_
184 :type relationship_name: str
185 :param updated_value: _description_
186 :type updated_value: _type_
187 :param append: _description_, defaults to False
188 :type append: bool, optional
189 """
190 # Firstly we need to find the relationship this is referring to
191 selected_dal = self.configurationconfiguration.get_dal(class_id, uid)
192 # Okay need a better way of doing this...
193 rel_list = self.get_relationships_for_conf_object(selected_dal)
194
195 for relations in rel_list:
196 # Need to find our dal
197 if list(relations.keys())[0] != relationship_name:
198 continue
199
200 # Next we need to check the type of our object is okay
201 if updated_value not in self.get_conf_objects_class(relations['rel_info']['type']):
202 raise Exception(updated_value)
203 # raise TypeError(f"Cannot use object {updated_value} for relation expecting type {relations['rel_info']['type']}")
204
205 # Need to make sure everything is typed correctly
206 if append and relations['rel_info']['multivalue']:
207 rel = list(relations.items)[0]
208 rel.append(updated_value)
209
210 elif relations['rel_info']['multivalue']:
211 rel = [updated_value]
212 else:
213 rel = updated_value
214
215 # Should update the dal
216 setattr(selected_dal, relationship_name, rel)
217 self.configurationconfiguration.update_dal(selected_dal)
218
219
220 return
221
222 raise RuntimeError(f"Cannot find relationship with name {relationship_name}")
conffwk.Configuration __open_configuration(self, str configuration_file_name)
modify_relationship(self, class_id, uid, str relationship_name, updated_value, bool append=False)