Code Monkey home page Code Monkey logo

debugger's Introduction

Installation | Documentation | Contributing | License | Team | Getting help |

PyPI version Downloads Build Status Build Status Documentation Status Crowdin GitHub Discourse Gitter Gitpod

Binder

An extensible environment for interactive and reproducible computing, based on the Jupyter Notebook and Architecture.

JupyterLab is the next-generation user interface for Project Jupyter offering all the familiar building blocks of the classic Jupyter Notebook (notebook, terminal, text editor, file browser, rich outputs, etc.) in a flexible and powerful user interface.

JupyterLab can be extended using npm packages that use our public APIs. The prebuilt extensions can be distributed via PyPI, conda, and other package managers. The source extensions can be installed directly from npm (search for jupyterlab-extension) but require an additional build step. You can also find JupyterLab extensions exploring GitHub topic jupyterlab-extension. To learn more about extensions, see the user documentation.

Read the current JupyterLab documentation on ReadTheDocs.

Important

JupyterLab 3 will reach its end of maintenance date on May 15, 2024, anywhere on Earth. To help us make this transition, fixes for critical issues will still be backported until December 31, 2024. If you are still running JupyterLab 3, we strongly encourage you to upgrade to JupyterLab 4 as soon as possible. For more information, see JupyterLab 3 end of maintenance on the Jupyter Blog.


Getting started

Installation

If you use conda, mamba, or pip, you can install JupyterLab with one of the following commands.

  • If you use conda:
    conda install -c conda-forge jupyterlab
  • If you use mamba:
    mamba install -c conda-forge jupyterlab
  • If you use pip:
    pip install jupyterlab
    If installing using pip install --user, you must add the user-level bin directory to your PATH environment variable in order to launch jupyter lab. If you are using a Unix derivative (e.g., FreeBSD, GNU/Linux, macOS), you can do this by running export PATH="$HOME/.local/bin:$PATH". If you are using a macOS version that comes with Python 2, run pip3 instead of pip.

For more detailed instructions, consult the installation guide. Project installation instructions from the git sources are available in the contributor documentation.

Installing with Previous Versions of Jupyter Notebook

When using a version of Jupyter Notebook earlier than 5.3, the following command must be run after installing JupyterLab to enable the JupyterLab server extension:

jupyter serverextension enable --py jupyterlab --sys-prefix

Running

Start up JupyterLab using:

jupyter lab

JupyterLab will open automatically in the browser. See the documentation for additional details.

If you encounter an error like "Command 'jupyter' not found", please make sure PATH environment variable is set correctly. Alternatively, you can start up JupyterLab using ~/.local/bin/jupyter lab without changing the PATH environment variable.

Prerequisites and Supported Browsers

The latest versions of the following browsers are currently known to work:

  • Firefox
  • Chrome
  • Safari

See our documentation for additional details.


Getting help

We encourage you to ask questions on the Discourse forum. A question answered there can become a useful resource for others.

Bug report

To report a bug please read the guidelines and then open a Github issue. To keep resolved issues self-contained, the lock bot will lock closed issues as resolved after a period of inactivity. If a related discussion is still needed after an issue is locked, please open a new issue and reference the old issue.

Feature request

We also welcome suggestions for new features as they help make the project more useful for everyone. To request a feature please use the feature request template.


Development

Extending JupyterLab

To start developing an extension for JupyterLab, see the developer documentation and the API docs.

Contributing

To contribute code or documentation to JupyterLab itself, please read the contributor documentation.

JupyterLab follows the Jupyter Community Guides.

License

JupyterLab uses a shared copyright model that enables all contributors to maintain the copyright on their contributions. All code is licensed under the terms of the revised BSD license.

Team

JupyterLab is part of Project Jupyter and is developed by an open community. The maintenance team is assisted by a much larger group of contributors to JupyterLab and Project Jupyter as a whole.

JupyterLab's current maintainers are listed in alphabetical order, with affiliation, and main areas of contribution:

  • Mehmet Bektas, Netflix (general development, extensions).
  • Alex Bozarth, IBM (general development, extensions).
  • Eric Charles, Datalayer, (general development, extensions).
  • Frédéric Collonval, WebScIT (general development, extensions).
  • Martha Cryan, Mito (general development, extensions).
  • Afshin Darian, QuantStack (co-creator, application/high-level architecture, prolific contributions throughout the code base).
  • Vidar T. Fauske, JPMorgan Chase (general development, extensions).
  • Brian Granger, AWS (co-creator, strategy, vision, management, UI/UX design, architecture).
  • Jason Grout, Databricks (co-creator, vision, general development).
  • Michał Krassowski, Quansight (general development, extensions).
  • Max Klein, JPMorgan Chase (UI Package, build system, general development, extensions).
  • Gonzalo Peña-Castellanos, QuanSight (general development, i18n, extensions).
  • Fernando Perez, UC Berkeley (co-creator, vision).
  • Isabela Presedo-Floyd, QuanSight Labs (design/UX).
  • Steven Silvester, MongoDB (co-creator, release management, packaging, prolific contributions throughout the code base).
  • Jeremy Tuloup, QuantStack (general development, extensions).

