-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented Restart and debug #10462
Conversation
Thanks for making a pull request to JupyterLab! To try out this branch on binder, follow this link: |
It almost works, breakpoints are correctly set in the back end, and the code stops on the breakpoint. Last issue is breakpoints do not appear on the UI, and the debugger button is not toggled correctly. |
Thanks Johan! Mind posting a quick screencast to get an idea of the flow and UX? |
const handler = new Debugger.Handler({ | ||
type: 'notebook', | ||
shell: app.shell, | ||
service | ||
}); | ||
|
||
app.commands.addCommand('debugger:restart-debug', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will improve that so that the command can be easily added to the toolbar and context menus.
if (restarted) { | ||
await service.restoreDebuggerState(state); | ||
await handler._update(notebookTracker.currentWidget!, | ||
notebookTracker.currentWidget!.sessionContext.session); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my main concern, I had to pass the _update
method to public and call it after restoring the debugger state, otherwise the toggle button is switched off and the breakpoints are not restored in the UI. THey are correclty sent to the kernel though, since the code breaks as expected.
We don't want to call the publid method update
since all the signal handlers for different channels and other stuffs restored in this method are already there. So I wonder if we should add a special entry for the restart and debug
feature to the handler, or simply pass this method in public.
packages/debugger/src/handler.ts
Outdated
@@ -212,7 +212,7 @@ export class DebuggerHandler { | |||
* @param widget The widget to update. | |||
* @param connection The session connection. | |||
*/ | |||
private async _update( | |||
public async _update( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment on index.ts changes above.
Would it be possible to disable the built-in "restart and ..." commands and overwrite those with the debugger-aware wrappers (instead of adding another "restart and ..." command)? Also cross-referencing #10090. Edit: maybe disabling commands is not something that can be easily done, so I should have rather said "disable the default menu entries". Of course, this might be a bad idea. |
Or maybe the |
@krassowska I agree that having an additional "Restart and ...." command is not ideal but it is still better than having the notebook package depending on the debugger package. @fcollonval has an idea to override the behavior of "Restart and run all" when the debugger is available, but he needs to prototype it. Another solution would be to add this command as a button in the toolbar and avoid adding it in the menu. |
I thought that having it as an optional dependency is fine; it could be restricted to Ok, yet another idea: could we consider having a callback in the notebook commands saying "kernel will restart" (which will await for all promises returned by callbacks) so we can save the breakpoints, and then after kernel restarted another callback saying "kernel is ready (do you need to do something before running cells?)" (upon which the breakpoints would be restored)? |
I think it's more or loess what @fcollonval has in mind. I let him comment for giving the detail. |
I tested the ability to override the semantic menu by adding those lines in the activate function of // As the notebook tracker is required for this, the semantic menu should exists.
const notebookCmds = Array.from(mainMenu.kernelMenu.kernelUsers).find(
value => value.tracker === notebookTracker
);
if (notebookCmds) {
// const defaultCommands = { ...notebookCmds };
notebookCmds.restartKernel = async widget => {
const state = service.getDebuggerState();
console.log(state.cells);
const panel = widget as NotebookPanel;
const { context, content } = panel;
await service.stop();
const restarted = await sessionContextDialogs!.restart(
context.sessionContext
);
if (restarted) {
await service.restoreDebuggerState(state);
await handler._update(panel, panel.sessionContext.session);
await NotebookActions.runAll(content, context.sessionContext);
}
return restarted;
};
} This works. But the major problem is the multiplication of commands that do a restart (and something else). So that won't allow to get a consistent behavior. FYI - restart commands are in 3 places:
A refactoring of those code to use consistently a restart command then do something else would be good. Then there is still the trouble of providing a mechanism to carry pre-/post-actions on some commands (in particular the restart command) to achieve a better API to avoid something like the hack above. The discussion should probably be broaden to address for example the need to have a different action on the notebook play and stop toolbar buttons when the user is actually debugging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the menu entry in the settings to be consistent with the new mechanism allowing customization and I rebased the PR.
I only have one comment on missing documentation for new public API. Otherwise, I would suggest merging this first version. And improve it in a second time when hooks on the kernel machinery will be available.
The pattern we used for the "copy shareable link" command in the file browser's context menu was to create a small targeted plugin that adds just that one command (this pattern could be used for a logical grouping of commands) and to have extension authors replace that extension with their own if they need: https://github.com/jupyterlab/jupyterlab/blob/master/packages/filebrowser-extension/src/index.ts#L446-L495 The downside of this approach is that it requires disabling an extension explicitly. But we could instead have that extension expose the disposable object that |
Another pattern that came out of conversation with @SylvainCorlay is to have a meta command that makes a decision about whether to use the default command or a debugger version of the command, potentially by always running the debugger version of the command and expecting some return value e.g., |
This pull request has been mentioned on Jupyter Community Forum. There might be relevant details there: https://discourse.jupyter.org/t/detect-kernel-restart-inside-extension/8970/3 |
For this particular case, a downside of disposing the original command is the need to duplicate/know its code as it may still be executed. @afshin what do you think about this proposal? |
Kicking CI |
const breakpoints = this._model.breakpoints.breakpoints; | ||
let cells: string[] = []; | ||
for (const id of breakpoints.keys()) { | ||
const editorList = this._debuggerSources!.find({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A follow-up for this could be to try to remove the non-null assertion, since IDebugger.ISources
might not be available.
@meeseeksdev please backport to 3.2.x |
Owee, I'm MrMeeseeks, Look at me. There seem to be a conflict, please backport manually. Here are approximate instructions:
And apply the correct labels and milestones. Congratulation you did some good work! Hopefully your backport PR will be tested by the continuous integration and merged soon! Remember to remove If these instruction are inaccurate, feel free to suggest an improvement. |
@jtpio @fcollonval There is still an issue when restoring the degger state,
I think it is because we don't stop the debugger before restarting the kernel and the frontend is in an inconsistent state.The issue is that the new breakpoints sourcePath is different because the pid (which is used in the sourcePath) of the new kernel is different from that of the older kernel.
New menu entry: