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

Added a warning for gluing an object outside of a context #45

Merged
merged 7 commits into from
May 8, 2019
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions scrapbook/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
from .scraps import Scrap, scrap_to_payload
from .schemas import GLUE_PAYLOAD_FMT
from .encoders import registry as encoder_registry
from .utils import kernel_required


@kernel_required
def glue(name, scrap, encoder=None, display=None):
"""
Records a scrap (data value) in the given notebook cell.
Expand Down
2 changes: 2 additions & 0 deletions scrapbook/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .schemas import GLUE_PAYLOAD_PREFIX, RECORD_PAYLOAD_PREFIX
from .encoders import registry as encoder_registry
from .exceptions import ScrapbookException
from .utils import kernel_required


def merge_dicts(dicts):
Expand Down Expand Up @@ -252,6 +253,7 @@ def _strip_scrapbook_metadata(self, metadata):
copied.pop("scrapbook", None)
return copied

@kernel_required
def reglue(self, name, new_name=None, raise_on_missing=True, unattached=False):
"""
Display output from a named source of the notebook.
Expand Down
16 changes: 16 additions & 0 deletions scrapbook/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@
from IPython.display import Image

from . import get_fixture_path
from .. import utils
from ..api import glue
from ..schemas import GLUE_PAYLOAD_FMT


@pytest.fixture(scope='session', autouse=True)
def kernel_mock():
"""Mocks the kernel to capture warnings during testing"""
with mock.patch.object(utils, 'is_kernel') as _fixture:
_fixture.return_value = True
yield _fixture


@pytest.mark.parametrize(
"name,scrap,encoder,data,metadata",
[
Expand Down Expand Up @@ -196,3 +205,10 @@ def test_glue_plus_display(
mock.call(display_output, metadata=display_metadata, raw=True),
]
)


@mock.patch("scrapbook.utils.is_kernel")
def test_glue_warning(kernel_mock):
kernel_mock.return_value = False
with pytest.warns(UserWarning):
glue('foo', 'bar', 'text')
23 changes: 22 additions & 1 deletion scrapbook/tests/test_notebooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from nbformat.v4 import new_notebook, new_code_cell, new_markdown_cell, new_output

from . import get_notebook_path, get_notebook_dir
from .. import read_notebook
from .. import read_notebook, utils
from ..models import Notebook
from ..exceptions import ScrapbookException

Expand All @@ -21,6 +21,13 @@
FileNotFoundError = IOError


@pytest.fixture(scope='session', autouse=True)
def kernel_mock():
"""Mocks the kernel to capture warnings during testing"""
with mock.patch.object(utils, 'is_kernel') as _fixture:
yield _fixture


class AnyDict(object):
def __eq__(self, other):
return isinstance(other, dict)
Expand Down Expand Up @@ -298,3 +305,17 @@ def test_metadata_but_empty_content():
def test_markdown():
nb = Notebook(new_notebook(cells=[new_markdown_cell("this is a test.")]))
assert nb.scraps == collections.OrderedDict()


@mock.patch("scrapbook.utils.is_kernel")
def test_reglue_warning(kernel_mock, notebook_result):
kernel_mock.return_value = False
with pytest.warns(UserWarning):
notebook_result.reglue('number')


@mock.patch("scrapbook.utils.is_kernel")
def test_reglue_kernel_no_warning(kernel_mock, notebook_result, recwarn):
kernel_mock.return_value = True
notebook_result.reglue('number')
assert len(recwarn) == 0
9 changes: 8 additions & 1 deletion scrapbook/tests/test_scrapbooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@
from pandas.util.testing import assert_frame_equal

from . import get_notebook_path
from .. import read_notebooks
from .. import read_notebooks, utils
from ..scraps import Scrap, Scraps


@pytest.fixture(scope='session', autouse=True)
def kernel_mock():
"""Mocks the kernel to capture warnings during testing"""
with mock.patch.object(utils, 'is_kernel') as _fixture:
yield _fixture


class AnyMarkdownWith(Markdown):
def __eq__(self, other):
try:
Expand Down
22 changes: 22 additions & 0 deletions scrapbook/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys

from mock import MagicMock
from ..utils import is_kernel


def test_is_kernel_true():
class FakeIPyKernel():
kernel = True
sys.modules['IPython'] = MagicMock()
sys.modules['IPython'].get_ipython.return_value = FakeIPyKernel
assert is_kernel()
del sys.modules['IPython']


def test_not_kernel_in_ipython():
sys.modules['IPython'] = MagicMock()
sys.modules['IPython'].get_ipython.return_value = {}
assert not is_kernel()
del sys.modules['IPython']
33 changes: 33 additions & 0 deletions scrapbook/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
"""
utils.py
Provides the utilities for scrapbook functions and operations.
"""
import sys
import warnings
from functools import wraps


def is_kernel():
"""
Returns True if execution context is inside a kernel
"""
# if IPython hasn't been imported, there's nothing to check
if 'IPython' in sys.modules:
from IPython import get_ipython
ipy = get_ipython()
if ipy is not None:
return getattr(ipy, 'kernel', None) is not None
return False


def kernel_required(f):
@wraps(f)
def wrapper(*args, **kwds):
if not is_kernel():
warnings.warn(
"No kernel detected for '{fname}'.".format(
fname=f.__name__))
return f(*args, **kwds)
return wrapper