Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option for not writing an output ipynb file #669

Merged
merged 2 commits into from
Jun 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions papermill/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def execute_notebook(
----------
input_path : str or Path
Path to input notebook
output_path : str or Path
Path to save executed notebook
output_path : str or Path or None
Path to save executed notebook. If None, no file will be saved
parameters : dict, optional
Arbitrary keyword arguments to pass to the notebook parameters
engine_name : str, optional
Expand Down
21 changes: 21 additions & 0 deletions papermill/iorw.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ def read(self, path, extensions=['.ipynb', '.json']):
return notebook_metadata

def write(self, buf, path, extensions=['.ipynb', '.json']):
if path is None:
return
if path == '-':
try:
return sys.stdout.buffer.write(buf.encode('utf-8'))
Expand Down Expand Up @@ -158,6 +160,9 @@ def register_entry_points(self):
self.register(entrypoint.name, entrypoint.load())

def get_handler(self, path):
if path is None:
return NoIOHandler()

local_handler = None
for scheme, handler in self._handlers:
if scheme == 'local':
Expand Down Expand Up @@ -406,6 +411,22 @@ def pretty_path(self, path):
return path


class NoIOHandler(object):
'''Handler for output_path of None - intended to not write anything'''

def read(self, path):
raise PapermillException('read is not supported by NoIOHandler')

def listdir(self, path):
raise PapermillException('listdir is not supported by NoIOHandler')

def write(self, buf, path):
return

def pretty_path(self, path):
return 'Notebook will not be saved'


# Hack to make YAML loader not auto-convert datetimes
# https://stackoverflow.com/a/52312810
class NoDatesSafeLoader(yaml.SafeLoader):
Expand Down
7 changes: 5 additions & 2 deletions papermill/parameterize.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ def parameterize_path(path, parameters):

Parameters
----------
path : string
path : string or None
Path with optional parameters, as a python format string
parameters : dict
parameters : dict or None
Arbitrary keyword arguments to fill in the path
"""
if path is None:
return

if parameters is None:
parameters = {}

Expand Down
7 changes: 7 additions & 0 deletions papermill/tests/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ def test_report_mode(self):
self.assertEqual(cell.metadata.get('jupyter', {}).get('source_hidden'), True)


class TestOutputPathNone(unittest.TestCase):
def test_output_path_of_none(self):
"""Output path of None should return notebook node obj but not write an ipynb"""
nb = execute_notebook(get_notebook_path('simple_execute.ipynb'), None, {'msg': 'Hello'})
self.assertEqual(nb.metadata.papermill.parameters, {'msg': 'Hello'})


class TestCWD(unittest.TestCase):
def setUp(self):
self.test_dir = tempfile.mkdtemp()
Expand Down
24 changes: 24 additions & 0 deletions papermill/tests/test_iorw.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from ..iorw import (
HttpHandler,
LocalHandler,
NoIOHandler,
ADLHandler,
PapermillIO,
read_yaml_file,
Expand Down Expand Up @@ -90,6 +91,9 @@ def test_get_local_handler(self):
self.papermill_io.register("local", self.fake2)
self.assertEqual(self.papermill_io.get_handler("dne"), self.fake2)

def test_get_no_io_handler(self):
self.assertIsInstance(self.papermill_io.get_handler(None), NoIOHandler)

def test_entrypoint_register(self):

fake_entrypoint = Mock(load=Mock())
Expand Down Expand Up @@ -163,6 +167,9 @@ def test_write_with_no_file_extension(self):
with pytest.warns(UserWarning):
self.papermill_io.write("buffer", "fake/path")

def test_write_with_path_of_none(self):
self.assertIsNone(self.papermill_io.write('buffer', None))

def test_write_with_invalid_file_extension(self):
with pytest.warns(UserWarning):
self.papermill_io.write("buffer", "fake/path/fakeoutputpath.ipynb1")
Expand Down Expand Up @@ -246,6 +253,23 @@ def test_invalid_string(self):
LocalHandler().read("a random string")


class TestNoIOHandler(unittest.TestCase):
def test_raises_on_read(self):
with self.assertRaises(PapermillException):
NoIOHandler().read(None)

def test_raises_on_listdir(self):
with self.assertRaises(PapermillException):
NoIOHandler().listdir(None)

def test_write_returns_none(self):
self.assertIsNone(NoIOHandler().write('buf', None))

def test_pretty_path(self):
expect = 'Notebook will not be saved'
self.assertEqual(NoIOHandler().pretty_path(None), expect)


class TestADLHandler(unittest.TestCase):
"""
Tests for `ADLHandler`
Expand Down
4 changes: 4 additions & 0 deletions papermill/tests/test_parameterize.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,7 @@ def test_parameterized_path_with_none_parameters(self):
with self.assertRaises(PapermillMissingParameterException) as context:
parameterize_path("{foo}", None)
self.assertEqual(str(context.exception), "Missing parameter 'foo'")

def test_path_of_none_returns_none(self):
self.assertIsNone(parameterize_path(path=None, parameters={'foo': 'bar'}))
self.assertIsNone(parameterize_path(path=None, parameters=None))