Maintainer emeritus:

  • Chris Colbert, Project Jupyter (co-creator, application/low-level architecture, technical leadership, vision, PhosphorJS)
  • Jessica Forde, Project Jupyter (demo, documentation)
  • Tim George, Cal Poly (UI/UX design, strategy, management, user needs analysis).
  • Cameron Oelsen, Cal Poly (UI/UX design).
  • Ian Rose, Quansight/City of LA (general core development, extensions).
  • Andrew Schlaepfer, Bloomberg (general development, extensions).
  • Saul Shanabrook, Quansight (general development, extensions)

This list is provided to give the reader context on who we are and how our team functions. To be listed, please submit a pull request with your information.


Weekly Dev Meeting

We have videoconference meetings every week where we discuss what we have been working on and get feedback from one another.

Anyone is welcome to attend, if they would like to discuss a topic or just listen in.

Notes are archived on GitHub Jupyter Frontends team compass.

debugger's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

debugger's Issues

Add `continue` command

There should be a new command for the continue debug action, so it can be mapped to a keyboard shortcut (F5 in regular IDEs, F8 in the dev tools).

Add CI

Since #9 is going to add some tests, we can start thinking about what we want to use to run them automatically.

The 2 main options at the moment seem to be:

  • Azure pipelines: already used for the main JupyterLab repo
  • GitHub actions: now available in beta, looking promising (and also arguably easier to configure?)

Normalize naming and namespaces

The FooWidget classes should just be called Foo and they should have a namespace Foo where their model is defined as Foo.IModel.

dumpCell request

Although most of the Debug Adapter Protocol can be directly used, there is a usecase specific to Jupyterlab that requires an additional message type.

When setting breakpoints, the debugger expects a source path which must refer to a file on disk. Since the cells of a notebook are executed by the interpreter, it not possible to directly set breakpoints in them. The solution is to first require the backend to dump the cell in a file, and then use this file as the source path argument of the setBreakpoints request. This can be achieved with the following additional messages:

Message type: debug_request

content = {
  'type': 'request',
  # Sequence number (also known as message ID).
  # For protocol messages of type 'request' this ID can be used to cancel the request.
  'seq': 'number',
  'command': 'dumpCell',
  'arguments': {
    # Source code of the cell, one or more lines
    'code': str
  }
}

When receiving this request, the backend "computes" a filename, write the content of the cell in it, and returns the name of the file:

Message_type debug_reply

content = {
  'type': 'response',
  # Sequence number of the corresponding request.
  'request_seq': 'number',
  # Outcome of the request
  'success': 'bool',
  'command': 'dumpCell',
  'body': {
    # Name of the file where the cell was dumped
    # Can be used as the 'sourcePath' argument in a 'setBreakpoints' request
    'sourcePath': 'str'
  }
}

Restore open sidebar

At the moment if we open the sidebar and then reload the page, the sidebar will be minimized:

restore-sidebar-state

It would be great if the sidebar could keep its "open" state on reload.

Is 'conda' env needed when installing this extension?

I am so glad to see jupyterlab will be able to debug code soon, but the readme tells that xeus-python 0.5+ is needed. Must this Prerequisites be satisfied after stable version realesed? I use pip rather than conda env.

When will this feature be released? I can't wait to debug my code.

Thx!

Handle kernel status

For now we don't check whether a kernel is ready before sending debug messages.

We should do that check before starting a new session and restoring an existing one. And also handle status changes.

Cell execution signal

I was looking into the NotebookActions.executed signal to be able to know when a cell is executed.

However it seems to be triggered after a cell has been executed (after the execute_request message is sent).

Ideally what we would want is:

  1. listen to a signal that is triggered before the cell is executed
  2. wait for the user to execute a cell (Ctrl-Enter)
  3. a beforeExecute signal is emitted, send all the messages to initialize the debug session
  4. only after would the cell be run (and the execute_request be sent)

Send breakpoints to the debugger

To be implemented after #42.

Breakpoints set in the UI should be sent over to the debugger all at once (the debugger must be started beforehand).

Handle `exited` event

The variables should be cleared from the sidebar when the exited is received.

Other visual elements should also update accordingly.

Add example notebook

We can add an example notebook to the repo that uses xeus-python as the kernel.

This example notebook wll then be opened when starting Binder.

Always show line numbers and gutters when the sidebar is open

At the moment the gutters and line numbers are being toggled when switching between cells:

codemirror-gutters-toggled

It would be better to always keep them on when the debugger sidebar is visible and being used.

