From a9e2eab20edc326c02aff84b4b9b9b59e5a596b8 Mon Sep 17 00:00:00 2001
From: Stefano Borini <sborini@enthought.com>
Date: Tue, 11 Jul 2017 13:05:58 +0100
Subject: [PATCH] More basic implementation, with support for workflow file

---
 examples/test_workflow.json                   |  6 ++++
 force_bdss/application.py                     | 25 ---------------
 .../basic_key_performance_calculator.py       |  4 +--
 force_bdss/basic_multi_criteria_optimizer.py  |  4 +--
 force_bdss/bdss_application.py                | 21 +++++++++++++
 force_bdss/cli/force_bdss.py                  | 31 +++++++++++++++++++
 ...{workflow_plugin.py => core_mco_driver.py} | 25 +++++++--------
 .../multi_criteria_optimizers_plugin.py       |  1 -
 .../workspecs/multi_criteria_optimization.py  | 13 ++++++++
 force_bdss/workspecs/workflow.py              | 18 +++++++++++
 setup.py                                      |  5 +--
 11 files changed, 108 insertions(+), 45 deletions(-)
 create mode 100644 examples/test_workflow.json
 delete mode 100644 force_bdss/application.py
 create mode 100644 force_bdss/bdss_application.py
 create mode 100644 force_bdss/cli/force_bdss.py
 rename force_bdss/{workflow_plugin.py => core_mco_driver.py} (61%)
 create mode 100644 force_bdss/workspecs/multi_criteria_optimization.py
 create mode 100644 force_bdss/workspecs/workflow.py

diff --git a/examples/test_workflow.json b/examples/test_workflow.json
new file mode 100644
index 0000000..49c04bc
--- /dev/null
+++ b/examples/test_workflow.json
@@ -0,0 +1,6 @@
+{
+    "multi_criteria_optimization": {
+        "type": "simple"
+    }
+}
+
diff --git a/force_bdss/application.py b/force_bdss/application.py
deleted file mode 100644
index d0fef51..0000000
--- a/force_bdss/application.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Enthought library imports.
-from envisage.api import Application
-
-
-# Application entry point.
-from force_bdss.multi_criteria_optimizers_plugin import \
-    MultiCriteriaOptimizersPlugin
-from force_bdss.workflow_plugin import WorkflowPlugin
-from force_bdss.key_performance_calculators_plugin import \
-    KeyPerformanceCalculatorsPlugin
-
-
-def run():
-
-    application = Application(
-        id='force',
-        plugins=[
-            WorkflowPlugin(),
-            MultiCriteriaOptimizersPlugin(),
-            KeyPerformanceCalculatorsPlugin(),
-        ]
-    )
-
-    # Run it!
-    application.run()
diff --git a/force_bdss/basic_key_performance_calculator.py b/force_bdss/basic_key_performance_calculator.py
index 30d8a76..63fd2e4 100644
--- a/force_bdss/basic_key_performance_calculator.py
+++ b/force_bdss/basic_key_performance_calculator.py
@@ -5,5 +5,5 @@ from force_bdss.i_key_performance_calculator import IKeyPerformanceCalculator
 
 @provides(IKeyPerformanceCalculator)
 class BasicKeyPerformanceCalculator(HasStrictTraits):
-    def run(self):
-        print("Computing basic key performance indicator")
+    def run(self, workflow):
+        print("Computing basic key performance indicator, {}".format(workflow))
diff --git a/force_bdss/basic_multi_criteria_optimizer.py b/force_bdss/basic_multi_criteria_optimizer.py
index 740c6aa..6cac40d 100644
--- a/force_bdss/basic_multi_criteria_optimizer.py
+++ b/force_bdss/basic_multi_criteria_optimizer.py
@@ -5,5 +5,5 @@ from force_bdss.i_multi_criteria_optimizers import IMultiCriteriaOptimizer
 
 @provides(IMultiCriteriaOptimizer)
 class BasicMultiCriteriaOptimizer(HasStrictTraits):
-    def run(self):
-        print("Basic multicriteria optimizer in action")
+    def run(self, workflow):
+        print("Basic multicriteria optimizer in action, {}".format(workflow))
diff --git a/force_bdss/bdss_application.py b/force_bdss/bdss_application.py
new file mode 100644
index 0000000..62fd89c
--- /dev/null
+++ b/force_bdss/bdss_application.py
@@ -0,0 +1,21 @@
+import json
+
+from envisage.api import Application
+from traits.api import Unicode
+from traits.trait_types import List, Bool, Instance
+
+from force_bdss.workspecs.workflow import Workflow
+
+
+class BDSSApplication(Application):
+    id = "force_bdss.bdss_application"
+
+    workflow_filepath = Unicode()
+
+    workflow = Instance(Workflow)
+
+    evaluate = Bool()
+
+    def _workflow_default(self):
+        with open(self.workflow_filepath) as f:
+            return Workflow.from_json(json.load(f))
diff --git a/force_bdss/cli/force_bdss.py b/force_bdss/cli/force_bdss.py
new file mode 100644
index 0000000..20e1a6e
--- /dev/null
+++ b/force_bdss/cli/force_bdss.py
@@ -0,0 +1,31 @@
+import click
+from envisage.core_plugin import CorePlugin
+import logging
+
+from force_bdss.bdss_application import BDSSApplication
+from force_bdss.core_mco_driver import CoreMCODriver
+from force_bdss.multi_criteria_optimizers_plugin import \
+    MultiCriteriaOptimizersPlugin
+from force_bdss.key_performance_calculators_plugin import \
+    KeyPerformanceCalculatorsPlugin
+
+
+@click.command()
+@click.option("--evaluate", is_flag=True)
+@click.argument('workflow_filepath', type=click.Path(exists=True))
+def run(evaluate, workflow_filepath):
+
+    plugins = [
+        CorePlugin(),
+        CoreMCODriver(),
+        KeyPerformanceCalculatorsPlugin(),
+        MultiCriteriaOptimizersPlugin(),
+    ]
+
+    application = BDSSApplication(
+        plugins=plugins,
+        evaluate=evaluate,
+        workflow_filepath=workflow_filepath
+    )
+
+    application.run()
diff --git a/force_bdss/workflow_plugin.py b/force_bdss/core_mco_driver.py
similarity index 61%
rename from force_bdss/workflow_plugin.py
rename to force_bdss/core_mco_driver.py
index 75e898c..8e82a17 100644
--- a/force_bdss/workflow_plugin.py
+++ b/force_bdss/core_mco_driver.py
@@ -1,27 +1,26 @@
 from envisage.extension_point import ExtensionPoint
