Skip to content

Commit

Permalink
Merge branch 'master' into mm-voila
Browse files Browse the repository at this point in the history
  • Loading branch information
mmarchetti committed Mar 7, 2023
2 parents 6706207 + b0abbec commit f2f84da
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 2 deletions.
7 changes: 5 additions & 2 deletions rsconnect_jupyter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

from ssl import SSLError

from rsconnect_jupyter.managers import get_model

try:
from rsconnect_jupyter.version import version as __version__ # noqa
except ImportError:
Expand Down Expand Up @@ -74,7 +76,7 @@ def md5(s):
# https://github.com/jupyter/notebook/blob/master/notebook/base/handlers.py
class EndpointHandler(APIHandler):
@web.authenticated
def post(self, action):
async def post(self, action):
data = self.get_json_body()

if action == "verify_server":
Expand Down Expand Up @@ -161,7 +163,8 @@ def post(self, action):
hide_all_input = data.get("hide_all_input", False)
hide_tagged_input = data.get("hide_tagged_input", False)

model = self.contents_manager.get(path=nb_path)
model = await get_model(self.contents_manager, nb_path)

if model["type"] != "notebook":
# not a notebook
raise web.HTTPError(400, "Not a notebook: %s" % nb_path)
Expand Down
21 changes: 21 additions & 0 deletions rsconnect_jupyter/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from inspect import isawaitable
from typing import Union, Awaitable

from jupyter_server.services.contents.manager import ContentsManager


async def get_model(manager: ContentsManager, path: str) -> dict:
"""
Gets the model via the ContentsManager.
If the ContentsManager is async (e.g., AsyncContentsManager), then an await is issued. Otherwise,
the model is returned under synchronous expectations.
:param manager: A Jupyter ContentsManager
:param path: The model path
:return: The model
"""
model: Union[dict, Awaitable[dict]] = manager.get(path)
if isawaitable(model):
model = await model
return model
5 changes: 5 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,8 @@ packages = rsconnect_jupyter
python_requires = >=3.7
include_package_data = true
zip_safe = false

[options.extras_require]
test =
black
pytest
30 changes: 30 additions & 0 deletions tests/test_managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from unittest import TestCase
from unittest.mock import Mock, MagicMock, AsyncMock

from rsconnect_jupyter.managers import ContentsManager, get_model, isawaitable


class GetModelTestCase(TestCase):
async def test_synchronous(self):
model = AsyncMock()
manager = MagicMock(spec=ContentsManager)
manager.get = Mock(return_value=model)
path = "path"
spy = Mock(wraps=isawaitable, return_value=False)
res = await get_model(manager, path)
self.assertEqual(res, model)
model.assert_not_awaited()
manager.get.assert_called_once_with(path)
spy.assert_called_once_with(model)

async def test_asynchronous(self):
model = AsyncMock()
manager = MagicMock(spec=ContentsManager)
manager.get = Mock(return_value=model)
path = "path"
spy = Mock(wraps=isawaitable, return_value=True)
res = await get_model(manager, path)
self.assertEqual(res, model)
model.assert_awaited()
manager.get.assert_called_once_with(path)
spy.assert_called_once_with(model)

0 comments on commit f2f84da

Please sign in to comment.