Skip to content

Commit

Permalink
(previous was an incomplete commit)
Browse files Browse the repository at this point in the history
  • Loading branch information
pchtsp committed Jul 24, 2024
1 parent b9a97c5 commit 8236957
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 94 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/test_cornflow_server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Set up Quarto
uses: quarto-dev/quarto-actions/setup@v2
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# To install LaTeX to build PDF book
tinytex: true
- name: Copy DAG files
run: |
cd ..
Expand Down
10 changes: 6 additions & 4 deletions cornflow-dags/DAG/tsp/core/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .solution import Solution

import json, tempfile
from quarto import render
import quarto


class Experiment(ExperimentCore):
Expand Down Expand Up @@ -51,8 +51,6 @@ def get_objective(self) -> float:
# if solution is empty, we return 0
if len(self.solution.data["route"]) == 0:
return 0
# we get a sorted list of nodes by position
arcs = self.solution.get_used_arcs()

# we sum all arc weights in the solution
return sum(self.get_used_arc_weights().values())
Expand Down Expand Up @@ -93,13 +91,17 @@ def generate_report(self, report_path: str, report_name="report") -> None:
if not os.path.exists(path_to_qmd):
raise FileNotFoundError(f"Report with path {path_to_qmd} does not exist.")
path_to_output = path_without_ext + ".html"
try:
quarto.quarto.find_quarto()
except FileNotFoundError:
raise ModuleNotFoundError("Quarto is not installed.")
with tempfile.TemporaryDirectory() as tmp:
path = os.path.join(tmp, "experiment.json")
# write a json with instance and solution to temp file
self.to_json(path)
# pass the path to the report to render
# it generates a report with path = path_to_output
render(input=path_to_qmd, execute_params=dict(file_name=path))
quarto.render(input=path_to_qmd, execute_params=dict(file_name=path))
# quarto always writes the report in the .qmd directory.
# thus, we need to move it where we want to:
os.replace(path_to_output, report_path)
2 changes: 1 addition & 1 deletion cornflow-dags/DAG/tsp/core/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def to_tsplib95(self):
def get_arcs(self) -> TupList:
return self.data["arcs"]

def get_indexed_arcs(self) -> TupList:
def get_indexed_arcs(self) -> SuperDict:
return self.data["arcs"].to_dict(
result_col=None, indices=["n1", "n2"], is_list=False
)
Expand Down
96 changes: 95 additions & 1 deletion cornflow-dags/tests/test_dags.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
sys.modules["airflow.secrets.environment_variables"] = mymodule

from cornflow_client import SchemaManager, ApplicationCore
from cornflow_client.airflow.dag_utilities import cf_solve
from cornflow_client.airflow.dag_utilities import (
cf_solve,
cf_report,
AirflowDagException,
)
from jsonschema import Draft7Validator
from pytups import SuperDict

Expand Down Expand Up @@ -193,6 +197,16 @@ def test_report(self):
pass
self.assertRaises(StopIteration, parser.feed, content)

def test_report_error(self):
tests = self.app.test_cases
my_experim = self.app.solvers["cpsat"](self.app.instance(tests[0]["instance"]))
my_experim.solve(dict())
report_path = "./my_report.html"
my_fun = my_experim.generate_report(
report_path=report_path, report_name="wrong_name"
)
self.assertRaises(FileNotFoundError, my_fun)

def test_export(self):
tests = self.app.test_cases
my_file_path = "export.json"
Expand All @@ -203,6 +217,86 @@ def test_export(self):
except FileNotFoundError:
pass

@patch("cornflow_client.airflow.dag_utilities.connect_to_cornflow")
def test_complete_report(self, connectCornflow, config=None):
config = config or self.config
config = dict(**config, report=dict(name="report"))
tests = self.app.test_cases
for test_case in tests:
instance_data = test_case.get("instance")
solution_data = test_case.get("solution", None)
if solution_data is None:
solution_data = dict(route=[])

mock = Mock()
mock.get_data.return_value = dict(
data=instance_data, solution_data=solution_data
)
mock.get_results.return_value = dict(config=config, state=1)
mock.create_report.return_value = dict(id=1)
connectCornflow.return_value = mock
dag_run = Mock()
dag_run.conf = dict(exec_id="exec_id")
cf_report(app=self.app, secrets="", dag_run=dag_run)
mock.create_report.assert_called_once()
mock.put_one_report.assert_called_once()

