src.fairreckitlib.core.config.config_factories

This module contains the (base) factories that are used in other packages.

Classes:

BaseFactory: base class for all factories.
Factory: class that instantiates new objects (a leaf).
GroupFactory: class that groups other factories (a branch).

Functions:

create_factory_from_list: create object factory from list of object (param) creation tuples.
resolve_factory: resolve the object factory from the name of the object.

This program has been developed by students from the bachelor Computer Science at Utrecht University within the Software Project course. © Copyright Utrecht University (Department of Information and Computing Sciences)

  1"""This module contains the (base) factories that are used in other packages.
  2
  3Classes:
  4
  5    BaseFactory: base class for all factories.
  6    Factory: class that instantiates new objects (a leaf).
  7    GroupFactory: class that groups other factories (a branch).
  8
  9Functions:
 10
 11    create_factory_from_list: create object factory from list of object (param) creation tuples.
 12    resolve_factory: resolve the object factory from the name of the object.
 13
 14This program has been developed by students from the bachelor Computer Science at
 15Utrecht University within the Software Project course.
 16© Copyright Utrecht University (Department of Information and Computing Sciences)
 17"""
 18
 19from abc import ABCMeta, abstractmethod
 20from typing import Any, Callable, Dict, List, Optional, Tuple, Union
 21
 22from ..core_constants import KEY_NAME, KEY_PARAMS
 23from .config_parameters import ConfigParameters, create_empty_parameters
 24
 25FUNC_CREATE_OBJ = 'f_create_obj'
 26FUNC_CREATE_PARAMS = 'f_create_params'
 27
 28
 29class BaseFactory(metaclass=ABCMeta):
 30    """Base class for all FairRecKit experiment factories.
 31
 32    The abstraction is intended to support functionality for a tree-like structure.
 33    The actual factory is a leaf and a group of factories that belong together a branch.
 34
 35    Public methods:
 36
 37    get_available
 38    get_available_names
 39    get_name
 40    is_available
 41    """
 42
 43    def __init__(self, factory_name: str):
 44        """Construct the base factory.
 45
 46        Args:
 47            factory_name: the name of the factory.
 48        """
 49        self.factory_name = factory_name
 50        self.factory = {}
 51
 52    @abstractmethod
 53    def get_available(self) -> Any:
 54        """Get the available objects in the factory.
 55
 56        The availability return type depends on the derived class.
 57        """
 58        raise NotImplementedError()
 59
 60    def get_available_names(self) -> List[str]:
 61        """Get the names that are available in the factory.
 62
 63        Returns:
 64            a list of names that is available.
 65        """
 66        result = []
 67
 68        for name, _ in self.factory.items():
 69            result.append(name)
 70
 71        return result
 72
 73    def get_name(self) -> str:
 74        """Get the name of the factory.
 75
 76        Returns:
 77            the factory name.
 78        """
 79        return self.factory_name
 80
 81    def get_num_entries(self) -> int:
 82        """Get the number of entries present in the factory.
 83
 84        Returns:
 85            the amount of entries.
 86        """
 87        return len(self.factory)
 88
 89    @abstractmethod
 90    def is_obj_available(self, obj_name: str) -> bool:
 91        """Is the object with the specified name available.
 92
 93        Args:
 94            obj_name: the name of the object to query for availability.
 95
 96        Returns:
 97            whether the object is available.
 98        """
 99        raise NotImplementedError()
