-
Notifications
You must be signed in to change notification settings - Fork 35
Description
π Template Sync Required
Changes from the upstream vscode-python-tools-extension-template have not yet been incorporated into this repository.
Source PR
- Add Jupyter notebook cell support via LSP 3.17 Notebook Document SyncΒ vscode-python-tools-extension-template#265 β Add Jupyter notebook cell support via LSP 3.17 Notebook Document Sync
Summary
The template now ships with built-in support for linting Python cells inside Jupyter notebooks (.ipynb) and the VS Code Interactive Window via the LSP 3.17 Notebook Document Sync specification. This adds NOTEBOOK_SYNC_OPTIONS to the server initialization, a _get_document_path helper for resolving vscode-notebook-cell: URIs to the parent notebook's filesystem path, and four notebook lifecycle handlers (notebookDocument/didOpen, /didChange, /didSave, /didClose).
vscode-mypy currently explicitly skips notebook cells in _linting_helper with a "Not Supported" log warning. Adopting the template's pattern would enable mypy type checking in Jupyter notebook Python cells.
Files with missing changes
bundled/tool/lsp_server.pyβ Missing the notebook infrastructure:import urllib.parsenot presentNOTEBOOK_SYNC_OPTIONSconstant not presentLanguageServerconstructor does not includenotebook_document_sync_get_document_pathhelper not present- No
notebook_did_open,notebook_did_change,notebook_did_save, ornotebook_did_closehandlers _linting_helperexplicitly rejectsvscode-notebook-cell:URIs (lines 213β216) rather than handling them
Suggested fix
Below are the recommended additions to bundled/tool/lsp_server.py. Mypy-specific logic (e.g., reportingScope, daemon handling) should be preserved inside each new handler, mirroring how _linting_helper works for regular text documents.
1. Add the urllib.parse import (near the top with other stdlib imports):
+import urllib.parse2. Add NOTEBOOK_SYNC_OPTIONS (before or after MAX_WORKERS):
+import lsprotocol.types as lsp
+
+NOTEBOOK_SYNC_OPTIONS = lsp.NotebookDocumentSyncOptions(
+ notebook_selector=[
+ lsp.NotebookDocumentFilterWithNotebook(
+ notebook="jupyter-notebook",
+ cells=[lsp.NotebookCellLanguage(language="python")],
+ ),
+ lsp.NotebookDocumentFilterWithNotebook(
+ notebook="interactive",
+ cells=[lsp.NotebookCellLanguage(language="python")],
+ ),
+ ],
+ save=True,
+)3. Add notebook_document_sync to the LanguageServer constructor:
-LSP_SERVER = LanguageServer(name="Mypy", version="v0.1.0", max_workers=MAX_WORKERS)
+LSP_SERVER = LanguageServer(
+ name="Mypy",
+ version="v0.1.0",
+ max_workers=MAX_WORKERS,
+ notebook_document_sync=NOTEBOOK_SYNC_OPTIONS,
+)4. Add the _get_document_path helper (near other document helpers):
+def _get_document_path(cell_uri: str) -> str:
+ """Resolve a vscode-notebook-cell: URI to the parent notebook's filesystem path."""
+ parsed = urllib.parse.urlparse(cell_uri)
+ if parsed.scheme == "vscode-notebook-cell":
+ nb_uri = parsed._replace(scheme="file", fragment="").geturl()
+ return LSP_SERVER.workspace.get_text_document(nb_uri).path
+ return LSP_SERVER.workspace.get_text_document(cell_uri).path5. Add notebook lifecycle handlers (alongside the existing did_open, did_save, did_close handlers):
+`@LSP_SERVER`.feature(lsp.NOTEBOOK_DOCUMENT_DID_OPEN)
+def notebook_did_open(params: lsp.DidOpenNotebookDocumentParams) -> None:
+ """LSP handler for notebookDocument/didOpen request."""
+ nb = LSP_SERVER.workspace.get_notebook_document(
+ notebook_uri=params.notebook_document.uri
+ )
+ if nb is None:
+ return
+ for cell in nb.cells:
+ if cell.kind == lsp.NotebookCellKind.Code:
+ doc = LSP_SERVER.workspace.get_text_document(cell.document)
+ _linting_helper(doc)
+
+
+`@LSP_SERVER`.feature(lsp.NOTEBOOK_DOCUMENT_DID_SAVE)
+def notebook_did_save(params: lsp.DidSaveNotebookDocumentParams) -> None:
+ """LSP handler for notebookDocument/didSave request."""
+ nb = LSP_SERVER.workspace.get_notebook_document(
+ notebook_uri=params.notebook_document.uri
+ )
+ if nb is None:
+ return
+ for cell in nb.cells:
+ if cell.kind == lsp.NotebookCellKind.Code:
+ doc = LSP_SERVER.workspace.get_text_document(cell.document)
+ _linting_helper(doc)
+
+
+`@LSP_SERVER`.feature(lsp.NOTEBOOK_DOCUMENT_DID_CLOSE)
+def notebook_did_close(params: lsp.DidCloseNotebookDocumentParams) -> None:
+ """LSP handler for notebookDocument/didClose request."""
+ for cell_doc in params.cell_text_documents:
+ doc = LSP_SERVER.workspace.get_text_document(cell_doc.uri)
+ _clear_diagnostics(doc)
+
+
+`@LSP_SERVER`.feature(lsp.NOTEBOOK_DOCUMENT_DID_CHANGE)
+def notebook_did_change(params: lsp.DidChangeNotebookDocumentParams) -> None:
+ """LSP handler for notebookDocument/didChange request."""
+ if params.change.cells is None:
+ return
+ cell_changes = params.change.cells
+ if cell_changes.text_content:
+ for changed in cell_changes.text_content:
+ doc = LSP_SERVER.workspace.get_text_document(changed.document.uri)
+ _linting_helper(doc)
+ if cell_changes.structure:
+ for removed in (cell_changes.structure.did_close or []):
+ doc = LSP_SERVER.workspace.get_text_document(removed.uri)
+ _clear_diagnostics(doc)6. Remove the "Not Supported" skip from _linting_helper (lines 213β216):
- if str(document.uri).startswith("vscode-notebook-cell"):
- # We don't support running mypy on notebook cells.
- log_warning(f"Skipping notebook cells [Not Supported]: {str(document.uri)}")
- _clear_diagnostics(document)
- return None
-Note: The mypy tool runs against a file path. For notebook cells,
_get_document_pathresolves the cell URI to the parent notebook's.ipynbpath. You may want to verify how mypy behaves when given a.ipynbfile path and adjust the implementation accordingly.
Files skipped
README.mdβ Template-specific documentation; vscode-mypy has its own README.src/test/python_tests/test_notebook.pyβ New test file added by the template. vscode-mypy should add its own notebook integration tests covering mypy-specific behavior.
π€ This issue was auto-generated by the extension-template-sync workflow.
Generated by Extension Template Sync