@patch("cornflow_client.airflow.dag_utilities.connect_to_cornflow")
def test_complete_report_wrong_data(self, connectCornflow, config=None):
config = config or self.config
config = dict(**config, report=dict(name="report"))
tests = self.app.test_cases
for test_case in tests:
instance_data = test_case.get("instance")
solution_data = None

mock = Mock()
mock.get_data.return_value = dict(
data=instance_data, solution_data=solution_data
)
mock.get_results.return_value = dict(config=config, state=1)
mock.create_report.return_value = dict(id=1)
connectCornflow.return_value = mock
dag_run = Mock()
dag_run.conf = dict(exec_id="exec_id")
my_report = lambda: cf_report(app=self.app, secrets="", dag_run=dag_run)
self.assertRaises(AirflowDagException, my_report)
mock.create_report.assert_called_once()
mock.raw.put_api_for_id.assert_called_once()
args, kwargs = mock.raw.put_api_for_id.call_args
self.assertEqual(kwargs["data"], {"state": -1})

@patch("quarto.render")
@patch("cornflow_client.airflow.dag_utilities.connect_to_cornflow")
def test_complete_report_no_quarto(self, connectCornflow, render, config=None):
config = config or self.config
config = dict(**config, report=dict(name="report"))
tests = self.app.test_cases
render.side_effect = ModuleNotFoundError()
render.return_value = dict(a=1)
for test_case in tests:
instance_data = test_case.get("instance")
solution_data = test_case.get("solution", None)
if solution_data is None:
solution_data = dict(route=[])

mock = Mock()
mock.get_data.return_value = dict(
data=instance_data,
solution_data=solution_data,
)
mock.get_results.return_value = dict(config=config, state=1)
mock.create_report.return_value = dict(id=1)
connectCornflow.return_value = mock
dag_run = Mock()
dag_run.conf = dict(exec_id="exec_id")
my_report = lambda: cf_report(app=self.app, secrets="", dag_run=dag_run)
self.assertRaises(AirflowDagException, my_report)
mock.create_report.assert_called_once()
mock.raw.put_api_for_id.assert_called_once()
args, kwargs = mock.raw.put_api_for_id.call_args
self.assertEqual(kwargs["data"], {"state": -10})


class Vrp(BaseDAGTests.SolvingTests):
def setUp(self):
Expand Down
5 changes: 0 additions & 5 deletions cornflow-server/cornflow/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ class Development(DefaultConfig):
""" """

ENV = "development"
UPLOAD_FOLDER = os.getenv("UPLOAD_FOLDER", "/usr/src/app/static")


class Testing(DefaultConfig):
Expand All @@ -115,10 +114,6 @@ class Testing(DefaultConfig):
AIRFLOW_PWD = os.getenv("AIRFLOW_PWD", "admin")
OPEN_DEPLOYMENT = 1
LOG_LEVEL = int(os.getenv("LOG_LEVEL", 10))
UPLOAD_FOLDER = os.getenv(
"UPLOAD_FOLDER",
os.path.abspath(os.path.join(os.path.dirname(__file__), "./static")),
)


class Production(DefaultConfig):
Expand Down
7 changes: 6 additions & 1 deletion cornflow-server/cornflow/endpoints/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
ExecutionRelaunchEndpoint,
)

from .reports import ReportEndpoint, ReportDetailsEndpoint
from .reports import ReportEndpoint, ReportDetailsEndpoint, ReportDetailsEditEndpoint
from .health import HealthEndpoint
from .instance import (
InstanceEndpoint,
Expand Down Expand Up @@ -224,6 +224,11 @@
urls="/report/<int:idx>/",
endpoint="report-detail",
),
dict(
resource=ReportDetailsEditEndpoint,
urls="/report/<int:idx>/edit/",
endpoint="report-detail-edit",
),
dict(resource=ReportEndpoint, urls="/report/", endpoint="report"),
]

Expand Down
Loading

0 comments on commit 8236957

Please sign in to comment.