100
101
102class Factory(BaseFactory):
103    """The factory that implements object and parameters creation.
104
105    Public methods:
106
107    add_obj
108    create
109    create_params
110    """
111
112    def add_obj(self,
113                obj_name: str,
114                func_create_obj: Callable[[str, Dict[str, Any]], Any],
115                func_create_obj_params: Optional[Callable[[], ConfigParameters]]=None
116                ) -> None:
117        """Add object with associated parameter creation to the factory.
118
119        Parameter creation is optional and should be None if the object has no parameters.
120
121        Args:
122            obj_name: the name of the object
123            func_create_obj: the function that creates and returns a new object.
124            func_create_obj_params: the function that creates and returns the parameters
125                that are associated with a newly created object or None when the object
126                has no parameters.
127
128        Raises:
129            KeyError: when the object name is already present in the factory.
130        """
131        if obj_name in self.factory:
132            raise KeyError('Factory ' + self.factory_name,
133                           ': object already exists: ' + obj_name)
134
135        if func_create_obj_params is None:
136            func_create_obj_params = create_empty_parameters
137
138        self.factory[obj_name] = {
139            FUNC_CREATE_OBJ: func_create_obj,
140            FUNC_CREATE_PARAMS: func_create_obj_params
141        }
142
143    def create(self, obj_name: str, obj_params: Dict[str, Any]=None, **kwargs) -> Any:
144        """Create and return a new object with the specified name.
145
146        The specified parameters are expected to be of the same structure as the defaults
147        of the ConfigParameters that are associated with the desired object. When no parameters
148        are specified it will use the object's defaults.
149
150        Args:
151            obj_name: the name of the object to create.
152            obj_params: the parameters of the object.
153
154        Keyword Args:
155            Any: extra arguments that need to be passed to the object on creation.
156
157        Returns:
158            the created object or None when it does not exist.
159        """
160        if obj_name not in self.factory:
161            return None
162
163        func_create_obj = self.factory[obj_name][FUNC_CREATE_OBJ]
164        if obj_params is None:
165            obj_params = self.create_params(obj_name).get_defaults()
166
167        return func_create_obj(obj_name, dict(obj_params), **kwargs)
168
169    def create_params(self, obj_name: str) -> ConfigParameters:
170        """Create parameters for the object with the specified name.
171
172        Args:
173            obj_name: name of the object to create parameters for.
174
175        Returns:
176            the configuration parameters of the object or empty parameters when it does not exist.
177        """
178        if obj_name not in self.factory:
179            return create_empty_parameters()
180
181        return self.on_create_params(obj_name)
182
183    def on_create_params(self, obj_name: str) -> ConfigParameters:
184        """Create parameters for the object with the specified name.
185
186        Args:
187            obj_name: name of the object to create parameters for.
188
189        Returns:
190            the configuration parameters of the object or empty parameters when it does not exist.
191        """
192        return self.factory[obj_name][FUNC_CREATE_PARAMS]()
193
194    def get_available(self) -> List[Dict[str, Dict[str, Any]]]:
195        """Get the availability of all object names and their parameters.
196
197        Each object in the factory has a name and parameters that consists of
198        a dictionary with name-value pairs.
199
200        Returns:
201            a list of dictionary entries that includes the name and the parameters.
202        """
203        obj_list = []
204
205        for obj_name, _ in self.factory.items():
206            obj_list.append({
207                KEY_NAME: obj_name,
208                KEY_PARAMS: self.on_create_params(obj_name).to_dict()
209            })
210
211        return obj_list
212
213    def is_obj_available(self, obj_name: str) -> bool:
214        """Is the object with the specified name available.
215
216        Checks the object for existing in this factory.
217
218        Args:
219            obj_name: the name of the object to query for availability.
220
221        Returns:
222            whether the object is available.
223        """
224        return obj_name in self.factory is not None
225
226
227class GroupFactory(BaseFactory):
228    """The factory that groups other factories together.
229
230    Public methods:
231
232    add_factory
233    get_factory
234    get_sub_availability
235    """
236
237    def add_factory(self, factory: BaseFactory) -> None:
238        """Add the specified factory to the group.
239
240        The name of the factory is used as the key.
241
242        Args:
243            factory: to add to the group.
244
245        Raises:
246            KeyError: when the name of the factory already exists in the group.
247        """
248        factory_name = factory.get_name()
249        if factory_name in self.factory:
250            raise KeyError('Factory ' + self.factory_name,
251                           ': factory already exists: ' + factory_name)
252
253        self.factory[factory_name] = factory
254
255    def get_available(self) -> Dict[str, Any]:
256        """Get the availability of all factories in the group.
257
258        Each factory has a name and availability that depends on the
259        type of the factory. Effectively this will generate a tree-like
260        structure of the factory's availability.
261
262        Returns:
263            a dictionary with factory name and availability pairs.
264        """
265        factory_list = {}
266
267        for factory_name, factory in self.factory.items():
268            factory_list[factory_name] = factory.get_available()
269
270        return factory_list
271
272    def get_factory(self, factory_name: str) -> BaseFactory:
273        """Get the factory with the specified name.
274
275        Args:
276            factory_name: the name of the factory to retrieve
277
278        Returns:
279            the requested factory or None when not available.
280        """
281        return self.factory.get(factory_name)
282
283    def get_sub_availability(
284            self,
285            sub_factory_name: str,
286            sub_type: str = None) -> Dict[str, Any]:
287        """Get the sub availability from the factory with the specified name (and type).
288
289        Args:
290            sub_factory_name: the name of the sub-factory to query for availability.
291            sub_type: the subtype of the sub-factory to query for availability or None
292                for the complete availability.
293
294        Returns:
295            a dictionary containing the availability of the sub-factory (type).
296        """
297        sub_factory = self.get_factory(sub_factory_name)
298        if sub_type is None:
299            return sub_factory.get_available()
300
301        type_factory = sub_factory.get_factory(sub_type)
302        if type_factory is None:
303            return {}
304
305        return type_factory.get_available()
306
307    def is_obj_available(self, obj_name: str) -> bool:
308        """Is the object with the specified name available.
309
310        Checks the object for existing in any of the child factories.
311
312        Args:
313            obj_name: the name of the object to query for availability.
314
315        Returns:
316            whether the object is available.
317        """
318        for _, factory in self.factory.items():
319            if factory.is_obj_available(obj_name):
320                return True
321
322        return False
323
324
325def create_factory_from_list(
326        factory_name: str,
327        obj_tuple_list: List[Tuple[
328            str,
329            Callable[[str, Dict[str, Any]], Any],
330            Optional[Callable[[], ConfigParameters]]
331        ]]) -> Factory:
332    """Create and return the factory with the specified tuple entries.
333
334    Each tuple in the list consists of three things; the name of the object,
335    the object creation function and the parameter creation function.
336
337    Args:
338        factory_name: the name of the factory to create.
339        obj_tuple_list: a list of object tuples to add after factory creation.
340
341    Returns:
342        the factory with the added objects.
343    """
344    factory = Factory(factory_name)
345
346    for (obj_name, func_create_obj, func_create_obj_params) in obj_tuple_list:
347        factory.add_obj(
348            obj_name,
349            func_create_obj,
350            func_create_obj_params
351        )
352
353    return factory
354
355
356def resolve_factory(
357        obj_name: str,
358        obj_factory: Union[Factory, GroupFactory]) -> Optional[Factory]:
359    """Resolve the object factory from the name of the object.
360
361    Args:
362        obj_name: the name of the object.
363        obj_factory: the (group) factory to query for the object.
364
365    Returns:
366        the resolved factory or None when not found.
367    """
368    if isinstance(obj_factory, Factory):
369        return obj_factory if obj_factory.is_obj_available(obj_name) else None
370
371    for factory_name in obj_factory.get_available_names():
372        obj_sub_factory = obj_factory.get_factory(factory_name)
373        if obj_sub_factory.is_obj_available(obj_name):
374            if isinstance(obj_sub_factory, GroupFactory):
375                return resolve_factory(obj_name, obj_sub_factory)
376
377            return obj_sub_factory
378
379    return None
class BaseFactory:
 30class BaseFactory(metaclass=ABCMeta):
 31    """Base class for all FairRecKit experiment factories.
 32
 33    The abstraction is intended to support functionality for a tree-like structure.
 34    The actual factory is a leaf and a group of factories that belong together a branch.
 35
 36    Public methods:
 37
 38    get_available
 39    get_available_names
 40    get_name
 41    is_available
 42    """
 43
 44    def __init__(self, factory_name: str):
 45        """Construct the base factory.
 46
 47        Args:
 48            factory_name: the name of the factory.
 49        """
 50        self.factory_name = factory_name
 51        self.factory = {}
 52
 53    @abstractmethod
 54    def get_available(self) -> Any:
 55        """Get the available objects in the factory.
 56
 57        The availability return type depends on the derived class.
 58        """
 59        raise NotImplementedError()
 60
 61    def get_available_names(self) -> List[str]:
 62        """Get the names that are available in the factory.
 63
 64        Returns:
 65            a list of names that is available.
 66        """
 67        result = []
 68
 69        for name, _ in self.factory.items():
 70            result.append(name)
 71
 72        return result
 73
 74    def get_name(self) -> str:
 75        """Get the name of the factory.
 76
 77        Returns:
 78            the factory name.
 79        """
 80        return self.factory_name
 81
 82    def get_num_entries(self) -> int:
 83        """Get the number of entries present in the factory.
 84
 85        Returns:
 86            the amount of entries.
 87        """
 88        return len(self.factory)
 89
 90    @abstractmethod
 91    def is_obj_available(self, obj_name: str) -> bool:
 92        """Is the object with the specified name available.
 93
 94        Args:
 95            obj_name: the name of the object to query for availability.
 96
 97        Returns:
 98            whether the object is available.
 99        """