-from traits.api import List
 from envisage.plugin import Plugin
-from traits.api import on_trait_change
+from traits.has_traits import on_trait_change
+from traits.trait_types import List
 
 from force_bdss.i_key_performance_calculator import IKeyPerformanceCalculator
 from force_bdss.i_multi_criteria_optimizers import IMultiCriteriaOptimizer
 
 
-class WorkflowPlugin(Plugin):
-
-    id = "force_bdss.workflow_plugin"
+class CoreMCODriver(Plugin):
+    multi_criteria_optimizers = ExtensionPoint(
+        List(IMultiCriteriaOptimizer),
+        id='force_bdss.multi_criteria_optimizers')
 
     key_performance_calculators = ExtensionPoint(
         List(IKeyPerformanceCalculator),
         id='force_bdss.key_performance_calculators')
 
-    multi_criteria_optimizers = ExtensionPoint(
-        List(IMultiCriteriaOptimizer),
-        id='force_bdss.multi_criteria_optimizers')
-
     @on_trait_change("application:started")
     def application_started(self):
-        for mco in self.multi_criteria_optimizers:
-            mco.run()
-        for kpc in self.key_performance_calculators:
-            kpc.run()
+        if self.application.evaluate:
+            for kpi in self.key_performance_calculators:
+                kpi.run(self.application.workflow)
+        else:
+            for mco in self.multi_criteria_optimizers:
+                mco.run(self.application.workflow)
diff --git a/force_bdss/multi_criteria_optimizers_plugin.py b/force_bdss/multi_criteria_optimizers_plugin.py
index a815cd1..07a39a0 100644
--- a/force_bdss/multi_criteria_optimizers_plugin.py
+++ b/force_bdss/multi_criteria_optimizers_plugin.py
@@ -7,7 +7,6 @@ from force_bdss.i_multi_criteria_optimizers import IMultiCriteriaOptimizer
 
 
 class MultiCriteriaOptimizersPlugin(Plugin):
-
     id = "force_bdss.multi_criteria_optimizers_plugin"
 
     multi_criteria_optimizers = List(
diff --git a/force_bdss/workspecs/multi_criteria_optimization.py b/force_bdss/workspecs/multi_criteria_optimization.py
new file mode 100644
index 0000000..6d0a06a
--- /dev/null
+++ b/force_bdss/workspecs/multi_criteria_optimization.py
@@ -0,0 +1,13 @@
+from traits.api import HasStrictTraits, String
+
+
+class MultiCriteriaOptimization(HasStrictTraits):
+    type = String
+
+    @classmethod
+    def from_json(cls, json_data):
+        self = cls(
+            type=json_data["type"]
+        )
+
+        return self
diff --git a/force_bdss/workspecs/workflow.py b/force_bdss/workspecs/workflow.py
new file mode 100644
index 0000000..6ff7cf7
--- /dev/null
+++ b/force_bdss/workspecs/workflow.py
@@ -0,0 +1,18 @@
+from traits.api import HasStrictTraits, Instance, String
+
+from .multi_criteria_optimization import MultiCriteriaOptimization
+
+
+class Workflow(HasStrictTraits):
+    name = String()
+    multi_criteria_optimization = Instance(MultiCriteriaOptimization)
+
+    @classmethod
+    def from_json(cls, json_data):
+        self = cls(
+            multi_criteria_optimization=MultiCriteriaOptimization.from_json(
+                    json_data["multi_criteria_optimization"]
+                )
+            )
+
+        return self
diff --git a/setup.py b/setup.py
index dcce066..49ad67e 100644
--- a/setup.py
+++ b/setup.py
@@ -7,9 +7,10 @@ setup(
     version=VERSION,
     entry_points={
     'console_scripts': [
-        'force_bdss = force_bdss.application:run',
+        'force_bdss = force_bdss.cli.force_bdss:run',
     ]},
     install_requires=[
-        "envisage >= 4.6.0"
+        "envisage >= 4.6.0",
+        "click >= 6.7"
     ]
 )
-- 
GitLab