Skip to content

Commit fc12374

Browse files
authored
Merge pull request #60 from man-group/fix-scheduler-options
Fix hide_code and generate_pdf scheduler options
2 parents 60d664a + 86e64de commit fc12374

File tree

7 files changed

+117
-9
lines changed

7 files changed

+117
-9
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
0.3.1 (2021-10-??)
22
------------------
33

4-
* Bugfix: Large notebooks were causing serialisation errors; now properly stored in gridfs
5-
* Improvement: index page should be a lot quicker due to storage improvements
4+
* Improvement: index page should be a lot quicker due to storage improvements.
5+
* Bugfix: hide_code and generate_pdf options now work as intended with the scheduler.
6+
* Bugfix: Large notebooks were causing serialisation errors; now safely stored in gridfs.
67
* **Incompatibility**: Reports run with this version onwards will not be readable by older versions of Notebooker.
78

89
0.3.0 (2021-10-05)

notebooker/web/routes/run_report.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,21 +232,24 @@ class RunReportParams(NamedTuple):
232232

233233

234234
def validate_run_params(params, issues: List[str]) -> RunReportParams:
235+
logger.info(f"Validating input params: {params}")
235236
# Find and cleanse the title of the report
236237
report_title = validate_title(params.get("report_title"), issues)
237238
# Get mailto email address
238239
mailto = validate_mailto(params.get("mailto"), issues)
239-
# Find whether to generate PDF output
240-
generate_pdf_output = params.get("generate_pdf") == "on"
241-
hide_code = params.get("hide_code") == "on"
240+
# "on" comes from HTML, "True" comes from urlencoded JSON params
241+
generate_pdf_output = params.get("generate_pdf") in ("on", "True")
242+
hide_code = params.get("hide_code") in ("on", "True")
242243

243-
return RunReportParams(
244+
out = RunReportParams(
244245
report_title=report_title,
245246
mailto=mailto,
246247
generate_pdf_output=generate_pdf_output,
247248
hide_code=hide_code,
248249
scheduler_job_id=params.get("scheduler_job_id"),
249250
)
251+
logger.info(f"Validated params: {out}")
252+
return out
250253

251254

252255
def _handle_run_report(
@@ -256,6 +259,13 @@ def _handle_run_report(
256259
if issues:
257260
return jsonify({"status": "Failed", "content": ("\n".join(issues))})
258261
report_name = convert_report_name_url_to_path(report_name)
262+
logger.info(f"Handling run report with parameters report_name={report_name} "
263+
f"report_title={params.report_title}"
264+
f"mailto={params.mailto} "
265+
f"overrides_dict={overrides_dict} "
266+
f"generate_pdf_output={params.generate_pdf_output} "
267+
f"hide_code={params.hide_code} "
268+
f"scheduler_job_id={params.scheduler_job_id}")
259269
try:
260270
job_id = run_report(
261271
report_name,

notebooker/web/routes/scheduling.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
from typing import Optional, List
3-
import uuid
3+
import logging
44

55
from apscheduler.jobstores.base import ConflictingIdError
66
from flask import Blueprint, jsonify, render_template, current_app, request, url_for, abort
@@ -12,6 +12,7 @@
1212
from apscheduler.triggers import cron
1313

1414
scheduling_bp = Blueprint("scheduling_bp", __name__)
15+
logger = logging.getLogger(__name__)
1516

1617

1718
@scheduling_bp.route("/scheduler/health")
@@ -101,6 +102,7 @@ def create_schedule(report_name):
101102
"hide_code": params.hide_code,
102103
"scheduler_job_id": job_id,
103104
}
105+
logger.info(f"Creating job with params: {dict_params}")
104106
try:
105107
job = current_app.apscheduler.add_job(
106108
"notebooker.web.scheduler:run_report", jobstore="mongo", trigger=trigger, kwargs=dict_params, id=job_id

notebooker/web/scheduler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ def run_report(
1818
hide_code: bool,
1919
scheduler_job_id: str,
2020
):
21+
"""
22+
This is the entrypoint of the scheduler; APScheduler has to
23+
run a python function and so we invoke an API call from a thin wrapper.
24+
"""
2125
if GLOBAL_CONFIG is None:
2226
url = f"http://localhost/run_report_json/{report_name}"
2327
else:
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import json
2+
import urllib
3+
4+
import mock
5+
6+
7+
def test_run_report_json_parameters(flask_app, setup_workspace):
8+
with flask_app.test_client() as client:
9+
report_name = "fake/report"
10+
overrides = {"a": 1}
11+
report_title = "title"
12+
mailto = "[email protected]"
13+
generate_pdf = True
14+
hide_code = True
15+
scheduler_job_id = "abc/123"
16+
payload = {
17+
"overrides": json.dumps(overrides),
18+
"report_title": report_title,
19+
"mailto": mailto,
20+
"generate_pdf": generate_pdf,
21+
"hide_code": hide_code,
22+
"scheduler_job_id": scheduler_job_id,
23+
}
24+
with mock.patch("notebooker.web.routes.run_report.run_report") as rr:
25+
rr.return_value = "fake_job_id"
26+
rv = client.post(
27+
f"/run_report_json/{report_name}?{urllib.parse.urlencode(payload)}"
28+
)
29+
assert rv.data == b'{"id":"fake_job_id"}\n'
30+
assert rv.status_code == 202, rv.data
31+
rr.assert_called_with(
32+
report_name,
33+
report_title,
34+
mailto,
35+
overrides,
36+
generate_pdf_output=generate_pdf,
37+
hide_code=hide_code,
38+
scheduler_job_id=scheduler_job_id,
39+
)

tests/integration/web/test_scheduling.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def test_create_schedule(flask_app, setup_workspace):
1212
"report_name": "fake/report",
1313
"overrides": "",
1414
"mailto": "",
15+
"generate_pdf": True,
1516
"cron_schedule": "* * * * *",
1617
},
1718
)
@@ -23,7 +24,7 @@ def test_create_schedule(flask_app, setup_workspace):
2324
"delete_url": "/scheduler/fake/report_test2",
2425
"id": "fake/report_test2",
2526
"params": {
26-
"generate_pdf": False,
27+
"generate_pdf": True,
2728
"hide_code": False,
2829
"mailto": "",
2930
"overrides": "",
@@ -46,6 +47,27 @@ def test_create_schedule(flask_app, setup_workspace):
4647
}
4748

4849

50+
def test_scheduler_handles_booleans_properly(flask_app, setup_workspace):
51+
with flask_app.test_client() as client:
52+
rv = client.post(
53+
"/scheduler/create/fake/report",
54+
data={
55+
"report_title": "test2",
56+
"report_name": "fake/report",
57+
"overrides": "",
58+
"mailto": "",
59+
"generate_pdf": True,
60+
"hide_code": True,
61+
"cron_schedule": "* * * * *",
62+
},
63+
)
64+
assert rv.status_code == 201
65+
data = json.loads(rv.data)
66+
assert data.pop("next_run_time")
67+
assert data["params"]["generate_pdf"] is True
68+
assert data["params"]["hide_code"] is True
69+
70+
4971
def test_create_schedule_bad_report_name(flask_app, setup_workspace):
5072
with flask_app.test_client() as client:
5173
rv = client.post(

tests/unit/test_run_report.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import sys
33

44
import mock
5+
from werkzeug.datastructures import CombinedMultiDict, ImmutableMultiDict
56

67
from notebooker.constants import DEFAULT_SERIALIZER
7-
from notebooker.web.routes.run_report import _monitor_stderr
8+
from notebooker.web.routes.run_report import _monitor_stderr, validate_run_params, RunReportParams
89

910

1011
def test_monitor_stderr():
@@ -31,3 +32,32 @@ def test_monitor_stderr():
3132
mock.call("abc123", new_lines=["This is going to stderr a bit later\n"]),
3233
]
3334
)
35+
36+
37+
def test_validate_run_params():
38+
input_params = CombinedMultiDict(
39+
[
40+
ImmutableMultiDict(
41+
[
42+
("overrides", "{}"),
43+
("report_title", "asdas"),
44+
("mailto", ""),
45+
("generate_pdf", "True"),
46+
("hide_code", "True"),
47+
("scheduler_job_id", "plot_random_asdas"),
48+
]
49+
),
50+
ImmutableMultiDict([]),
51+
]
52+
)
53+
issues = []
54+
expected_output = RunReportParams(
55+
report_title="asdas",
56+
mailto="",
57+
generate_pdf_output=True,
58+
hide_code=True,
59+
scheduler_job_id="plot_random_asdas",
60+
)
61+
actual_output = validate_run_params(input_params, issues)
62+
assert issues == []
63+
assert actual_output == expected_output

0 commit comments

Comments
 (0)