100        raise NotImplementedError()

Base class for all FairRecKit experiment factories.

The abstraction is intended to support functionality for a tree-like structure. The actual factory is a leaf and a group of factories that belong together a branch.

Public methods:

get_available get_available_names get_name is_available

BaseFactory(factory_name: str)
44    def __init__(self, factory_name: str):
45        """Construct the base factory.
46
47        Args:
48            factory_name: the name of the factory.
49        """
50        self.factory_name = factory_name
51        self.factory = {}

Construct the base factory.

Args: factory_name: the name of the factory.

@abstractmethod
def get_available(self) -> Any:
53    @abstractmethod
54    def get_available(self) -> Any:
55        """Get the available objects in the factory.
56
57        The availability return type depends on the derived class.
58        """
59        raise NotImplementedError()

Get the available objects in the factory.

The availability return type depends on the derived class.

def get_available_names(self) -> List[str]:
61    def get_available_names(self) -> List[str]:
62        """Get the names that are available in the factory.
63
64        Returns:
65            a list of names that is available.
66        """
67        result = []
68
69        for name, _ in self.factory.items():
70            result.append(name)
71
72        return result

Get the names that are available in the factory.

Returns: a list of names that is available.

def get_name(self) -> str:
74    def get_name(self) -> str:
75        """Get the name of the factory.
76
77        Returns:
78            the factory name.
79        """
80        return self.factory_name

