Skip to content

Add notebook cell support for isort#565

Merged
edvilme merged 13 commits intomicrosoft:mainfrom
edvilme:notebook-cells
Mar 4, 2026
Merged

Add notebook cell support for isort#565
edvilme merged 13 commits intomicrosoft:mainfrom
edvilme:notebook-cells

Conversation

@edvilme
Copy link
Contributor

@edvilme edvilme commented Mar 3, 2026

Summary

With the upgrade to pygls 2, the extension can now leverage LSP 3.17's notebook document sync protocol. This PR adds Jupyter notebook cell support to the isort extension, enabling import sorting diagnostics and code actions for Python cells within notebooks in both server and server-less modes. Closes #303.

Also removes the is_python guard that used ast.parse to validate Python code before running isort. This check rejected valid-but-incomplete Python code, preventing organize imports from working on files being actively edited. Closes #243.

Changes

LSP Server (bundled/tool/lsp_server.py)

  • Notebook document sync: Declared NotebookDocumentSyncOptions for jupyter-notebook and interactive notebook types with Python cell filtering
  • Notebook handlers: Added notebookDocument/didOpen, didChange, didSave, and didClose handlers that run diagnostics on notebook cells
  • Cell filtering: Non-code cells (e.g., Markdown) are filtered out using NotebookCellKind.Code checks
  • Cell structure changes: The didChange handler processes text content edits, cell additions (structure.did_open), and cell removals (structure.did_close)
  • Removed is_python guard: Removed is_python, strip_magic_commands, and MAGIC_COMMAND_REGEX — isort handles magic commands and syntax errors gracefully on its own, and the ast.parse check was incorrectly rejecting incomplete code ("no organize imports action available" error on uncompleted code #243)
  • Docstring fix: Corrected _get_document_path example to show .ipynb output instead of .py

Server-less mode (src/common/runner.ts, src/common/sortImports.ts)

  • Notebook URI resolution: Added getDocumentPath helper to runner.ts that resolves vscode-notebook-cell:// URIs to filesystem paths, mirroring _get_document_path on the Python side
  • Full notebook support: Removed the isNotebookCell guard — server-less mode now fully supports notebook cells
  • URI handling: Changed code action data from uri.fsPath to uri.toString() so notebook cell URIs round-trip correctly through code action resolution

Tests

  • Session client: Added notebook notification methods (notify_notebook_did_open/did_change/did_save/did_close) to the LSP test client
  • New test file (test_notebook.py): 5 tests covering all notebook handlers:
    • test_notebook_did_open — diagnostics published on notebook open
    • test_notebook_did_change_text_content — diagnostics update on cell edit
    • test_notebook_did_change_structure_add_cell — new cells are linted
    • test_notebook_did_save — all cells re-linted on save
    • test_notebook_did_close — diagnostics cleared on close
  • Incomplete code tests: Added tests for both regular documents and notebook cells with syntactically incomplete Python code to verify isort works without the is_python guard
  • Mock updates: Added notebook-related types to the lsprotocol mock in test_get_cwd.py to fix CI import failures

edvilme added 5 commits March 3, 2026 14:11
- Add notebook document sync options for jupyter-notebook and interactive
- Add LSP handlers for notebook did_open, did_change, did_save, did_close
- Remove notebook cell guard in server-less code action provider
- Use uri.toString() instead of fsPath for code action data
- Add missing PEP 8 blank lines between top-level functions in lsp_server.py
- Restore notebook cell guard in server-less mode code action provider
- Revert unrelated package-lock.json peer changes
- Fix prettier formatting (catch {}, empty arrow functions)
Lint newly added cells and clear diagnostics for removed cells,
not just cells with text content changes.
The function resolves notebook cell URIs to the notebook's .ipynb
path (stripping the cell fragment), not to a .py path.
- Add notebook notification methods to LspSession test client
- Add tests for notebookDocument/didOpen, didChange, didSave, didClose
- Test cell structure changes (adding new cells with unsorted imports)
- Test diagnostics are cleared on notebook close
@edvilme edvilme marked this pull request as draft March 3, 2026 22:37
edvilme added 3 commits March 3, 2026 14:46
The mock lsprotocol.types module was missing notebook-related
constants and types needed by the module-level NOTEBOOK_SYNC_OPTIONS
in lsp_server.py, causing import failures in CI.
@edvilme edvilme added the feature-request Request for new features or functionality label Mar 3, 2026
@edvilme
Copy link
Contributor Author

edvilme commented Mar 3, 2026

Fixes #303

@edvilme edvilme marked this pull request as ready for review March 3, 2026 22:54
edvilme added 4 commits March 3, 2026 15:20
Use cell.kind check to skip markdown cells, matching the pattern
used in notebook_did_save.
Consistent with the other .fsPath to .toString() changes in this
file — fsPath loses scheme information for non-file URIs.
Add getDocumentPath helper to runner.ts that resolves notebook cell
URIs to filesystem paths (mirroring _get_document_path in Python).
Remove the isNotebookCell guard in sortImports.ts since the runner
can now handle notebook URIs.
The notebook document URI should use the file: scheme (it represents
the .ipynb file on disk). Only individual cell URIs use the
vscode-notebook-cell: scheme.
@edvilme edvilme requested a review from rchiodo March 3, 2026 23:40
rchiodo
rchiodo previously approved these changes Mar 3, 2026
Copy link
Contributor

@rchiodo rchiodo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

Remove is_python, strip_magic_commands, and MAGIC_COMMAND_REGEX from
lsp_server.py. The is_python check used ast.parse which rejected
valid-but-incomplete Python code, preventing organize imports from
working on files being actively edited.

Closes microsoft#243

Also removes now-unused ast and re imports.

Adds tests for both regular documents and notebook cells with
incomplete Python code (missing function body) to verify isort
correctly sorts imports without the is_python guard.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@edvilme edvilme requested a review from rchiodo March 4, 2026 00:05
@edvilme edvilme enabled auto-merge (squash) March 4, 2026 00:06
@edvilme edvilme merged commit 6a673e8 into microsoft:main Mar 4, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature-request Request for new features or functionality

Projects

None yet

2 participants