fix(notebook): send the notebook path to the UI with forward slashes (#1466)

* fix(notebook): send the notebook path to the UI with forward slashes

On Windows a notebook's snapshot and output events carried its canonical
path as `to_string_lossy()` (`C:\a\b.ipynb`), and the UI uses that path as
the notebook tab's identity, while the project tree and editor name the same
file `C:/a/b.ipynb`. NotebookSnapshot.path and NotebookOutputEvent.path are
now IpcPath, like the other path fields on the IPC boundary (#1456 did the
same for Spring route sources and Add to .gitignore).

* chore: regenerate bindings for the notebook IpcPath fields

---------

Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
This commit is contained in:
kevinh
2026-11-05 20:25:22 +08:00
committed by GitHub
co-authored by l0ng-ai
parent 1aec21b43f
commit 4a217a4473
3 changed files with 18 additions and 8 deletions
+13 -3
View File
@@ -1,7 +1,7 @@
//! Project-incarnation notebook ownership and whole-batch execution admission.
use crate::ops::Channel;
use ide_core::error::ErrorKind;
use ide_core::{CancellationToken, IdeError, IdeEvent, IdeResult, SharedSink};
use ide_core::{CancellationToken, IdeError, IdeEvent, IdeResult, IpcPath, SharedSink};
use ide_notebook::kernel::{KernelManager, KernelOutput};
use ide_notebook::{NotebookDocument, NotebookEdit, NotebookSnapshot};
use parking_lot::Mutex;
@@ -17,7 +17,7 @@ use tokio::sync::{Mutex as AsyncMutex, watch};
#[serde(rename_all = "camelCase")]
pub struct NotebookOutputEvent {
pub id: String,
pub path: String,
pub path: IpcPath,
pub cell: String,
pub msg_id: String,
pub kind: String,
@@ -536,7 +536,7 @@ fn commit_output(
};
Ok(Some(NotebookOutputEvent {
id: document.id.clone(),
path: document.path.to_string_lossy().into_owned(),
path: document.path.clone().into(),
cell: cell.to_owned(),
msg_id: output.msg_id,
kind: output.kind,
@@ -592,6 +592,16 @@ mod tests {
other.shutdown().await;
}
#[tokio::test]
async fn the_notebook_path_reaches_the_ui_as_the_project_tree_names_it() {
let (dir, service, _) = fixture();
let ui_path =
format!("{}/session.ipynb", ide_core::ipc_path::to_ipc(&dunce::canonicalize(dir.path()).unwrap()));
let snapshot = service.open(Path::new(&ui_path)).unwrap();
assert_eq!(serde_json::to_value(&snapshot).unwrap()["path"], ui_path);
service.shutdown().await;
}
#[tokio::test(start_paused = true)]
async fn failed_close_keeps_the_incarnation_recoverable_until_a_retry_succeeds() {
let (dir, service, initial) = fixture();
+3 -3
View File
@@ -9,7 +9,7 @@ use std::{
time::{Duration, Instant},
};
use ide_core::{IdeError, IdeResult, error::ErrorKind};
use ide_core::{IdeError, IdeResult, IpcPath, error::ErrorKind};
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use specta::Type;
@@ -22,7 +22,7 @@ use crate::kernel::KernelOutput;
#[serde(rename_all = "camelCase")]
pub struct NotebookSnapshot {
pub id: String,
pub path: String,
pub path: IpcPath,
pub version: u32,
pub dirty: bool,
pub can_undo: bool,
@@ -188,7 +188,7 @@ impl NotebookDocument {
pub fn snapshot(&self) -> NotebookSnapshot {
NotebookSnapshot {
id: self.id.clone(),
path: self.path.to_string_lossy().into_owned(),
path: self.path.clone().into(),
version: self.version,
dirty: self.is_dirty(),
can_undo: !self.execution_active && !self.undo.is_empty(),
+2 -2
View File
@@ -5342,7 +5342,7 @@ export type NotebookEdit = { type: "setSource"; cell: string; source: string } |
export type NotebookOutputEvent = {
id: string,
path: string,
path: IpcPath,
cell: string,
msgId: string,
kind: string,
@@ -5354,7 +5354,7 @@ export type NotebookOutputEvent = {
export type NotebookSnapshot = {
id: string,
path: string,
path: IpcPath,
version: number,
dirty: boolean,
canUndo: boolean,