Get the name of the factory.

Returns: the factory name.

def get_num_entries(self) -> int:
82    def get_num_entries(self) -> int:
83        """Get the number of entries present in the factory.
84
85        Returns:
86            the amount of entries.
87        """
88        return len(self.factory)

Get the number of entries present in the factory.

Returns: the amount of entries.

@abstractmethod
def is_obj_available(self, obj_name: str) -> bool:
 90    @abstractmethod
 91    def is_obj_available(self, obj_name: str) -> bool:
 92        """Is the object with the specified name available.
 93
 94        Args:
 95            obj_name: the name of the object to query for availability.
 96
 97        Returns:
 98            whether the object is available.
 99        """
100        raise NotImplementedError()

Is the object with the specified name available.

Args: obj_name: the name of the object to query for availability.

Returns: whether the object is available.

class Factory(BaseFactory):
103class Factory(BaseFactory):
104    """The factory that implements object and parameters creation.
105
106    Public methods:
107
108    add_obj
109    create
110    create_params
111    """
112
113    def add_obj(self,
114                obj_name: str,
115                func_create_obj: Callable[[str, Dict[str, Any]], Any],
116                func_create_obj_params: Optional[Callable[[], ConfigParameters]]=None
117                ) -> None:
118        """Add object with associated parameter creation to the factory.
119
120        Parameter creation is optional and should be None if the object has no parameters.
121
122        Args:
123            obj_name: the name of the object
124            func_create_obj: the function that creates and returns a new object.
125            func_create_obj_params: the function that creates and returns the parameters
126                that are associated with a newly created object or None when the object
127                has no parameters.
128
129        Raises:
130            KeyError: when the object name is already present in the factory.
131        """
132        if obj_name in self.factory:
133            raise KeyError('Factory ' + self.factory_name,
134                           ': object already exists: ' + obj_name)
135
136        if func_create_obj_params is None:
137            func_create_obj_params = create_empty_parameters
138
139        self.factory[obj_name] = {
140            FUNC_CREATE_OBJ: func_create_obj,
141            FUNC_CREATE_PARAMS: func_create_obj_params
142        }
143
144    def create(self, obj_name: str, obj_params: Dict[str, Any]=None, **kwargs) -> Any:
145        """Create and return a new object with the specified name.
146
147        The specified parameters are expected to be of the same structure as the defaults
148        of the ConfigParameters that are associated with the desired object. When no parameters
149        are specified it will use the object's defaults.
150
151        Args:
152            obj_name: the name of the object to create.
153            obj_params: the parameters of the object.
154
155        Keyword Args:
156            Any: extra arguments that need to be passed to the object on creation.
157
158        Returns:
159            the created object or None when it does not exist.
160        """
161        if obj_name not in self.factory:
162            return None
163
164        func_create_obj = self.factory[obj_name][FUNC_CREATE_OBJ]
165        if obj_params is None:
166            obj_params = self.create_params(obj_name).get_defaults()
167
168        return func_create_obj(obj_name, dict(obj_params), **kwargs)
169
170    def create_params(self, obj_name: str) -> ConfigParameters:
171        """Create parameters for the object with the specified name.
172
173        Args:
174            obj_name: name of the object to create parameters for.
175
176        Returns:
177            the configuration parameters of the object or empty parameters when it does not exist.
178        """
179        if obj_name not in self.factory:
180            return create_empty_parameters()
181
182        return self.on_create_params(obj_name)
183
184    def on_create_params(self, obj_name: str) -> ConfigParameters:
185        """Create parameters for the object with the specified name.
186
187        Args:
188            obj_name: name of the object to create parameters for.
189
190        Returns:
191            the configuration parameters of the object or empty parameters when it does not exist.
192        """
193        return self.factory[obj_name][FUNC_CREATE_PARAMS]()
194
195    def get_available(self) -> List[Dict[str, Dict[str, Any]]]:
196        """Get the availability of all object names and their parameters.
197
198        Each object in the factory has a name and parameters that consists of
199        a dictionary with name-value pairs.
200
201        Returns:
202            a list of dictionary entries that includes the name and the parameters.
203        """
204        obj_list = []
205
206        for obj_name, _ in self.factory.items():
207            obj_list.append({
208                KEY_NAME: obj_name,
209                KEY_PARAMS: self.on_create_params(obj_name).to_dict()
210            })
211
212        return obj_list
213
214    def is_obj_available(self, obj_name: str) -> bool:
215        """Is the object with the specified name available.
216
217        Checks the object for existing in this factory.
218
219        Args:
220            obj_name: the name of the object to query for availability.
221
222        Returns:
223            whether the object is available.
224        """
225        return obj_name in self.factory is not None

