Abstract classes can be displayed and instanciated by the factories
Summary
The GEMSEO factory mechanism enables to discover automatically all the sub-classes of a given parent abstract class. However, it is possible to have a hierarchy of abstract sub-classes.
The role of the Factory is to only exposes the concrete classes. Yet, no mechanism currently permit to detect and differentiate the concrete and abstract sub-classes
Gemseo version
HEAD of develop (c3892f4e)
Platform info
Not relevant
Environment info
Not relevant
Steps to reproduce
What is the current bug behavior?
Abstract sub-classes are detected and can be instanciated through the factory mechanism.
What is the expected correct behavior?
Only concrete sub-classes shall be exposed and possibly instantiated by the end used through the factory mechanism.
Relevant logs and/or screenshots
An example (among others) can be found in https://gemseo.readthedocs.io/en/stable/examples/mlearning/clustering_model/plot_clustering_api.html#get-available-clustering-models where MLPredictiveClusteringAlgo
is an abstract method and cannot be used on its own.
Possible fixes
Abstract classes can be defined through inheriting from ABC
, and by decorating the abstract methods by the @abstractmethod
decorator. The __abstract_methods__
attribute of a specific class can be then used to determine if the class is concrete or abstract, depending on if it has entries or not. Below a snippet to determine whether a class is abstract.
def is_abstract(cls: Type[Acceleration]) -> bool:
"""Whether the Acceleration sub-class is abstract.
Args:
cls: A reference to an Acceleration sub-class.
Returns:
Whether the class is abstract.
"""
return bool(getattr(cls, "__abstractmethods__", False))
Then, the update
method in the main factory class could use this function to filter the abstract classes:
names_to_classes = self.__get_sub_classes(self.__base_class)
for name, cls in names_to_classes.items():
if self.__is_class_in_modules(module_names, cls) and not is_abstract(cls):
self.__names_to_classes[name] = cls
It has to be noted that ABC
and the abstractmethod
decorator should be used to enable this mechanism.