Stop the dev server being interrupted at startup, and make interpreter selection work from .pyxl files - #13
Merged
Conversation
…tion The "Debug Pyxle app (React browser)" configuration started the dev server by opening a shell terminal and typing `pyxle dev` into it. A shell terminal is writable by any extension, and the Python extension activates the selected environment in every new one via TerminalShellIntegration.executeCommand(), which is documented to send ^C first to interrupt whatever is running. The server was killed seconds after starting and the activation line typed in its place. The extension now owns the process: a Pseudoterminal spawns the dev server directly, so no shell exists to inject into (a foreign sendText is delivered to handleInput, where it is dropped) and shutdown is exact — SIGINT to the process group, SIGKILL backstop, taskkill on Windows. That path also ran whatever `pyxle` came first on PATH while the Python path ran VS Code's selected interpreter — two different installs. Both now run the selected interpreter as `python -m pyxle dev`, through one shared argv helper and the same pre-launch check. The pre-launch check is reworked: - It tests what the interpreter can do (find_spec pyxle.__main__), never the version its metadata reports, so an editable install whose dist-info is stale is no longer refused. The reported version is shown for context only. - A probe that cannot answer (crash, timeout, spawn failure) reports "unknown" and lets the launch proceed rather than asserting pyxle is absent. - Both failure dialogs lead with Select Interpreter — the usual cause is that pyxle lives in another environment — always open the picker when clicked, and re-probe afterwards so a fixed environment continues the launch. New: a status-bar item shows the selected interpreter while a .pyxl file is open, with a Pyxle: Select Python Interpreter command, since the Python extension scopes its own indicator to .py files. Also stop owned dev servers when the extension shuts down (they run in their own process group and would otherwise keep holding their ports), and drop the duplicated "Pyxle: " prefix from command palette titles.
5 tasks
Review of the pty rework surfaced five defects, all in the new process-lifecycle code: The Windows teardown could throw and strand the tree. `cp.spawn` reports a missing or blocked `taskkill` asynchronously as an "error" event, which the surrounding try/catch cannot see and which throws when unhandled. It now has a listener that falls back to killing the leader directly, instead of waiting out the SIGKILL timer that only ever reaches that leader and leaves Vite holding its port. Exit settled on both "exit" and "close". "exit" fires before the piped stdio drains, so a server that died on startup printed "The dev server stopped" above its own traceback, and a deliberate stop closed the panel on top of output still in flight. It settles on "close" alone now, which also still covers the case the pair was guarding: a command that does not exist emits "error" then "close" and never "exit" — checked against Node directly. `onDidExit` was declared, fired, and subscribed by nobody. The React launch now uses it to cancel the readiness wait when a server it started exits early, so a broken interpreter that the probe deliberately lets through reports the real error instead of holding the in-flight guard for the full two-minute timeout, silently swallowing every further F5. The interpreter gate can block on a dialog and a quick pick for an unbounded time, and discovery was not re-read afterwards — long enough for a server to have appeared, and a second `pyxle dev` was spawned onto the taken port. It re-checks and re-adopts instead. The changelog claimed shutdown always stops the server; the process group that makes one signal reach the whole tree also removes the SIGHUP a pty close used to deliver, so a force-quit can still leave it running. Says so now.
Member
Author
|
Reviewed and merging. The diagnosis is right and the pty approach is the correct fix rather than a timing workaround: VS Code routes Five lifecycle gaps in the new code are fixed in a follow-up commit on this branch:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The issue
Two problems, both reported from a real session and both rooted in how the extension talks to the Python environment.
1. The dev server was killed seconds after it started. Using "Debug Pyxle app (React browser)", the server came up and was then immediately interrupted:
The extension started the server by opening a shell terminal and typing
pyxle devinto it. A shell terminal is writable by anything, and the Python extension activates the selected environment in every newly created one. Modern activation goes throughTerminalShellIntegration.executeCommand(), whose documented behaviour is to send^Cfirst to interrupt any running command — so VS Code interrupted the just-started server and typed the activation line (pyenv shell …,source .venv/bin/activate) in its place. Nothing the extension could time around: activation is asynchronous and lands whenever the interpreter resolves.2. "Debugging needs pyxle-framework 0.8.0 or newer" with 0.8.0 installed. Two causes:
pyxlewas first on the shellPATH— routinely a different environment. The two configurations could run two different installs of two different versions..pyxleditor (the Python extension scopes its own to.pyfiles), so the interpreter driving the launch was invisible and unchangeable without opening an unrelated Python file.The fix
The extension owns the dev-server process. A
Pseudoterminalspawns it directly instead of typing into a shell. No shell meansterminal.shellIntegrationis never populated, so the^C-sending API cannot be called on it, and a foreignTerminal.sendText()is delivered to ourhandleInput, where it is dropped — the injection is inert by construction rather than merely unlikely. The panel still shows the server's output, Ctrl-C still stops it, and shutdown is now exact: SIGINT to the process group (so Vite and the SSR workers go too), a SIGKILL backstop,taskkill /T /Fon Windows.Both configurations run the same environment. The React-browser flow now launches
<selected interpreter> -m pyxle devthrough the same argv helper and the same pre-launch check as the Python flow.The pre-launch check is capability-based and no longer a dead end.
find_spec('pyxle.__main__')), never what its package metadata claims — so an editable install whose dist-info still reads0.7.5while the code is current launches normally. The reported version is shown for context only, labelled as package metadata.unknownand lets the launch proceed, so the debugger surfaces the real error instead of the check asserting "pyxle is not installed".New: the interpreter is visible and switchable from
.pyxlfiles — a status-bar item showing the selected environment (click to change), plus a Pyxle: Select Python Interpreter command.Also in this change: owned dev servers are stopped when VS Code shuts down (they run in their own process group and would otherwise keep holding their ports), and command palette entries no longer read "Pyxle: Pyxle: …".
Verification
tsc --noEmitclean;npm testgreen (23 tests, 12 new covering the probe, version parsing and interpreter labelling).0.7.5with current code → launches (previously refused), a0.8.0install → ok, a nonexistent interpreter →unknownrather than a false "not installed".sendText("pyxle dev").The changelog entry is under Unreleased — this ships with the next extension release.