The factory that implements object and parameters creation.

Public methods:

add_obj create create_params

def add_obj( self, obj_name: str, func_create_obj: Callable[[str, Dict[str, Any]], Any], func_create_obj_params: Optional[Callable[[], src.fairreckitlib.core.config.config_parameters.ConfigParameters]] = None) -> None:
113    def add_obj(self,
114                obj_name: str,
115                func_create_obj: Callable[[str, Dict[str, Any]], Any],
116                func_create_obj_params: Optional[Callable[[], ConfigParameters]]=None
117                ) -> None:
118        """Add object with associated parameter creation to the factory.
119
120        Parameter creation is optional and should be None if the object has no parameters.
121
122        Args:
123            obj_name: the name of the object
124            func_create_obj: the function that creates and returns a new object.
125            func_create_obj_params: the function that creates and returns the parameters
126                that are associated with a newly created object or None when the object
127                has no parameters.
128
129        Raises:
130            KeyError: when the object name is already present in the factory.
131        """
132        if obj_name in self.factory:
133            raise KeyError('Factory ' + self.factory_name,
134                           ': object already exists: ' + obj_name)
135
136        if func_create_obj_params is None:
137            func_create_obj_params = create_empty_parameters
138
139        self.factory[obj_name] = {
140            FUNC_CREATE_OBJ: func_create_obj,
141            FUNC_CREATE_PARAMS: func_create_obj_params
142        }

Add object with associated parameter creation to the factory.

Parameter creation is optional and should be None if the object has no parameters.

Args: obj_name: the name of the object func_create_obj: the function that creates and returns a new object. func_create_obj_params: the function that creates and returns the parameters that are associated with a newly created object or None when the object has no parameters.

Raises: KeyError: when the object name is already present in the factory.

