Skip to content

Commit

Permalink
Add experimental VS Code (code) runtime to juv run
Browse files Browse the repository at this point in the history
This PR adds a `code` runtime option to `juv run`, allowing VS Code to
be launched in a way similar to other Jupyter runtimes. The approach
uses the behavior of the `code` CLI, which inherits the environment
it was run in.

A script is created using the inline metadata so that running `code
<notebook.ipynb>` ensures a virtual environment is available in the VS
Code session with the necessary dependencies.

Ideally, we'd have a VS Code extension to dynamically create and
register virtual environments for better discoverability. This
implementation goes the other way by enabling basic support via the CLI.
However, the user must manually select the virtual environment from VS
Code's dropdown, where it appears with an obscure, temporary name
(derived from the hashed environment created by `uv`).
  • Loading branch information
manzt committed Dec 18, 2024
1 parent 29e9892 commit 133dbfd
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/juv/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def run( # noqa: PLR0913
if mode == "dry":
print(f"uv {' '.join(args)}") # noqa: T201

elif mode == "managed":
elif mode == "managed" and runtime.name != "code":
from ._run_managed import run as run_managed

run_managed(script, args, str(path))
Expand Down
23 changes: 19 additions & 4 deletions src/juv/_run_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
if typing.TYPE_CHECKING:
import pathlib

RuntimeName = typing.Literal["notebook", "lab", "nbclassic"]
RuntimeName = typing.Literal["notebook", "lab", "nbclassic", "code"]


def is_notebook_kind(kind: str) -> typing.TypeGuard[RuntimeName]:
return kind in {"notebook", "lab", "nbclassic"}
return kind in {"notebook", "lab", "nbclassic", "code"}


@dataclass
Expand Down Expand Up @@ -45,12 +45,19 @@ def script_template(self) -> str:
return NOTEBOOK
if self.name == "nbclassic":
return NBCLASSIC
if self.name == "code":
return VSCODE
msg = f"Invalid self: {self.name}"
raise ValueError(msg)

def as_with_arg(self) -> str:
# lab is actually jupyterlab
with_ = "jupyterlab" if self.name == "lab" else self.name
with_ = {
"lab": "jupyterlab",
"notebook": "notebook",
"nbclassic": "nbclassic",
# vscode needs ipykernel to be in the environment
"code": "ipykernel",
}[self.name]

# append version if present
if self.version:
Expand Down Expand Up @@ -200,6 +207,14 @@ def handle_termination(signum, frame):
main()
"""

VSCODE = """
{meta}
import subprocess
import os
subprocess.run(["code", r"{notebook}"], check=True, env=os.environ)
"""


def prepare_run_script_and_uv_run_args( # noqa: PLR0913
*,
Expand Down

0 comments on commit 133dbfd

Please sign in to comment.