We also want to keep the breakpoints set for other cells.

Access to the debugger widget across plugins

At the moment the debugger widget is accessed from the notebooks and consoles plugins via the tracker exposed from the proxy.

A side effect of accessing the widget this way is code that doesn't look natural. Here debug.session is tested twice:

debugger/src/index.ts

Lines 185 to 193 in b15c240

if (!debug.session) {
debug.session = new DebugSession({ client: widget.session });
} else {
debug.session.client = widget.session;
}
if (debug.session) {
await debug.session.restoreState();
app.commands.notifyCommandChanged();
}

We should probably keep the proxy as a way to access the (single) instance of the debugger widget (similar to the inspector and completer extensions), but it looks we could change some of the values it proxies?

Consider using react-inspector for the variable explorer

The react-inspector library could be a nice tool to consider to show a tree of variables, that would handle the different scopes ("Locals", "Globals", "builtins") out of the box.

It's being used in the jupyterlab-kernelspy and the jupyterlab-data-explorer extensions.

An example of what it would look like:

image

The tree (headers, labels) can be customized so we could show the most important information at the higher levels (variable name and value). And end up with something similar to VS Code:

image

Implement debugger expanded layout

The expanded mode of the debugger should have the debugger sidebar inside a SplitPanel that has a TabPanel as its other pane (to hold read-only text editors for stepping into code).

Architecture of the debugger

Nothing blocking at all, these are just some questions and thoughts about how internal components should interact.

  • Should we hide the DebugSession behind the DebugService? In this case, the DebugService would provide methods to set the session, start and stop it.
  • Should the DebugService only provide methods to send debug request and react to debug events? In this case, it would be responsible for updating the "data" of different model classes (Breakpoints, Variables).
  • Should the debugger model hold other model classes (breakpoints, variables)?

cc @afshin @jtpio @KsavinN

Request variables state

Let's replace the fake variables by real ones read from the kernel.
This means implementing the scopes and variables requests.

There is an example of such requests in the tests:

const getVariables = async () => {
const stackFramesReply = await debugSession.sendRequest('stackTrace', {
threadId
});
const frameId = stackFramesReply.body.stackFrames[0].id;
const scopesReply = await debugSession.sendRequest('scopes', {
frameId
});
const scopes = scopesReply.body.scopes;
const variablesReference = scopes[0].variablesReference;
const variablesReply = await debugSession.sendRequest('variables', {
variablesReference
});
return variablesReply.body.variables;
};

Handle stop

#84 handles when the execution of a cell has continued.

But for now if we click on stop the variables and callstack are still shown:

stop-debugger-cleanup

Restore the debugger session's state

If a user switches back to a notebook whose code execution was interrupted on a breakpoint, or if she reloads the page while the code execution is interrupted on a breakpoint, what should the behavior be? Should we be able to restore the full state, that is highlight the line where the code stopped, and restore the breakpoints and callstack? Or should we simply restart the debugger (and resume the code execution)?

I think the first behavior (restoring everything) would be a butter user experience, however this requires additional changes in the backend.

Connect to the debugger

Now that there is a minimal UI for the debugger, we could start using the DebugSession to send debug requests to the kernel and have a "loop" in place:

  • start the debugger
  • initialize (set config and breakpoints)
  • request scopes and variables
  • stop the debugger

Add tests for the debugger UI

Once the interfaces and the overall structure become more stable, it will be useful to start adding tests for the UI elements as well.

This will help us test more complex scenarios and edge cases.

Map buttons to debug actions

Now that we have the start and stop commands, they can be triggered when clicking on the start / continue and stop buttons.

Variables search

How about having the variable search filter return results on substring matches?

So searching for 1 would return test 1:

variable-search

Automated sorting of imports

One thing that the current tslint / prettier configuration is not covering is the automatic sorting of imports.

It doesn't seem to be enforced in the jupyterlab repo either.

Maybe we can consider having that triggered on git commit too.

Cleanup reference to `IDataConnector`?

We've been carrying a reference to an IDataConnector, but without really using it:

readonly connector: IDataConnector<ReadonlyJSONValue> | null;

The idea was to use it and implement the fetch method to send debug messages to the kernel, similar to the inspector extension.

However since the DebugSession handles the communication to the kernel we probably don't need the connector anymore.

Display classes in variables

For now classes (and potentially other nested data types) don't have their attributes displayed:

image

We'll probably need a few extra calls to variables and send the right variablesReference.

As a reference in VS Code:

image

Debug Protocol Overview

Adding a quick overview of the debug protocol, so it's easier to visualize the types of messages sent between the JupyterLab extension and the kernel.

It only shows a subset of the messages for now, but can be extended to also include the calls to continue, stepIn and disconnect.

This also show new messages that are not part of the Debug Adapter Protocol (DAP), such as dumpCell.

Diagram

debug-protocol

TODO

  • Add the call to debug_info_request
  • Add the flow to show the files being debugged (stepIn / breakpoints)

References

Source

Generated using: https://bramp.github.io/js-sequence-diagrams/

Diagram source
user->JupyterLab: open notebook

JupyterLab->kernel: kernel_info_request

kernel->JupyterLab: kernel_info_reply

JupyterLab->JupyterLab: check 'debugger' key

JupyterLab->user: show toggle button\nif 'debugger'

user->JupyterLab: enable debugging

JupyterLab->kernel: debugInfo request

kernel->JupyterLab: debugInfo response

user->JupyterLab: start debugger

JupyterLab->kernel: initialize request

kernel->JupyterLab: initialize response

JupyterLab->kernel: attach request

kernel->JupyterLab: attach response

Note right of kernel: debugger started

user->JupyterLab: add breakpoints\n(click on gutters)

JupyterLab->kernel: dumpCell request

kernel->JupyterLab: dumpCell response

JupyterLab->kernel: setBreakpoints request

kernel->JupyterLab: breakpoints response

JupyterLab->kernel: configurationDone request

kernel->JupyterLab: configurationDone response

user->JupyterLab: execute cell\n(Ctrl-Enter)

JupyterLab->kernel: requestExecute

kernel->kernel: execute code

kernel->kernel: hit breakpoint

kernel-->JupyterLab: stopped event

JupyterLab->kernel: stackTrace request

kernel->JupyterLab: stackTrace response

JupyterLab->user: show current line

JupyterLab->kernel: scopes request

kernel->JupyterLab: scopes response

JupyterLab->kernel: variables request

kernel->JupyterLab: variables response

JupyterLab->user: show variables

user->JupyterLab: step in deleted cell code

JupyterLab->kernel: stepIn request

kernel-->JupyterLab: stopped event

JupyterLab->JupyterLab: search for code matching\nsource path

JupyterLab->kernel: source request

kernel->JupyterLab: source response

JupyterLab->user: show source for current path

Note right of kernel: debug session

user->JupyterLab: disable debugging

JupyterLab->kernel: disconnect request

Note right of kernel: debugger stopped

kernel->JupyterLab: disconnect response

JupyterLab->JupyterLab: clear debugging UI for\nthe notebook

Remove the `launch` command

Setting breakpoints and sending the configurationDone message to the kernel should happen without manually executing the launch command.

Develop Table in Variables

  • - Table in Variables need second level when type of variable is class.

  • - Body of table need have resize with set scrollbar (overflow:auto)

Update the breakpoint locations

As mentioned in #99 and #99 (comment), the breakpoints actually set by the debugger might not correspond to the ones set in the UI.

For example this is the case when setting a breakpoint on an empty line.

We should read the debug_reply message received after setBreakpoints to retrieve the correct list of breakpoints, and update the breakpoint marks in the editor UI (and the line in the sidebar).

As an example in VS code when the debugger is running:

vs-code-breakpoint-location

Debugger state restoration

The frontend should be able to request the state of the debugger so it can restore its state after a reload for instance. This implies adding a new message in the debug protocol.

Besides, a cell with breakpoints needs to be dumped to a real file, so that the debugger can break when the execution hits a breakpoint. The current solution is to send the content of the cell to the backend in the dumpCell request, and let the backend compute the hash of this content, and then dump the content to a file whose name contents this hash. Notice that the backend also needs to compute this file name (and therefore, the hash of the content) in the implementation of execute_request to "map" the code of the cell to the file. It is required that the names computed in execute_request and dumpCell match, otherwise the debugger cannot break.

With the current implementation, it is impossible to restore the breakpoints in the frontend after a reload. The frontend needs to ask the kernel which breakpoints were set, and how files map to cells. After in person conversations with @jtpio and @SylvainCorlay, the following solutions are considered:

  • the hash is computed in the backend only. In that case, upon reload, the front end needs to send the content of each cell to get the associated filename, and then can ask the kernel for the breakpoints.
  • the hash is computed in the frontend only. In that case, it must be sent to the backend in the dumpCell request, but also as an additional parameter of the execute_request.
  • the frontend and the backend can compute the hash when they need it. In that case, they must agree on a hash method (this can be done in the debug_info_request message, or harcoded) and the full state of the debugger can be retrieved with a single request.

I think solution 2 should be avoided since it requires modifying the current protocol with additional parameter that makes sense for debugging only. Solution 1 is simpler than solutoin 3 since the hash method is an implementation detail of the backend, however many messages are sent upon reload while solution 3 requires only one request.

Also, since many notebooks can be opened at the same time, it could be useful to "cache" the state and the breakpoints in the DebugSession objects to avoid requesting the backend each time we switch from one notebook to the other (or to a console).

EDIT: reformulated and exposed the three possible solutions

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.