def create(self, obj_name: str, obj_params: Dict[str, Any] = None, **kwargs) -> Any:
144    def create(self, obj_name: str, obj_params: Dict[str, Any]=None, **kwargs) -> Any:
145        """Create and return a new object with the specified name.
146
147        The specified parameters are expected to be of the same structure as the defaults
148        of the ConfigParameters that are associated with the desired object. When no parameters
149        are specified it will use the object's defaults.
150
151        Args:
152            obj_name: the name of the object to create.
153            obj_params: the parameters of the object.
154
155        Keyword Args:
156            Any: extra arguments that need to be passed to the object on creation.
157
158        Returns:
159            the created object or None when it does not exist.
160        """
161        if obj_name not in self.factory:
162            return None
163
164        func_create_obj = self.factory[obj_name][FUNC_CREATE_OBJ]
165        if obj_params is None:
166            obj_params = self.create_params(obj_name).get_defaults()
167
168        return func_create_obj(obj_name, dict(obj_params), **kwargs)

Create and return a new object with the specified name.

The specified parameters are expected to be of the same structure as the defaults of the ConfigParameters that are associated with the desired object. When no parameters are specified it will use the object's defaults.

Args: obj_name: the name of the object to create. obj_params: the parameters of the object.

Keyword Args: Any: extra arguments that need to be passed to the object on creation.

Returns: the created object or None when it does not exist.

def create_params( self, obj_name: str) -> src.fairreckitlib.core.config.config_parameters.ConfigParameters:
170    def create_params(self, obj_name: str) -> ConfigParameters:
171        """Create parameters for the object with the specified name.
172
173        Args:
174            obj_name: name of the object to create parameters for.
175
176        Returns:
177            the configuration parameters of the object or empty parameters when it does not exist.
178        """
179        if obj_name not in self.factory:
180            return create_empty_parameters()
181
182        return self.on_create_params(obj_name)

Create parameters for the object with the specified name.

Args: obj_name: name of the object to create parameters for.

Returns: the configuration parameters of the object or empty parameters when it does not exist.

def on_create_params( self, obj_name: str) -> src.fairreckitlib.core.config.config_parameters.ConfigParameters:
184    def on_create_params(self, obj_name: str) -> ConfigParameters:
185        """Create parameters for the object with the specified name.
186
187        Args:
188            obj_name: name of the object to create parameters for.
189
190        Returns:
191            the configuration parameters of the object or empty parameters when it does not exist.
192        """
193        return self.factory[obj_name][FUNC_CREATE_PARAMS]()

Create parameters for the object with the specified name.

Args: obj_name: name of the object to create parameters for.

Returns: the configuration parameters of the object or empty parameters when it does not exist.

def get_available(self) -> List[Dict[str, Dict[str, Any]]]:
195    def get_available(self) -> List[Dict[str, Dict[str, Any]]]:
196        """Get the availability of all object names and their parameters.
197
198        Each object in the factory has a name and parameters that consists of
199        a dictionary with name-value pairs.
200
201        Returns:
202            a list of dictionary entries that includes the name and the parameters.
203        """
204        obj_list = []
205
206        for obj_name, _ in self.factory.items():
207            obj_list.append({
208                KEY_NAME: obj_name,
209                KEY_PARAMS: self.on_create_params(obj_name).to_dict()
210            })
211
212        return obj_list

Get the availability of all object names and their parameters.

Each object in the factory has a name and parameters that consists of a dictionary with name-value pairs.

Returns: a list of dictionary entries that includes the name and the parameters.

def is_obj_available(self, obj_name: str) -> bool:
214    def is_obj_available(self, obj_name: str) -> bool:
215        """Is the object with the specified name available.
216
217        Checks the object for existing in this factory.
218
219        Args:
220            obj_name: the name of the object to query for availability.
221
222        Returns:
223            whether the object is available.
224        """
225        return obj_name in self.factory is not None

Is the object with the specified name available.

Checks the object for existing in this factory.

Args: obj_name: the name of the object to query for availability.

Returns: whether the object is available.

