diff --git a/.gitignore b/.gitignore index ef8bc3d..c661ff5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ dist/ .pytest_cache/ __pycache__/ *.pyc +.coverage +htmlcov/ diff --git a/faculty_mill/execute.py b/faculty_mill/execute.py new file mode 100644 index 0000000..dd513d2 --- /dev/null +++ b/faculty_mill/execute.py @@ -0,0 +1,31 @@ +import shutil +from pathlib import Path +from io import TextIOWrapper + +import click +from papermill.cli import papermill + + +def run( + notebook: TextIOWrapper, + directory: Path, + execute: bool, + click_context: click.Context, +) -> Path: + input_path = directory / "input.ipynb" + output_path = directory / "output.ipynb" + with input_path.open("w") as input_file: + shutil.copyfileobj(notebook, input_file) + + if execute: + papermill_click_context = papermill.make_context( + "The papermill execution command.", + [str(input_path), str(output_path)] + click_context.args, + parent=click_context, + ) + + papermill.invoke(papermill_click_context) + else: + shutil.copy(str(input_path), str(output_path)) + + return output_path diff --git a/faculty_mill/faculty_reporter.py b/faculty_mill/faculty_reporter.py index 06787d9..e889c99 100644 --- a/faculty_mill/faculty_reporter.py +++ b/faculty_mill/faculty_reporter.py @@ -1,13 +1,12 @@ -import shutil from contextlib import contextmanager from pathlib import Path from tempfile import TemporaryDirectory import click -from papermill.cli import papermill -from publish import publish +from .publish import publish from .version import print_version +from .execute import run @contextmanager @@ -69,23 +68,8 @@ def main( """ with tmpdir() as directory: - input_path = directory / "input.ipynb" - output_path = directory / "output.ipynb" - # write the input file to the new, temporary input file - # this is to allow processing of stdin - with input_path.open("w") as input_file: - shutil.copyfileobj(notebook, input_file) - - if execute: - papermill_click_context = papermill.make_context( - "The papermill execution command.", - [str(input_path), str(output_path)] + click_context.args, - parent=click_context, - ) - papermill.invoke(papermill_click_context) - else: - shutil.copy(input_path, output_path) + output_path = run(notebook, directory, execute, click_context) publish(report_name, output_path, show_code=show_code) diff --git a/tests/test_execute.py b/tests/test_execute.py new file mode 100644 index 0000000..c1dba10 --- /dev/null +++ b/tests/test_execute.py @@ -0,0 +1,54 @@ +from io import StringIO +from pathlib import Path +from unittest.mock import Mock, patch +import pytest + +from faculty_mill.execute import run + + +@pytest.fixture +def tempdir(tmpdir): + """Fixture that wraps pytest fixture to return Path object""" + return Path(str(tmpdir)) + + +@pytest.fixture +def tmpnotebook(): + test_notebook = StringIO() + test_notebook.write("test notebook content") + test_notebook.seek(0) + return test_notebook + + +@pytest.fixture +def mock_click_context(): + click_context = Mock() + click_context.args = ["arg 1", "arg 2"] + return click_context + + +def test_that_run_copies_content(tempdir, tmpnotebook, mock_click_context): + output_notebook = run( + tmpnotebook, tempdir, execute=False, click_context=mock_click_context + ) + assert output_notebook.parent == tempdir + assert output_notebook.read_text() == "test notebook content" + + +@patch("faculty_mill.execute.papermill") +def test_that_run_calls_papermill( + mock_papermill, tempdir, tmpnotebook, mock_click_context +): + output_notebook = run( + tmpnotebook, tempdir, execute=True, click_context=mock_click_context + ) + assert output_notebook.parent == tempdir + mock_papermill.make_context.assert_called_once_with( + "The papermill execution command.", + [str(tempdir / "input.ipynb"), str(tempdir / "output.ipynb")] + + mock_click_context.args, + parent=mock_click_context, + ) + mock_papermill.invoke.assert_called_once_with( + mock_papermill.make_context.return_value + )