Skip to content

Commit 0f823cc

Browse files
authored
Merge pull request #85 from man-group/fix-37-master
Fix for py37 build.
2 parents fb33ed9 + d2200db commit 0f823cc

File tree

14 files changed

+235
-142
lines changed

14 files changed

+235
-142
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ defaults: &defaults
8181
virtualenv ci
8282
. ci/bin/activate
8383
pip install six lxml flake8 tox pytest black .[test]
84-
python setup.py develop
84+
pip install --editable .
8585
# Save dependency cache
8686
- save_cache:
8787
key: v1-dep-{{ .Branch }}-{{ epoch }}

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Dev environment setup
22

33
Dev environment setup is largely the same as setup in the tutorial, but instead of pip installing the version
4-
in pypi, you can set up using `python setup.py develop`.
4+
in pypi, you can set up using `pip install --editable .`.
55

66

77
# Contributing

notebooker/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class NotebookResultComplete(NotebookResultBase):
148148
raw_html = attr.ib(default="")
149149
email_html = attr.ib(default="")
150150
update_time = attr.ib(default=datetime.datetime.now())
151-
pdf = attr.ib(default="")
151+
pdf = attr.ib(default=b"")
152152
report_title = attr.ib(default="")
153153
overrides = attr.ib(default=attr.Factory(dict))
154154
mailto = attr.ib(default="")