class GroupFactory(BaseFactory):
228class GroupFactory(BaseFactory):
229    """The factory that groups other factories together.
230
231    Public methods:
232
233    add_factory
234    get_factory
235    get_sub_availability
236    """
237
238    def add_factory(self, factory: BaseFactory) -> None:
239        """Add the specified factory to the group.
240
241        The name of the factory is used as the key.
242
243        Args:
244            factory: to add to the group.
245
246        Raises:
247            KeyError: when the name of the factory already exists in the group.
248        """
249        factory_name = factory.get_name()
250        if factory_name in self.factory:
251            raise KeyError('Factory ' + self.factory_name,
252                           ': factory already exists: ' + factory_name)
253
254        self.factory[factory_name] = factory
255
256    def get_available(self) -> Dict[str, Any]:
257        """Get the availability of all factories in the group.
258
259        Each factory has a name and availability that depends on the
260        type of the factory. Effectively this will generate a tree-like
261        structure of the factory's availability.
262
263        Returns:
264            a dictionary with factory name and availability pairs.
265        """
266        factory_list = {}
267
268        for factory_name, factory in self.factory.items():
269            factory_list[factory_name] = factory.get_available()
270
271        return factory_list
272
273    def get_factory(self, factory_name: str) -> BaseFactory:
274        """Get the factory with the specified name.
275
276        Args:
277            factory_name: the name of the factory to retrieve
278
279        Returns:
280            the requested factory or None when not available.
281        """
282        return self.factory.get(factory_name)
283
284    def get_sub_availability(
285            self,
286            sub_factory_name: str,
287            sub_type: str = None) -> Dict[str, Any]:
288        """Get the sub availability from the factory with the specified name (and type).
289
290        Args:
291            sub_factory_name: the name of the sub-factory to query for availability.
292            sub_type: the subtype of the sub-factory to query for availability or None
293                for the complete availability.
294
295        Returns:
296            a dictionary containing the availability of the sub-factory (type).
297        """
298        sub_factory = self.get_factory(sub_factory_name)
299        if sub_type is None:
300            return sub_factory.get_available()
301
302        type_factory = sub_factory.get_factory(sub_type)
303        if type_factory is None:
304            return {}
305
306        return type_factory.get_available()
307
308    def is_obj_available(self, obj_name: str) -> bool:
309        """Is the object with the specified name available.
310
311        Checks the object for existing in any of the child factories.
312
313        Args:
314            obj_name: the name of the object to query for availability.
315
316        Returns:
317            whether the object is available.
318        """
319        for _, factory in self.factory.items():
320            if factory.is_obj_available(obj_name):
321                return True
322
323        return False

The factory that groups other factories together.

Public methods:

add_factory get_factory get_sub_availability

def add_factory( self, factory: src.fairreckitlib.core.config.config_factories.BaseFactory) -> None:
238    def add_factory(self, factory: BaseFactory) -> None:
239        """Add the specified factory to the group.
240
241        The name of the factory is used as the key.
242
243        Args:
244            factory: to add to the group.
245
246        Raises:
247            KeyError: when the name of the factory already exists in the group.
248        """
249        factory_name = factory.get_name()
250        if factory_name in self.factory:
251            raise KeyError('Factory ' + self.factory_name,
252                           ': factory already exists: ' + factory_name)
253
254        self.factory[factory_name] = factory

Add the specified factory to the group.

The name of the factory is used as the key.

Args: factory: to add to the group.

Raises: KeyError: when the name of the factory already exists in the group.

def get_available(self) -> Dict[str, Any]:
256    def get_available(self) -> Dict[str, Any]:
257        """Get the availability of all factories in the group.
258
259        Each factory has a name and availability that depends on the
260        type of the factory. Effectively this will generate a tree-like
261        structure of the factory's availability.
262
263        Returns:
264            a dictionary with factory name and availability pairs.
265        """
266        factory_list = {}
267
268        for factory_name, factory in self.factory.items():
269            factory_list[factory_name] = factory.get_available()
270
271        return factory_list

Get the availability of all factories in the group.

Each factory has a name and availability that depends on the type of the factory. Effectively this will generate a tree-like structure of the factory's availability.

Returns: a dictionary with factory name and availability pairs.

def get_factory( self, factory_name: str) -> src.fairreckitlib.core.config.config_factories.BaseFactory:
273    def get_factory(self, factory_name: str) -> BaseFactory:
274        """Get the factory with the specified name.
275
276        Args:
277            factory_name: the name of the factory to retrieve
278
279        Returns:
280            the requested factory or None when not available.
281        """
282        return self.factory.get(factory_name)

Get the factory with the specified name.

Args: factory_name: the name of the factory to retrieve

Returns: the requested factory or None when not available.

