fix: rabbit review 001 - persist Streamlit failures, guard Jupyter lifecycle
- st_demo: persist failure in call history, clear active_handle, and disable Run while call active to avoid overwriting handle - JupyterApp.shutdown: gather all shutdowns with return_exceptions=True and re-raise as BaseExceptionGroup so one failure doesn't leak kernels - messages: fallback known-but-malformed messages to UnknownJupyterMessage via ValidationError, make Unknown channel permissive (str) for nuance - transport: record reader failures as terminal state (_reader_failure) and fail fast from execute/messages_for instead of hanging - shell: don't reset execution_count to 0 when IPython returns None - README: use ipython_shell imports Skipped non-urgent/deferred items: line(), get_shell_2, test renames, import laziness, call-ID bounding, settle window config (worth doing later).
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from typing import Annotated, ClassVar, Final, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter
|
||||
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, ValidationError
|
||||
|
||||
|
||||
type JupyterChannel = Literal["iopub", "shell", "stdin"]
|
||||
@@ -176,6 +176,9 @@ class InputRequestMessage(_TypedMessage):
|
||||
class UnknownJupyterMessage(JupyterMessage):
|
||||
"""An extension or future message preserved without lossy parsing."""
|
||||
|
||||
# Allow any channel value so known-but-malformed fallbacks never fail
|
||||
# on a strict Literal. The parser preserves the transport channel verbatim.
|
||||
channel: str = "iopub" # type: ignore[assignment]
|
||||
raw: dict[str, object] = Field(default_factory=dict)
|
||||
|
||||
|
||||
@@ -252,7 +255,14 @@ def parse_jupyter_message(
|
||||
|
||||
if values["msg_type"] not in _KNOWN_MESSAGE_TYPES:
|
||||
return UnknownJupyterMessage.model_validate({**values, "raw": raw})
|
||||
return _KNOWN_MESSAGE_ADAPTER.validate_python(values)
|
||||
try:
|
||||
return _KNOWN_MESSAGE_ADAPTER.validate_python(values)
|
||||
except ValidationError:
|
||||
# Known msg_type but content or channel doesn't match the strict
|
||||
# model (e.g., extra execution_state, wrong stdout/stderr name,
|
||||
# or msg delivered on an unexpected channel). Degrade losslessly
|
||||
# instead of aborting the whole call.
|
||||
return UnknownJupyterMessage.model_validate({**values, "raw": raw})
|
||||
|
||||
|
||||
# Existing callers use this name for the transport-level message. Keep it as
|
||||
|
||||
Reference in New Issue
Block a user