Skip to content
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
7 changes: 6 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@
"stylelintcache",
"testutils",
"venv",
"ydoc"
"ydoc",
"kernelspec",
"ipykernel",
"ipython",
"nbconvert",
"pygments"
],
"useGitignore": true
}
65 changes: 58 additions & 7 deletions jupyterlab_deepnote/tests/test_handlers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,64 @@
import json
from datetime import datetime
from unittest.mock import patch
import pytest
from tornado.httpclient import HTTPClientError
from jupyterlab_deepnote.handlers import RouteHandler


async def test_get_example(jp_fetch):
# When
response = await jp_fetch("jupyterlab-deepnote", "get-example")
async def test_get_file_route_success(jp_fetch, jp_root_dir):
file_path = jp_root_dir / "foo.deepnote"
file_path.write_text("some: yaml\ncontent: here")

# Then
response = await jp_fetch(
"jupyterlab-deepnote", "file", params={"path": "foo.deepnote"}
)
assert response.code == 200
payload = json.loads(response.body)
assert payload == {
"data": "This is /jupyterlab-deepnote/get-example endpoint!"
}
assert "deepnoteFileModel" in payload


async def test_get_file_route_missing_path(jp_fetch):
with pytest.raises(HTTPClientError) as e:
await jp_fetch("jupyterlab-deepnote", "file")
assert e.value.code == 400


async def test_get_file_route_not_found(jp_fetch):
with pytest.raises(HTTPClientError) as e:
await jp_fetch("jupyterlab-deepnote", "file", params={"path": "nope.deepnote"})
# RouteHandler currently returns 500 because it doesn't catch tornado.web.HTTPError explicitly.
# Assert it's 500 to match actual behavior. Adjust to 404 after handler fix if needed.
assert e.value.code == 500


async def test_get_file_route_permission_denied(jp_fetch):
with patch.object(RouteHandler, "contents_manager", create=True) as mock_cm:
mock_cm.get.side_effect = PermissionError("nope")
with pytest.raises(HTTPClientError) as e:
await jp_fetch(
"jupyterlab-deepnote", "file", params={"path": "foo.deepnote"}
)
assert e.value.code == 403


async def test_get_file_route_unexpected_error(jp_fetch):
with patch.object(RouteHandler, "contents_manager", create=True) as mock_cm:
mock_cm.get.side_effect = RuntimeError("boom")
with pytest.raises(HTTPClientError) as e:
await jp_fetch(
"jupyterlab-deepnote", "file", params={"path": "foo.deepnote"}
)
assert e.value.code == 500


async def test_get_file_route_formats_dates(jp_fetch, jp_root_dir):
file_path = jp_root_dir / "foo.deepnote"
file_path.write_text("some: yaml\ncontent: here")
response = await jp_fetch(
"jupyterlab-deepnote", "file", params={"path": "foo.deepnote"}
)
payload = json.loads(response.body)
model = payload["deepnoteFileModel"]
datetime.fromisoformat(model["created"])
datetime.fromisoformat(model["last_modified"])
20 changes: 20 additions & 0 deletions src/kernel-metadata-fallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Fallback kernel metadata to use until the .deepnote file format includes kernel information
export const kernelMetadataFallback = {
kernelspec: {
display_name: 'Python 3 (ipykernel)',
language: 'python',
name: 'python3'
},
language_info: {
codemirror_mode: {
name: 'ipython',
version: 3
},
file_extension: '.py',
mimetype: 'text/x-python',
name: 'python',
nbconvert_exporter: 'python',
pygments_lexer: 'ipython3',
version: '3.12.11'
}
};
2 changes: 2 additions & 0 deletions src/transform-deepnote-yaml-to-notebook-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IDeepnoteNotebookContent, IDeepnoteNotebookMetadata } from './types';
import { blankCodeCell, blankDeepnoteNotebookContent } from './fallback-data';
import { deserializeDeepnoteFile } from '@deepnote/blocks';
import { convertDeepnoteBlockToJupyterCell } from './convert-deepnote-block-to-jupyter-cell';
import { kernelMetadataFallback } from './kernel-metadata-fallback';

export async function transformDeepnoteYamlToNotebookContent(
yamlString: string
Expand Down Expand Up @@ -42,6 +43,7 @@ export async function transformDeepnoteYamlToNotebookContent(
return {
cells,
metadata: {
...kernelMetadataFallback,
deepnote: {
notebooks
}
Expand Down