Skip to content

Commit 886d008

Browse files
committed
test(notebooks): cover snapshot failures and malformed HTTP responses
1 parent bc2d7d1 commit 886d008

3 files changed

Lines changed: 40 additions & 4 deletions

File tree

‎deepnote_toolkit/notebooks/yaml_loader.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111

1212

1313
class _CoreSchemaLoader(_BaseLoader): # type: ignore[misc,valid-type]
14-
"""A safe loader that resolves plain scalars by the YAML 1.2 core schema.
14+
"""A safe loader for the scalar conventions used by `.deepnote` files.
1515
1616
`.deepnote` files are written as YAML 1.2, where `No`, `on`, `12:30` and
1717
`2026-08-17` are strings. PyYAML's YAML 1.1 rules read them as booleans,
18-
numbers and dates.
18+
numbers and dates. Leading-zero scalars intentionally remain strings, unlike
19+
the core schema. Merge keys are treated as literal keys, not YAML 1.1 merges.
1920
"""
2021

2122
yaml_implicit_resolvers: dict[str, Any] = {}

‎docs/streamlit-apps.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ if st.button("Run"):
2222
elif result.snapshot_status == "pending":
2323
st.info("The run finished, but its outputs are not available yet.")
2424
elif (table := result.first_dataframe()) is not None:
25-
st.dataframe(table.records())
25+
st.dataframe(table.records(include_index=False))
2626
else:
2727
st.write(result.text())
2828
except RunnerError as error:
@@ -63,7 +63,8 @@ without a valid saved choice starts empty. Unselected single selects and partial
6363
selected date ranges are omitted from the returned dictionary; disable your Run
6464
button until required fields are present. An omitted input uses the notebook's
6565
value according to the API. Stale multi-select choices produce a warning. Invalid
66-
slider bounds/defaults and duplicate variable names raise `ValueError`.
66+
slider bounds/defaults and duplicate variable names raise `ValueError`. File inputs
67+
render as text paths; this helper does not upload files.
6768

6869
`runner.info().matches_inputs(document.inputs)` compares static input definitions:
6970
unique names, types, single/multiple selection, options, and slider bounds/steps.

‎tests/unit/test_notebooks_runners.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,3 +534,37 @@ def credentials(*, timeout):
534534
session=session(),
535535
).run({})
536536
assert not http.calls
537+
538+
539+
@pytest.mark.parametrize("status", [403, 503])
540+
def test_snapshot_poll_error_policy(http, runner, status):
541+
add_run(http, run_response(snapshotStatus="pending"), create=True)
542+
http.get(
543+
"https://api.deepnote.com/v2/runs/run-1?snapshotDelivery=blocks", status=status
544+
)
545+
if status == 403:
546+
with pytest.raises(RunnerError, match="403"):
547+
runner.run({})
548+
assert len(http.calls) == 2
549+
else:
550+
add_run(http, run_response(snapshotStatus="available", snapshotBlocks=[]))
551+
assert runner.run({}).snapshot_status == "available"
552+
assert len(http.calls) == 3
553+
554+
555+
@pytest.mark.parametrize("body", ["not-json", "[]", "null"])
556+
def test_invalid_json_response_is_a_runner_error(http, body):
557+
http.get("http://127.0.0.1:8787/api/info", body=body)
558+
with pytest.raises(RunnerError, match="invalid JSON|non-object"):
559+
DeepnoteLocalRunner(session=session()).info()
560+
561+
562+
def test_same_origin_redirect_is_also_refused(http, runner):
563+
http.post(
564+
"https://api.deepnote.com/v2/runs",
565+
status=307,
566+
headers={"Location": "https://api.deepnote.com/other"},
567+
)
568+
with pytest.raises(RunnerError, match="Refused a redirect"):
569+
runner.run({})
570+
assert len(http.calls) == 1

0 commit comments

Comments
 (0)