diff --git a/force_bdss/api.py b/force_bdss/api.py index 1a5aeedfb60db42e6d1e728a3d5a15d64350fe00..c1022dc0c9b910d9ccf1d9538134834cc3f669fe 100644 --- a/force_bdss/api.py +++ b/force_bdss/api.py @@ -1,15 +1,21 @@ from .base_extension_plugin import BaseExtensionPlugin # noqa from .id_generators import bundle_id # noqa -from .data_sources.i_data_source_bundle import IDataSourceBundle # noqa -from .mco.i_multi_criteria_optimizer_bundle import IMultiCriteriaOptimizerBundle # noqa -from .kpi.i_kpi_calculator_bundle import IKPICalculatorBundle # noqa + from .data_sources.base_data_source_model import BaseDataSourceModel # noqa from .data_sources.data_source_result import DataSourceResult # noqa from .data_sources.data_source_parameters import DataSourceParameters # noqa from .data_sources.base_data_source import BaseDataSource # noqa +from .data_sources.base_data_source_bundle import BaseDataSourceBundle # noqa +from .data_sources.i_data_source_bundle import IDataSourceBundle # noqa + from .kpi.base_kpi_calculator import BaseKPICalculator # noqa from .kpi.kpi_calculator_result import KPICalculatorResult # noqa from .kpi.base_kpi_calculator_model import BaseKPICalculatorModel # noqa +from .kpi.base_kpi_calculator_bundle import BaseKPICalculatorBundle # noqa +from .kpi.i_kpi_calculator_bundle import IKPICalculatorBundle # noqa + from .mco.base_mco_model import BaseMCOModel # noqa from .mco.base_mco_communicator import BaseMCOCommunicator # noqa from .mco.base_multi_criteria_optimizer import BaseMultiCriteriaOptimizer # noqa +from .mco.base_multi_criteria_optimizer_bundle import BaseMultiCriteriaOptimizerBundle # noqa +from .mco.i_multi_criteria_optimizer_bundle import IMultiCriteriaOptimizerBundle # noqa diff --git a/force_bdss/core_plugins/csv_extractor/csv_extractor/csv_extractor_bundle.py b/force_bdss/core_plugins/csv_extractor/csv_extractor/csv_extractor_bundle.py index a44b5e14b65970a1a62d26a7706469a60d13a679..55f998c49c4bfef7dfb37f93f61f3c435f00f518 100644 --- a/force_bdss/core_plugins/csv_extractor/csv_extractor/csv_extractor_bundle.py +++ b/force_bdss/core_plugins/csv_extractor/csv_extractor/csv_extractor_bundle.py @@ -1,15 +1,16 @@ -from traits.api import provides, HasStrictTraits, String +from traits.api import String -from force_bdss.api import bundle_id, IDataSourceBundle +from force_bdss.api import bundle_id, BaseDataSourceBundle from .csv_extractor_model import CSVExtractorModel from .csv_extractor_data_source import CSVExtractorDataSource -@provides(IDataSourceBundle) -class CSVExtractorBundle(HasStrictTraits): +class CSVExtractorBundle(BaseDataSourceBundle): id = String(bundle_id("enthought", "csv_extractor")) + name = String("CSV Extractor") + def create_model(self, model_data=None): if model_data is None: model_data = {} diff --git a/force_bdss/core_plugins/dummy_kpi/kpi_adder/kpi_adder_bundle.py b/force_bdss/core_plugins/dummy_kpi/kpi_adder/kpi_adder_bundle.py index a06cf885d4a2d581768da6c6b71a21e7208763c9..ab40c710bbbff3bbdd5c5a39d62b95414198fbc4 100644 --- a/force_bdss/core_plugins/dummy_kpi/kpi_adder/kpi_adder_bundle.py +++ b/force_bdss/core_plugins/dummy_kpi/kpi_adder/kpi_adder_bundle.py @@ -1,16 +1,16 @@ -from traits.api import provides, HasStrictTraits, String +from traits.api import String -from force_bdss.api import bundle_id -from force_bdss.api import IKPICalculatorBundle +from force_bdss.api import bundle_id, BaseKPICalculatorBundle from .kpi_adder_model import KPIAdderModel from .kpi_adder_calculator import KPIAdderCalculator -@provides(IKPICalculatorBundle) -class KPIAdderBundle(HasStrictTraits): +class KPIAdderBundle(BaseKPICalculatorBundle): id = String(bundle_id("enthought", "kpi_adder")) + name = String("KPI Adder") + def create_model(self, model_data=None): if model_data is None: model_data = {} diff --git a/force_bdss/core_plugins/dummy_mco/dakota/dakota_bundle.py b/force_bdss/core_plugins/dummy_mco/dakota/dakota_bundle.py index 07e4dd366a2c964cbf9de4dcace24170feb3bc6c..e4d9f441bf4dbcce63ac1de06a53a56dc35d693b 100644 --- a/force_bdss/core_plugins/dummy_mco/dakota/dakota_bundle.py +++ b/force_bdss/core_plugins/dummy_mco/dakota/dakota_bundle.py @@ -1,15 +1,16 @@ -from traits.api import HasStrictTraits, provides, String -from force_bdss.api import bundle_id, IMultiCriteriaOptimizerBundle +from traits.api import String +from force_bdss.api import bundle_id, BaseMultiCriteriaOptimizerBundle from .dakota_communicator import DakotaCommunicator from .dakota_model import DakotaModel from .dakota_optimizer import DakotaOptimizer -@provides(IMultiCriteriaOptimizerBundle) -class DakotaBundle(HasStrictTraits): +class DakotaBundle(BaseMultiCriteriaOptimizerBundle): id = String(bundle_id("enthought", "dakota")) + name = "Dakota" + def create_model(self, model_data=None): if model_data is None: model_data = {} diff --git a/force_bdss/data_sources/base_data_source_bundle.py b/force_bdss/data_sources/base_data_source_bundle.py new file mode 100644 index 0000000000000000000000000000000000000000..ab53763fd294b025edfefd25b90e8ff200227641 --- /dev/null +++ b/force_bdss/data_sources/base_data_source_bundle.py @@ -0,0 +1,56 @@ +import abc +from traits.api import ABCHasStrictTraits, provides, String + +from .i_data_source_bundle import IDataSourceBundle + + +@provides(IDataSourceBundle) +class BaseDataSourceBundle(ABCHasStrictTraits): + """Base class for DataSource bundles. Reimplement this class to + create your own DataSource. + """ + # NOTE: changes to this class must be ported also to the IDataSourceBundle + + #: Unique identifier that identifies the bundle uniquely in the + #: universe of bundles. Create one with the function bundle_id() + id = String() + + #: A human readable name of the bundle. Spaces allowed + name = String() + + @abc.abstractmethod + def create_data_source(self, application, model): + """Factory method. + Must return the bundle-specific BaseDataSource instance. + + Parameters + ---------- + application: Application + The envisage application. + model: BaseDataSourceModel + The model of the data source, instantiated with create_model() + + Returns + ------- + BaseDataSource + The specific instance of the generated DataSource + """ + + @abc.abstractmethod + def create_model(self, model_data=None): + """Factory method. + Creates the model object (or network of model objects) of the KPI + calculator. The model can provide a traits UI View according to + traitsui specifications, so that a UI can be provided automatically. + + Parameters + ---------- + model_data: dict or None + A dictionary containing the information to recreate the model. + If None, an empty (with defaults) model will be returned. + + Returns + ------- + BaseDataSourceModel + The model + """ diff --git a/force_bdss/data_sources/i_data_source_bundle.py b/force_bdss/data_sources/i_data_source_bundle.py index 5270245c23d05b36fda603bd723d843a6777ecd7..8ed2556078382854920a999ce5c1bf1a8d6ed19f 100644 --- a/force_bdss/data_sources/i_data_source_bundle.py +++ b/force_bdss/data_sources/i_data_source_bundle.py @@ -13,7 +13,6 @@ class IDataSourceBundle(Interface): """Factory method. Must return the bundle-specific BaseDataSource instance. """ - pass def create_model(self, model_data=None): """Factory method. diff --git a/force_bdss/data_sources/tests/test_base_data_source_bundle.py b/force_bdss/data_sources/tests/test_base_data_source_bundle.py new file mode 100644 index 0000000000000000000000000000000000000000..3564a7eb423a4ea3e265b4996be184744c8b1d6f --- /dev/null +++ b/force_bdss/data_sources/tests/test_base_data_source_bundle.py @@ -0,0 +1,23 @@ +import unittest + +from force_bdss.data_sources.base_data_source_bundle import \ + BaseDataSourceBundle + + +class DummyDataSourceBundle(BaseDataSourceBundle): + id = "foo" + + name = "bar" + + def create_data_source(self, application, model): + pass + + def create_model(self, model_data=None): + pass + + +class TestBaseDataSourceBundle(unittest.TestCase): + def test_initialization(self): + bundle = DummyDataSourceBundle() + self.assertEqual(bundle.id, 'foo') + self.assertEqual(bundle.name, 'bar') diff --git a/force_bdss/kpi/base_kpi_calculator_bundle.py b/force_bdss/kpi/base_kpi_calculator_bundle.py new file mode 100644 index 0000000000000000000000000000000000000000..5ae40637ebae8a75b0fed7089cfa6a629383e11c --- /dev/null +++ b/force_bdss/kpi/base_kpi_calculator_bundle.py @@ -0,0 +1,58 @@ +import abc +from traits.api import ABCHasStrictTraits, provides, String + +from .i_kpi_calculator_bundle import IKPICalculatorBundle + + +@provides(IKPICalculatorBundle) +class BaseKPICalculatorBundle(ABCHasStrictTraits): + """Base class for the Key Performance Indicator calculator bundles. + Inherit from this class to create a bundle, and reimplement the abstract + methods. + """ + # NOTE: any changes in this interface must be ported to + # IKPICalculatorBundle + + #: A unique ID generated with bundle_id() routine + id = String() + + #: A UI friendly name for the bundle. Can contain spaces. + name = String() + + @abc.abstractmethod + def create_kpi_calculator(self, application, model): + """Factory method. + Creates and returns an instance of a KPI Calculator, associated + to the given application and model. + + Parameters + ---------- + application: Application + The envisage application. + model: BaseKPICalculatorModel + The model of the calculator, instantiated with create_model() + + Returns + ------- + BaseKPICalculator + The specific instance of the generated KPICalculator + """ + + @abc.abstractmethod + def create_model(self, model_data=None): + """Factory method. + Creates the model object (or network of model objects) of the KPI + calculator. The model can provide a traits UI View according to + traitsui specifications, so that a UI can be provided automatically. + + Parameters + ---------- + model_data: dict or None + A dictionary containing the information to recreate the model. + If None, an empty (with defaults) model will be returned. + + Returns + ------- + BaseKPICalculatorModel + The model + """ diff --git a/force_bdss/kpi/i_kpi_calculator_bundle.py b/force_bdss/kpi/i_kpi_calculator_bundle.py index d4e8992ba059883f1b8824eb74966f3cdb0222e3..938e7de719990cf5e672c1c350adbf36bfca2a31 100644 --- a/force_bdss/kpi/i_kpi_calculator_bundle.py +++ b/force_bdss/kpi/i_kpi_calculator_bundle.py @@ -2,8 +2,12 @@ from traits.api import Interface, String class IKPICalculatorBundle(Interface): + """Envisage required interface for the BaseKPICalculatorBundle. + You should not need to use this directly.""" id = String() + name = String() + def create_kpi_calculator(self, application, model): pass diff --git a/force_bdss/kpi/tests/test_base_kpi_calculator_bundle.py b/force_bdss/kpi/tests/test_base_kpi_calculator_bundle.py new file mode 100644 index 0000000000000000000000000000000000000000..30dc60e7f8a5d4e6ebbc7598b14a03f247b61f3c --- /dev/null +++ b/force_bdss/kpi/tests/test_base_kpi_calculator_bundle.py @@ -0,0 +1,23 @@ +import unittest + +from force_bdss.kpi.base_kpi_calculator_bundle import \ + BaseKPICalculatorBundle + + +class DummyKPICalculatorBundle(BaseKPICalculatorBundle): + id = "foo" + + name = "bar" + + def create_kpi_calculator(self, application, model): + pass + + def create_model(self, model_data=None): + pass + + +class TestBaseKPICalculatorBundle(unittest.TestCase): + def test_initialization(self): + bundle = DummyKPICalculatorBundle() + self.assertEqual(bundle.id, 'foo') + self.assertEqual(bundle.name, 'bar') diff --git a/force_bdss/mco/base_multi_criteria_optimizer_bundle.py b/force_bdss/mco/base_multi_criteria_optimizer_bundle.py new file mode 100644 index 0000000000000000000000000000000000000000..228ec4c9c3546b6428a1226028af3acabb11c3c8 --- /dev/null +++ b/force_bdss/mco/base_multi_criteria_optimizer_bundle.py @@ -0,0 +1,76 @@ +import abc + +from traits.api import ABCHasStrictTraits, String +from traits.has_traits import provides + +from force_bdss.mco.i_multi_criteria_optimizer_bundle import ( + IMultiCriteriaOptimizerBundle +) + + +@provides(IMultiCriteriaOptimizerBundle) +class BaseMultiCriteriaOptimizerBundle(ABCHasStrictTraits): + """Base class for the MultiCriteria Optimizer bundle. + """ + # NOTE: any changes to the interface of this class must be replicated + # in the IMultiCriteriaOptimizerBundle interface class. + + #: A unique ID produced with the bundle_id() routine. + id = String() + + #: A user friendly name of the bundle. Spaces allowed. + name = String() + + @abc.abstractmethod + def create_optimizer(self, application, model): + """Factory method. + Creates the optimizer with the given application + and model and returns it to the caller. + + Parameters + ---------- + application: Application + The envisage application instance + model: BaseMCOModel + The model to associate to the optimizer, instantiated through + create_model() + + Returns + ------- + BaseMCOOptimizer + The optimizer + """ + + @abc.abstractmethod + def create_model(self, model_data=None): + """Factory method. + Creates the model object (or network of model objects) of the MCO. + The model can provide a traits UI View according to traitsui + specifications, so that a UI can be provided automatically. + + Parameters + ---------- + model_data: dict or None + A dictionary of data that can be interpreted appropriately to + recreate the model. If None, an empty (with defaults) model will + be created and returned. + + Returns + ------- + BaseMCOModel + The MCOModel + """ + + @abc.abstractmethod + def create_communicator(self, application, model): + """Factory method. Returns the communicator class that allows + exchange between the MCO and the evaluator code. + + Parameters + ---------- + application: Application + The envisage application instance + model: BaseMCOModel + The model to associate to the optimizer, instantiated through + create_model() + """ diff --git a/force_bdss/mco/i_multi_criteria_optimizer_bundle.py b/force_bdss/mco/i_multi_criteria_optimizer_bundle.py index cb4222992cf0d7349a798e9747511c7c7e73b4d6..82a857ae03fc9976247770f8aa095ac9528381a6 100644 --- a/force_bdss/mco/i_multi_criteria_optimizer_bundle.py +++ b/force_bdss/mco/i_multi_criteria_optimizer_bundle.py @@ -2,13 +2,18 @@ from traits.api import Interface, String class IMultiCriteriaOptimizerBundle(Interface): + """Interface for the MultiCriteria Optimizer bundle. + You should not need it, as its main use is for envisage support. + """ id = String() + name = String() + def create_optimizer(self, application, model): pass def create_model(self, model_data=None): pass - def create_communicator(self, model_data): + def create_communicator(self, application, model): pass diff --git a/force_bdss/mco/tests/test_base_multi_criteria_optimizer_bundle.py b/force_bdss/mco/tests/test_base_multi_criteria_optimizer_bundle.py new file mode 100644 index 0000000000000000000000000000000000000000..de89488eb3ae413fb83236c2582618e43535a40f --- /dev/null +++ b/force_bdss/mco/tests/test_base_multi_criteria_optimizer_bundle.py @@ -0,0 +1,27 @@ +import unittest + +from force_bdss.mco.base_multi_criteria_optimizer_bundle import ( + BaseMultiCriteriaOptimizerBundle +) + + +class DummyMCOBundle(BaseMultiCriteriaOptimizerBundle): + id = "foo" + + name = "bar" + + def create_optimizer(self, application, model): + pass + + def create_model(self, model_data=None): + pass + + def create_communicator(self, model_data): + pass + + +class TestBaseDataSourceBundle(unittest.TestCase): + def test_initialization(self): + bundle = DummyMCOBundle() + self.assertEqual(bundle.id, 'foo') + self.assertEqual(bundle.name, 'bar')