def get_sub_availability(self, sub_factory_name: str, sub_type: str = None) -> Dict[str, Any]:
284    def get_sub_availability(
285            self,
286            sub_factory_name: str,
287            sub_type: str = None) -> Dict[str, Any]:
288        """Get the sub availability from the factory with the specified name (and type).
289
290        Args:
291            sub_factory_name: the name of the sub-factory to query for availability.
292            sub_type: the subtype of the sub-factory to query for availability or None
293                for the complete availability.
294
295        Returns:
296            a dictionary containing the availability of the sub-factory (type).
297        """
298        sub_factory = self.get_factory(sub_factory_name)
299        if sub_type is None:
300            return sub_factory.get_available()
301
302        type_factory = sub_factory.get_factory(sub_type)
303        if type_factory is None:
304            return {}
305
306        return type_factory.get_available()

Get the sub availability from the factory with the specified name (and type).

Args: sub_factory_name: the name of the sub-factory to query for availability. sub_type: the subtype of the sub-factory to query for availability or None for the complete availability.

Returns: a dictionary containing the availability of the sub-factory (type).

def is_obj_available(self, obj_name: str) -> bool:
308    def is_obj_available(self, obj_name: str) -> bool:
309        """Is the object with the specified name available.
310
311        Checks the object for existing in any of the child factories.
312
313        Args:
314            obj_name: the name of the object to query for availability.
315
316        Returns:
317            whether the object is available.
318        """
319        for _, factory in self.factory.items():
320            if factory.is_obj_available(obj_name):
321                return True
322
323        return False

Is the object with the specified name available.

Checks the object for existing in any of the child factories.

Args: obj_name: the name of the object to query for availability.

Returns: whether the object is available.

def create_factory_from_list( factory_name: str, obj_tuple_list: List[Tuple[str, Callable[[str, Dict[str, Any]], Any], Optional[Callable[[], src.fairreckitlib.core.config.config_parameters.ConfigParameters]]]]) -> src.fairreckitlib.core.config.config_factories.Factory:
326def create_factory_from_list(
327        factory_name: str,
328        obj_tuple_list: List[Tuple[
329            str,
330            Callable[[str, Dict[str, Any]], Any],
331            Optional[Callable[[], ConfigParameters]]
332        ]]) -> Factory:
333    """Create and return the factory with the specified tuple entries.
334
335    Each tuple in the list consists of three things; the name of the object,
336    the object creation function and the parameter creation function.
337
338    Args:
339        factory_name: the name of the factory to create.
340        obj_tuple_list: a list of object tuples to add after factory creation.
341
342    Returns:
343        the factory with the added objects.
344    """
345    factory = Factory(factory_name)
346
347    for (obj_name, func_create_obj, func_create_obj_params) in obj_tuple_list:
348        factory.add_obj(
349            obj_name,
350            func_create_obj,
351            func_create_obj_params
352        )
353
354    return factory

Create and return the factory with the specified tuple entries.

Each tuple in the list consists of three things; the name of the object, the object creation function and the parameter creation function.

Args: factory_name: the name of the factory to create. obj_tuple_list: a list of object tuples to add after factory creation.

Returns: the factory with the added objects.

def resolve_factory( obj_name: str, obj_factory: Union[src.fairreckitlib.core.config.config_factories.Factory, src.fairreckitlib.core.config.config_factories.GroupFactory]) -> Optional[src.fairreckitlib.core.config.config_factories.Factory]:
357def resolve_factory(
358        obj_name: str,
359        obj_factory: Union[Factory, GroupFactory]) -> Optional[Factory]:
360    """Resolve the object factory from the name of the object.
361
362    Args:
363        obj_name: the name of the object.
364        obj_factory: the (group) factory to query for the object.
365
366    Returns:
367        the resolved factory or None when not found.
368    """
369    if isinstance(obj_factory, Factory):
370        return obj_factory if obj_factory.is_obj_available(obj_name) else None
371
372    for factory_name in obj_factory.get_available_names():
373        obj_sub_factory = obj_factory.get_factory(factory_name)
374        if obj_sub_factory.is_obj_available(obj_name):
375            if isinstance(obj_sub_factory, GroupFactory):
376                return resolve_factory(obj_name, obj_sub_factory)
377
378            return obj_sub_factory
379
380    return None

Resolve the object factory from the name of the object.

Args: obj_name: the name of the object. obj_factory: the (group) factory to query for the object.

Returns: the resolved factory or None when not found.