notebooker/execute_notebook.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def _run_checks(
110110

111111
logger.info("Saving output notebook as HTML from {}".format(ipynb_executed_path))
112112
html, resources = ipython_to_html(ipynb_executed_path, job_id)
113-
email_html, resources = ipython_to_html(ipynb_executed_path, job_id, hide_code=hide_code)
113+
email_html, _ = ipython_to_html(ipynb_executed_path, job_id, hide_code=hide_code)
114114
pdf = ipython_to_pdf(raw_executed_ipynb, report_title, hide_code=hide_code) if generate_pdf_output else ""
115115

116116
notebook_result = NotebookResultComplete(

notebooker/serialization/mongo.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,16 +199,26 @@ def _convert_result(
199199
if cls is None:
200200
return None
201201

202+
def ignore_missing_files(f):
203+
def _ignore_missing_files(path, *args, **kwargs):
204+
try:
205+
return f(path, *args, **kwargs)
206+
except NoFile:
207+
logger.error("Could not find file %s in %s", path, self.result_data_store)
208+
return ""
209+
return _ignore_missing_files
210+
211+
@ignore_missing_files
202212
def read_file(path, is_json=False):
213+
r = self.result_data_store.get_last_version(path).read()
203214
try:
204-
r = self.result_data_store.get_last_version(path).read()
205-
try:
206-
return "" if not r else json.loads(r) if is_json else r.decode("utf8")
207-
except UnicodeDecodeError:
208-
return r
209-
except NoFile:
210-
logger.error("Could not find file %s in %s", path, self.result_data_store)
211-
return ""
215+
return "" if not r else json.loads(r) if is_json else r.decode("utf8")
216+
except UnicodeDecodeError:
217+
return r
218+
219+
@ignore_missing_files
220+
def read_bytes_file(path):
221+
return self.result_data_store.get_last_version(path).read()
212222

213223
if not load_payload:
214224
result.pop("stdout", None)
@@ -219,7 +229,7 @@ def read_file(path, is_json=False):
219229
result["raw_html_resources"]["outputs"] = outputs
220230
if result.get("generate_pdf_output"):
221231
pdf_filename = _pdf_filename(result["job_id"])
222-
result["pdf"] = read_file(pdf_filename)
232+
result["pdf"] = read_bytes_file(pdf_filename)
223233
if not result.get("raw_ipynb_json"):
224234
result["raw_ipynb_json"] = read_file(_raw_json_filename(result["job_id"]), is_json=True)
225235
if not result.get("raw_html"):

notebooker/utils/conversion.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def ipython_to_html(ipynb_path: str, job_id: str, hide_code: bool = False) -> (n
3333
nb = nbformat.reads(nb_file.read(), as_version=nbformat.v4.nbformat)
3434
resources_dir = get_resources_dir(job_id)
3535
html, resources = html_exporter_with_figs.from_notebook_node(nb, resources={"output_files_dir": resources_dir})
36+
resources = {k: v for (k, v) in resources.items() if not callable(v)}
3637
return html, resources
3738

3839

setup.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,29 @@ def get_long_description():
5151
zip_safe=False,
5252
include_package_data=True,
5353
install_requires=[
54+
"apscheduler",
55+
"babel",
56+
"cachelib",
57+
"click>7.1.0",
58+
"dataclasses",
59+
"flask",
5460
"gevent",
61+
"gitpython",
62+
"inflection",
63+
"ipykernel",
5564
"ipython",
56-
"pandas",
65+
"ipython_genutils",
66+
"jupytext>=1.2.0",
5767
"matplotlib",
58-
"pymongo",
59-
"papermill",
60-
"dataclasses",
61-
"nbconvert<6.0.0", # Pin this because new template locations do not seem to work on OSX
68+
"nbconvert",
6269
"nbformat",
63-
"jupytext>=1.2.0",
64-
"ipykernel",
65-
"stashy",
66-
"click>7.1.0",
70+
"pandas",
71+
"papermill",
72+
"pymongo",
6773
"python-dateutil",
68-
"apscheduler",
69-
"flask",
7074
"requests",
7175
"retrying",
72-
"gitpython",
73-
"cachelib",
74-
"inflection",
75-
"babel",
76+
"stashy",
7677
],
7778
extras_require={
7879
"prometheus": ["prometheus_client"],

tests/conftest.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
import os
2+
13
import pytest
4+
from pytest_server_fixtures import CONFIG
5+
from pytest_server_fixtures.mongo import MongoTestServer
6+
from pytest_fixture_config import yield_requires_config
27

38
from notebooker.constants import (
49
DEFAULT_DATABASE_NAME,
@@ -11,6 +16,43 @@
1116
from notebooker.web.app import create_app, setup_app
1217

1318

19+
class MongoTestServerWithPath(MongoTestServer):
20+
@property
21+
def env(self):
22+
return {"PATH": os.environ["PATH"]}
23+
24+
25+
def _mongo_server():
26+
"""This does the actual work - there are several versions of this used
27+
with different scopes.
28+
"""
29+
test_server = MongoTestServerWithPath()
30+
try:
31+
test_server.start()
32+
yield test_server
33+
finally:
34+
test_server.teardown()
35+
36+
37+
@pytest.yield_fixture(scope="function")
38+
@yield_requires_config(CONFIG, ["mongo_bin"])
39+
def mongo_server():
40+
"""Function-scoped MongoDB server started in a local thread.
41+
This also provides a temp workspace.
42+
We tear down, and cleanup mongos at the end of the test.
43+
44+
For completeness, we tidy up any outstanding mongo temp directories
45+
at the start and end of each test session
46+
47+
Attributes
48+
----------
49+
api (`pymongo.MongoClient`) : PyMongo Client API connected to this server
50+
.. also inherits all attributes from the `workspace` fixture
51+
"""
52+
for server in _mongo_server():
53+
yield server
54+
55+
1456
@pytest.fixture
1557
def bson_library(mongo_server, test_db_name, test_lib_name):
1658
return mongo_server.api[test_db_name][test_lib_name]
@@ -98,7 +140,7 @@ def flask_app(webapp_config):
98140

99141

100142
@pytest.fixture
101-
def setup_and_cleanup_notebooker_filesystem(webapp_config):
143+
def setup_and_cleanup_notebooker_filesystem(webapp_config, setup_workspace):
102144
try:
103145
initialise_base_dirs(webapp_config=webapp_config)
104146
yield

tests/integration/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
}
118118
"""
119119

120+
120121
@pytest.fixture
121122
def setup_workspace(workspace):
122123
(workspace.workspace + "/templates").mkdir()
@@ -130,4 +131,4 @@ def setup_workspace(workspace):
130131
ipynb_report_to_run.write_lines(DUMMY_REPORT_IPYNB.split("\n"))
131132

132133
report_to_run_failing = workspace.workspace + "/templates/fake/report_failing.py"
133-
report_to_run_failing.write_lines(DUMMY_FAILING_REPORT.split("\n"))
134+
report_to_run_failing.write_lines(DUMMY_FAILING_REPORT.split("\n"))

tests/integration/test_e2e.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,7 @@ def _check_report_output(job_id, serialiser, **kwargs):
3232

3333
@pytest.mark.parametrize(
3434
"report_name",
35-
[
36-
"fake/py_report",
37-
"fake/ipynb_report"
38-
],
35+
["fake/py_report", "fake/ipynb_report"],
3936
)
4037
@freezegun.freeze_time(datetime.datetime(2018, 1, 12))
4138
def test_run_report(bson_library, flask_app, setup_and_cleanup_notebooker_filesystem, setup_workspace, report_name):
@@ -66,6 +63,7 @@ def test_run_report(bson_library, flask_app, setup_and_cleanup_notebooker_filesy
6663
assert job_id == serialiser.get_latest_successful_job_id_for_name_and_params(report_name, overrides)
6764
assert job_id == serialiser.get_latest_successful_job_id_for_name_and_params(report_name, None)
6865

66+
6967
@freezegun.freeze_time(datetime.datetime(2018, 1, 12))
7068
def test_run_failing_report(bson_library, flask_app, setup_and_cleanup_notebooker_filesystem, setup_workspace):
7169
with flask_app.app_context():
@@ -91,13 +89,12 @@ def test_run_failing_report(bson_library, flask_app, setup_and_cleanup_notebooke
9189

9290
@pytest.mark.parametrize(
9391
"report_name",
94-
[
95-
"fake/py_report",
96-
"fake/ipynb_report"
97-
],
92+
["fake/py_report", "fake/ipynb_report"],
9893
)
9994
@freezegun.freeze_time(datetime.datetime(2018, 1, 12))
100-
def test_run_report_and_rerun(bson_library, flask_app, setup_and_cleanup_notebooker_filesystem, setup_workspace, report_name):
95+
def test_run_report_and_rerun(
96+
bson_library, flask_app, setup_and_cleanup_notebooker_filesystem, setup_workspace, report_name
97+
):
10198
with flask_app.app_context():
10299
serialiser = get_serializer()
103100
overrides = {"n_points": 5}
@@ -140,13 +137,12 @@ def test_run_report_and_rerun(bson_library, flask_app, setup_and_cleanup_noteboo
140137

141138
@pytest.mark.parametrize(
142139
"report_name",
143-
[
144-
"fake/py_report",
145-
"fake/ipynb_report"
146-
],
140+
["fake/py_report", "fake/ipynb_report"],
147141
)
148142
@freezegun.freeze_time(datetime.datetime(2018, 1, 12))
149-
def test_run_report_hide_code(bson_library, flask_app, setup_and_cleanup_notebooker_filesystem, setup_workspace, report_name):
143+
def test_run_report_hide_code(
144+
bson_library, flask_app, setup_and_cleanup_notebooker_filesystem, setup_workspace, report_name
145+
):
150146
with flask_app.app_context():
151147
serialiser = get_serializer()
152148
overrides = {"n_points": 5}

0 commit comments

Comments
 (0)