From 82354b1a2dfd5031dcf48a8a4c1d993b1350c088 Mon Sep 17 00:00:00 2001 From: Stefano Borini <sborini@enthought.com> Date: Wed, 19 Jul 2017 17:02:25 +0100 Subject: [PATCH] Restructuring of the fundamental layout for the model objects --- force_bdss/base_core_driver.py | 10 ++++ force_bdss/bdss_application.py | 9 --- force_bdss/core_evaluation_driver.py | 39 ++++++------ force_bdss/core_mco_driver.py | 10 ++-- .../data_sources/base_data_source_model.py | 14 +++-- force_bdss/io/workflow_reader.py | 60 +++++++++++++++++++ force_bdss/kpi/base_kpi_calculator_model.py | 14 +++-- force_bdss/mco/base_mco_model.py | 14 +++-- force_bdss/workspecs/data_source.py | 15 ----- force_bdss/workspecs/kpi_calculator.py | 15 ----- .../workspecs/multi_criteria_optimizer.py | 15 ----- force_bdss/workspecs/workflow.py | 48 ++------------- 12 files changed, 124 insertions(+), 139 deletions(-) create mode 100644 force_bdss/io/workflow_reader.py delete mode 100644 force_bdss/workspecs/data_source.py delete mode 100644 force_bdss/workspecs/kpi_calculator.py delete mode 100644 force_bdss/workspecs/multi_criteria_optimizer.py diff --git a/force_bdss/base_core_driver.py b/force_bdss/base_core_driver.py index 5875f17..4d7a942 100644 --- a/force_bdss/base_core_driver.py +++ b/force_bdss/base_core_driver.py @@ -5,6 +5,8 @@ from force_bdss.bundle_registry_plugin import ( BundleRegistryPlugin, BUNDLE_REGISTRY_PLUGIN_ID ) +from force_bdss.io.workflow_reader import WorkflowReader +from force_bdss.workspecs.workflow import Workflow class BaseCoreDriver(Plugin): @@ -14,5 +16,13 @@ class BaseCoreDriver(Plugin): bundle_registry = Instance(BundleRegistryPlugin) + #: Deserialized content of the workflow file. + workflow = Instance(Workflow) + def _bundle_registry_default(self): return self.application.get_plugin(BUNDLE_REGISTRY_PLUGIN_ID) + + def _workflow_default(self): + reader = WorkflowReader(self.bundle_registry) + with open(self.application.workflow_filepath) as f: + return reader.read(f) diff --git a/force_bdss/bdss_application.py b/force_bdss/bdss_application.py index c813e4d..dd26fa6 100644 --- a/force_bdss/bdss_application.py +++ b/force_bdss/bdss_application.py @@ -11,8 +11,6 @@ from force_bdss.core_mco_driver import CoreMCODriver from traits.api import Unicode, Bool, Instance -from force_bdss.workspecs.workflow import Workflow - class BDSSApplication(Application): """Main application for the BDSS. @@ -22,9 +20,6 @@ class BDSSApplication(Application): #: The path of the workflow file to open workflow_filepath = Unicode() - #: Deserialized content of the workflow file. - workflow = Instance(Workflow) - #: This flags signals to the application not to execute and orchestrate #: the MCO, but instead to perform a single evaluation under the #: coordination of the MCO itself. See design notes for more details. @@ -56,7 +51,3 @@ class BDSSApplication(Application): print("No extensions found") super(BDSSApplication, self).__init__(plugins=plugins) - - def _workflow_default(self): - with open(self.workflow_filepath) as f: - return Workflow.from_json(json.load(f)) diff --git a/force_bdss/core_evaluation_driver.py b/force_bdss/core_evaluation_driver.py index 19e5666..d7cc54c 100644 --- a/force_bdss/core_evaluation_driver.py +++ b/force_bdss/core_evaluation_driver.py @@ -1,6 +1,9 @@ -from traits.has_traits import on_trait_change +import sys +from traits.api import on_trait_change from force_bdss.base_core_driver import BaseCoreDriver +from force_bdss.io.workflow_reader import InvalidVersionException, \ + InvalidFileException class CoreEvaluationDriver(BaseCoreDriver): @@ -10,11 +13,14 @@ class CoreEvaluationDriver(BaseCoreDriver): @on_trait_change("application:started") def application_started(self): - workflow = self.application.workflow - - mco_data = workflow.multi_criteria_optimizer - mco_bundle = self.bundle_registry.mco_bundle_by_id(mco_data.id) - mco_model = mco_bundle.create_model(mco_data.model_data) + try: + workflow = self.workflow + except (InvalidVersionException, InvalidFileException) as e: + print(str(e), file=sys.stderr) + sys.exit(1) + + mco_model = workflow.multi_criteria_optimizer + mco_bundle = mco_model.bundle mco_communicator = mco_bundle.create_communicator( self.application, mco_model) @@ -22,22 +28,17 @@ class CoreEvaluationDriver(BaseCoreDriver): parameters = mco_communicator.receive_from_mco() ds_results = [] - for requested_ds in workflow.data_sources: - ds_bundle = self.bundle_registry.data_source_bundle_by_id( - requested_ds.id) - ds_model = ds_bundle.create_model(requested_ds.model_data) - data_source = ds_bundle.create_data_source( - self.application, ds_model) + for ds_model in workflow.data_sources: + ds_bundle = ds_model.bundle + data_source = ds_bundle.create_data_source(self.application, + ds_model) ds_results.append(data_source.run(parameters)) kpi_results = [] - for requested_kpic in workflow.kpi_calculators: - kpic_bundle = self.bundle_registry.kpi_calculator_bundle_by_id( - requested_kpic.id) - ds_model = kpic_bundle.create_model( - requested_kpic.model_data) - kpi_calculator = kpic_bundle.create_data_source( - self.application, ds_model) + for kpic_model in workflow.kpi_calculators: + kpic_bundle = kpic_model.bundle + kpi_calculator = kpic_bundle.create_kpi_calculator( + self.application, kpic_model) kpi_results.append(kpi_calculator.run(ds_results)) mco_communicator.send_to_mco(kpi_results) diff --git a/force_bdss/core_mco_driver.py b/force_bdss/core_mco_driver.py index f84c83d..b4e6135 100644 --- a/force_bdss/core_mco_driver.py +++ b/force_bdss/core_mco_driver.py @@ -5,7 +5,7 @@ import sys from traits.api import on_trait_change from force_bdss.base_core_driver import BaseCoreDriver -from force_bdss.workspecs.workflow import (InvalidVersionException, +from force_bdss.io.workflow_reader import (InvalidVersionException, InvalidFileException) @@ -17,14 +17,12 @@ class CoreMCODriver(BaseCoreDriver): @on_trait_change("application:started") def application_started(self): try: - workflow = self.application.workflow + workflow = self.workflow except (InvalidVersionException, InvalidFileException) as e: print(str(e), file=sys.stderr) sys.exit(1) - mco_data = workflow.multi_criteria_optimizer - mco_bundle = self.bundle_registry.mco_bundle_by_id(mco_data.id) - mco_model = mco_bundle.create_model(mco_data.model_data) + mco_model = workflow.multi_criteria_optimizer + mco_bundle = mco_model.bundle mco = mco_bundle.create_optimizer(self.application, mco_model) - mco.run() diff --git a/force_bdss/data_sources/base_data_source_model.py b/force_bdss/data_sources/base_data_source_model.py index d88d3ad..f3ebea6 100644 --- a/force_bdss/data_sources/base_data_source_model.py +++ b/force_bdss/data_sources/base_data_source_model.py @@ -1,9 +1,11 @@ -import abc -from traits.api import ABCHasStrictTraits +from traits.api import ABCHasStrictTraits, Instance + +from .i_data_source_bundle import IDataSourceBundle class BaseDataSourceModel(ABCHasStrictTraits): - @classmethod - @abc.abstractmethod - def from_json(self, model_data): - pass + bundle = Instance(IDataSourceBundle) + + def __init__(self, bundle, *args, **kwargs): + self.bundle = bundle + super(BaseDataSourceModel, self).__init__(self, *args, **kwargs) diff --git a/force_bdss/io/workflow_reader.py b/force_bdss/io/workflow_reader.py new file mode 100644 index 0000000..eaad270 --- /dev/null +++ b/force_bdss/io/workflow_reader.py @@ -0,0 +1,60 @@ +import json + +from traits.api import HasStrictTraits, Instance + +from ..workspecs.workflow import Workflow +from ..bundle_registry_plugin import BundleRegistryPlugin + +SUPPORTED_FILE_VERSIONS = ["1"] + + +class InvalidFileException(Exception): + pass + + +class InvalidVersionException(InvalidFileException): + pass + + +class WorkflowReader(HasStrictTraits): + bundle_registry = Instance(BundleRegistryPlugin) + + def __init__(self, bundle_registry, *args, **kwargs): + self.bundle_registry = bundle_registry + + super(WorkflowReader, self).__init__(*args, **kwargs) + + def read(self, file): + json_data = json.load(file) + registry = self.bundle_registry + + try: + version = json_data["version"] + except KeyError: + raise InvalidFileException("Corrupted input file, no version" + " specified") + + if version not in SUPPORTED_FILE_VERSIONS: + raise InvalidVersionException( + "File version {} not supported".format(json_data["version"])) + + wf = Workflow() + + mco_id = json_data["multi_criteria_optimizer"]["id"] + mco_bundle = registry.mco_bundle_by_id(mco_id) + wf.multi_criteria_optimizer = mco_bundle.create_model( + json_data["multi_criteria_optimizer"]["model_data"]) + + for ds_entry in json_data["data_sources"]: + ds_id = ds_entry["id"] + ds_bundle = registry.data_source_bundle_by_id(ds_id) + wf.data_sources.append(ds_bundle.create_model( + ds_entry["model_data"])) + + for kpic_entry in json_data["kpi_calculators"]: + kpic_id = kpic_entry["id"] + kpic_bundle = registry.kpi_calculator_bundle_by_id(kpic_id) + wf.kpi_calculators.append(kpic_bundle.create_model( + kpic_entry["model_data"])) + + return wf diff --git a/force_bdss/kpi/base_kpi_calculator_model.py b/force_bdss/kpi/base_kpi_calculator_model.py index 9489b9b..512be3e 100644 --- a/force_bdss/kpi/base_kpi_calculator_model.py +++ b/force_bdss/kpi/base_kpi_calculator_model.py @@ -1,9 +1,11 @@ -import abc -from traits.has_traits import ABCHasStrictTraits +from traits.api import ABCHasStrictTraits, Instance + +from .i_kpi_calculator_bundle import IKPICalculatorBundle class BaseKPICalculatorModel(ABCHasStrictTraits): - @classmethod - @abc.abstractmethod - def from_json(self, model_data): - pass + bundle = Instance(IKPICalculatorBundle) + + def __init__(self, bundle, *args, **kwargs): + self.bundle = bundle + super(BaseKPICalculatorModel, self).__init__(self, *args, **kwargs) diff --git a/force_bdss/mco/base_mco_model.py b/force_bdss/mco/base_mco_model.py index 3bf128c..b263045 100644 --- a/force_bdss/mco/base_mco_model.py +++ b/force_bdss/mco/base_mco_model.py @@ -1,9 +1,11 @@ -import abc -from traits.api import ABCHasStrictTraits +from traits.api import ABCHasStrictTraits, Instance + +from .i_multi_criteria_optimizer_bundle import IMultiCriteriaOptimizerBundle class BaseMCOModel(ABCHasStrictTraits): - @classmethod - @abc.abstractmethod - def from_json(self, model_data): - pass + bundle = Instance(IMultiCriteriaOptimizerBundle) + + def __init__(self, bundle, *args, **kwargs): + self.bundle = bundle + super(BaseMCOModel, self).__init__(self, *args, **kwargs) diff --git a/force_bdss/workspecs/data_source.py b/force_bdss/workspecs/data_source.py deleted file mode 100644 index bad5752..0000000 --- a/force_bdss/workspecs/data_source.py +++ /dev/null @@ -1,15 +0,0 @@ -from traits.api import HasStrictTraits, String, Dict - - -class DataSource(HasStrictTraits): - id = String() - model_data = Dict() - - @classmethod - def from_json(cls, json_data): - self = cls( - id=json_data["id"], - model_data=json_data["model_data"] - ) - - return self diff --git a/force_bdss/workspecs/kpi_calculator.py b/force_bdss/workspecs/kpi_calculator.py deleted file mode 100644 index b806625..0000000 --- a/force_bdss/workspecs/kpi_calculator.py +++ /dev/null @@ -1,15 +0,0 @@ -from traits.api import HasStrictTraits, String, Dict - - -class KPICalculator(HasStrictTraits): - id = String() - model_data = Dict() - - @classmethod - def from_json(cls, json_data): - self = cls( - id=json_data["id"], - model_data=json_data["model_data"] - ) - - return self diff --git a/force_bdss/workspecs/multi_criteria_optimizer.py b/force_bdss/workspecs/multi_criteria_optimizer.py deleted file mode 100644 index efa4bfd..0000000 --- a/force_bdss/workspecs/multi_criteria_optimizer.py +++ /dev/null @@ -1,15 +0,0 @@ -from traits.api import HasStrictTraits, String, Dict - - -class MultiCriteriaOptimizer(HasStrictTraits): - id = String() - model_data = Dict() - - @classmethod - def from_json(cls, json_data): - self = cls( - id=json_data["id"], - model_data=json_data["model_data"] - ) - - return self diff --git a/force_bdss/workspecs/workflow.py b/force_bdss/workspecs/workflow.py index edc85c8..6ece6c7 100644 --- a/force_bdss/workspecs/workflow.py +++ b/force_bdss/workspecs/workflow.py @@ -1,48 +1,12 @@ from traits.api import HasStrictTraits, Instance, String, List -from force_bdss.workspecs.data_source import DataSource -from force_bdss.workspecs.kpi_calculator import KPICalculator -from .multi_criteria_optimizer import MultiCriteriaOptimizer - -SUPPORTED_FILE_VERSIONS = ["1"] - - -class InvalidFileException(Exception): - pass - - -class InvalidVersionException(InvalidFileException): - pass +from ..data_sources.base_data_source_model import BaseDataSourceModel +from ..kpi.base_kpi_calculator_model import BaseKPICalculatorModel +from ..mco.base_mco_model import BaseMCOModel class Workflow(HasStrictTraits): name = String() - multi_criteria_optimizer = Instance(MultiCriteriaOptimizer) - data_sources = List(DataSource) - kpi_calculators = List(KPICalculator) - - @classmethod - def from_json(cls, json_data): - try: - version = json_data["version"] - except KeyError: - raise InvalidFileException("Corrupted input file, no version" - " specified") - - if version not in SUPPORTED_FILE_VERSIONS: - raise InvalidVersionException( - "File version {} not supported".format(json_data["version"])) - - self = cls( - multi_criteria_optimizer=MultiCriteriaOptimizer.from_json( - json_data["multi_criteria_optimizer"] - ), - data_sources=[ - DataSource.from_json(data_source_data) - for data_source_data in json_data["data_sources"]], - kpi_calculators=[ - KPICalculator.from_json(kpi_calculator_data) - for kpi_calculator_data in json_data["kpi_calculators"]] - ) - - return self + multi_criteria_optimizer = Instance(BaseMCOModel) + data_sources = List(BaseDataSourceModel) + kpi_calculators = List(BaseKPICalculatorModel) -- GitLab