<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jupyter Blog - David Brochart</title><link href="https://jasongrout.github.io/medium-archive/pelican/" rel="alternate"/><link href="https://jasongrout.github.io/medium-archive/pelican/feeds/author-david-brochart.atom.xml" rel="self"/><id>https://jasongrout.github.io/medium-archive/pelican/</id><updated>2023-10-23T06:09:00+00:00</updated><subtitle>The Project Jupyter blog: news, releases, and community stories, archived from blog.jupyter.org.</subtitle><entry><title>Plug your application into the Jupyter world</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/" rel="alternate"/><published>2023-10-23T06:09:00+00:00</published><updated>2023-10-23T06:09:00+00:00</updated><author><name>David Brochart</name></author><id>tag:jasongrout.github.io,2023-10-23:/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/</id><summary type="html">&lt;p&gt;Kernels are a simple but powerful abstraction in the Jupyter architecture. They encapsulate language interpreters and make them accessible…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/images/001-1_ENzq7i52UtqxESs4UTKBYw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;Kernels are a simple but powerful abstraction in the Jupyter architecture. They encapsulate language interpreters and make them accessible through a standardized interface. This is the key to Jupyter’s remarkable versatility, with over 100 supported languages. Embedding a kernel in your custom application can seamlessly expose it to the Jupyter ecosystem. Not only can you attach JupyterLab to your program for e.g. state inspection, as you would do with a debugger, but you can truly extend your application with all the power of the Jupyter ecosystem.&lt;/p&gt;
&lt;h2 id="applications-gui-and-api"&gt;Applications: GUI and API&lt;/h2&gt;
&lt;p&gt;Several applications such as &lt;a href="https://www.freecad.org/"&gt;FreeCAD&lt;/a&gt;, &lt;a href="https://docs.blender.org/api/current/"&gt;Blender&lt;/a&gt;, or &lt;a href="https://docs.qgis.org/3.28/en/docs/pyqgis_developer_cookbook/index.html"&gt;QGIS&lt;/a&gt; provide a Python API to access their functionalities programmatically, and include an embedded Python console which allows using this API from within the application. Users can both use the graphical user interface and operate on the application in a scripted fashion depending on their needs.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Python consoles in FreeCAD, Blender, and QGIS (from left to right)." src="https://jasongrout.github.io/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/images/002-1_EMYG_XFNokXREwsUa9pbFA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Python consoles in FreeCAD, Blender, and QGIS (from left to right).&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If you think about it, these are the kinds of workflows that Jupyter has always been about, but Jupyter has evolved in the opposite direction. Instead of adding scripting to GUIs, Jupyter added GUIs to scripting. At first, Jupyter was IPython, a console for interactive computing. Then it went to the Web and became IPython Notebook, renamed to Jupyter Notebook. With the browser it became possible to display richer content and create small GUIs, using Jupyter Widgets. Then JupyterLab was created and allowed to create fully-fledged desktop-like applications in the browser, like 3-D CAD modelers.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="JupyterLab showing notebooks using JupyterCAD and ipyleaflet." src="https://jasongrout.github.io/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/images/003-1_m4WwlNYiIvMeZu1eXhrl7Q.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;JupyterLab showing notebooks using JupyterCAD and ipyleaflet.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Jupyter put a lot of attention on building a good experience interacting with the Python REPL, which is not the main focus of domain-specific desktop applications. The Python console embedded in desktop applications is often quite raw. Allowing users to connect from Jupyter can enable a much better experience.&lt;/p&gt;
&lt;p&gt;What if there was a bridge that allowed you to connect both worlds, your application on one side and Jupyter on the other side? What is the common denominator allowing code to interact with an application, while also being shared with Jupyter? In the Jupyter infrastructure, we call it a kernel.&lt;/p&gt;
&lt;h2 id="jupyter-kernels"&gt;Jupyter kernels&lt;/h2&gt;
&lt;p&gt;Kernels provide a standardized way to expose language interpreters to applications, in a language-agnostic fashion. You can think of it as a server that accepts requests such as “execute this piece of code” and that replies with a result. The result is actually a data representation, it can be as simple as “3” for an input of “1+2”, or a complex interactive plot. A kernel usually lives in a separate process on your machine, but it can also run in the same process, or even remotely on another machine. Someone wanting to connect to this kernel will need the connection information such as the IP address and the ports of the different communication “channels”. It is stored in what is called a connection file.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The Jupyter kernel protocol allows clients to interact with different languages." src="https://jasongrout.github.io/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/images/004-1_ywYEVpCKlbL6aBEGERsXSw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The Jupyter kernel protocol allows clients to interact with different languages.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Anyone who has access to this connection file can then execute code in the kernel. This is “shared code”, meaning that every client to this kernel eventually runs code in the same interpreter. If one client sets a variable “a=1”, other clients will see this variable. They are all running the “same program”. If the kernel runs in the same process as the application, then the kernel can interact directly with it. This way of sharing the execution engine serves as a bridge between the application and Jupyter.&lt;/p&gt;
&lt;p&gt;Now it is just a matter of exposing the connection file so that e.g. JupyterLab can see it. The application launching the kernel can save the connection file to a specific directory, and give the path to JupyterLab. And that’s it, JupyterLab can run a notebook using this kernel, allowing it to interact with the application.&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting started&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://github.com/jupyter-xeus/xeus-qt-python"&gt;xeus-qt-python&lt;/a&gt; repository is a great place to start and see how to embed a Python kernel inside a Qt application. Under the hood, it uses &lt;a href="https://github.com/jupyter-xeus/xeus-qt"&gt;xeus-qt&lt;/a&gt;, an integration of the &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;xeus&lt;/a&gt; kernel architecture in the Qt event loop. The Qt application actually runs JupyterLab in a Qt WebEngine window. Users can run code in a notebook and interact with the application, which in turn can interact with the notebook. Here, we create a Qt button from a notebook. When clicking on the button, a callback prints a message in the notebook. This demonstrates a two-way binding between the Qt application and JupyterLab.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Example of a Qt application embedding JupyterLab." src="https://jasongrout.github.io/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/images/005-1_FTlpril_YV5W6-xYelNrtA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Example of a Qt application embedding JupyterLab.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://github.com/Slicer/SlicerJupyter"&gt;SlicerJupyter&lt;/a&gt; from Kitware was one of the first applications to take advantage of this approach. You can read more in this &lt;a href="/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/"&gt;blog post&lt;/a&gt;. We hope that this technology will unlock a new brand of use-cases and allow applications to reach a new audience through the Jupyter ecosystem. Please reach out to us if you need help!&lt;/p&gt;
&lt;h3 id="about-the-author"&gt;About the author&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2023/plug-your-application-into-the-jupyter-world/images/006-1_gGWqElhixsQA-cGOzWcb7w.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/davidbrochart"&gt;&lt;strong&gt;David Brochart&lt;/strong&gt;&lt;/a&gt; is a technical director at QuantStack. He mostly works on the Jupyter backend stack. He contributed to the development of real-time collaboration in JupyterLab, and created the &lt;a href="https://davidbrochart.github.io/jupyverse/"&gt;Jupyverse&lt;/a&gt; project, a next-generation implementation of the Jupyter server.&lt;/p&gt;
&lt;h3 id="acknowledgments"&gt;Acknowledgments&lt;/h3&gt;
&lt;p&gt;This work was made possible thanks to several contributors. &lt;a href="https://twitter.com/mari_meir"&gt;&lt;strong&gt;Mariana Meireles&lt;/strong&gt;&lt;/a&gt; was the initial author of &lt;a href="https://github.com/jupyter-xeus/xeus-qt"&gt;xeus-qt&lt;/a&gt;. &lt;a href="https://twitter.com/ThorstenBeier"&gt;&lt;strong&gt;Thorsten Beier&lt;/strong&gt;&lt;/a&gt; is a scientific software developer at QuantStack and contributes to the &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;xeus&lt;/a&gt; kernel ecosystem. He is the initial creator of the &lt;a href="https://github.com/jupyter-xeus/xeus-qt-python"&gt;xeus-qt-python&lt;/a&gt; demonstration. &lt;a href="https://twitter.com/JohanMabille"&gt;&lt;strong&gt;Johan Mabille&lt;/strong&gt;&lt;/a&gt; is a technical director at QuantStack and he is the main author of &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;xeus&lt;/a&gt;. &lt;strong&gt;Afshin Darian&lt;/strong&gt; is a technical director at QuantStack and worked on the UI in JupyterLab 4.0 allowing to use an external kernel.&lt;/p&gt;
</content><category term="kernels"/></entry><entry><title>nbterm: Jupyter Notebooks in the terminal</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/nbterm-jupyter-notebooks-in-the-terminal/" rel="alternate"/><published>2021-04-26T16:42:00+00:00</published><updated>2021-04-26T16:42:00+00:00</updated><author><name>David Brochart</name></author><id>tag:jasongrout.github.io,2021-04-26:/medium-archive/pelican/posts/2021/nbterm-jupyter-notebooks-in-the-terminal/</id><summary type="html">&lt;p&gt;Jupyter notebooks are mostly known for their web-based user interface, such as JupyterLab or the Classic Notebook. They offer a great user…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Jupyter notebooks are mostly known for their web-based user interface, such as JupyterLab or the Classic Notebook. They offer a great user experience, allow for rich output rendering, provide interactivity through e.g. widgets, and make possible working with remote kernels.&lt;/p&gt;
&lt;p&gt;If just like me you tend to never leave the terminal in your workflow, you may be missing a tool to interact with Jupyter notebooks without switching to a web browser. While the &lt;a href="https://github.com/jupyter/jupyter_console"&gt;Jupyter Console&lt;/a&gt; already allows you to interact with a Jupyter kernel in the terminal, it is more comparable to a shell than a notebook.&lt;/p&gt;
&lt;p&gt;The notebook differs from the console in that it’s bound to a document, interleaving rich text and executable code. This makes the code representation more structured, while allowing for interactivity. Well, until recently this wasn’t possible in the terminal. But today, we are proud to announce &lt;strong&gt;nbterm&lt;/strong&gt;!&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Side-by-side comparison of the JupyterLab web notebook and nbterm." src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/nbterm-jupyter-notebooks-in-the-terminal/images/001-1_jZFC3kPJqxMSUeCGd7PHxw.jpeg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Side-by-side comparison of the JupyterLab web notebook and nbterm.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="getting-started-with-nbterm"&gt;Getting started with nbterm&lt;/h2&gt;
&lt;p&gt;Launching a notebook is as easy as entering:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;nbterm&lt;span class="w"&gt; &lt;/span&gt;my_notebook.ipynb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also create a new one if you don’t pass a notebook argument. Almost immediately, you will get a full-screen application that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/nbterm-jupyter-notebooks-in-the-terminal/images/002-1_s6BRdEgITBGOR0y1Ec7GSQ.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;nbterm has other command line options:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nbterm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;--help&lt;/span&gt;
&lt;span class="k"&gt;Usage&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nbterm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;OPTIONS&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NOTEBOOK_PATH&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="nl"&gt;Arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NOTEBOOK_PATH&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;notebook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;default: &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="nl"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;--no-kernel                     Don&amp;#39;t launch a kernel.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;--run                           Run the notebook.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;--save-path TEXT                Path to save the notebook.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;--version                       Show the version and exit.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;--help                          Show this message and exit.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For example, it is possible to run all cells of a notebook in batch mode, using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;nbterm&lt;span class="w"&gt; &lt;/span&gt;--run&lt;span class="w"&gt; &lt;/span&gt;my_notebook.ipynb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you didn’t specify a new name with &lt;code&gt;--save-path&lt;/code&gt;, a new notebook named &lt;code&gt;my_notebook_run.ipynb&lt;/code&gt; will be created, with all cell outputs populated. This mode of execution is similar to the &lt;a href="https://github.com/jupyter/nbclient"&gt;nbclient&lt;/a&gt; library, but accessible in the command line.&lt;/p&gt;
&lt;h2 id="embedding-nbterm"&gt;Embedding nbterm&lt;/h2&gt;
&lt;p&gt;It is also possible to use it as a library and embed it in your own application. Besides, all user interactions can be scripted. For instance, you can rearrange the cells and then run all cells like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;nbterm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Notebook&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;nb = Notebook(&amp;quot;my_notebook.ipynb&amp;quot;)
nb.cut_cell(3)
nb.paste_cell(1)
asyncio.run(nb.run_all())
nb.save()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="a-lightweight-jupyter-stack"&gt;A lightweight Jupyter stack&lt;/h2&gt;
&lt;p&gt;While you probably can’t tell the difference, nbterm doesn’t reuse the base Jupyter components such as &lt;a href="https://github.com/jupyter/jupyter_client"&gt;jupyter-client&lt;/a&gt; and &lt;a href="https://github.com/jupyter/nbformat"&gt;nbformat&lt;/a&gt; (respectively implementing the Jupyter kernel protocol and the Jupyter Notebook format). The reason is that nbterm was started as a toy project to see how hard it would be to have a minimalist notebook client.&lt;/p&gt;
&lt;p&gt;As a Jupyter contributor, I am mostly involved in the maintenance and modernization of these packages. I wanted to experiment with a new project without the backward-compatibility constraints. This resulted in a rather lean code base, and its simplicity makes it suitable to serve as a reference for other language implementations.&lt;/p&gt;
&lt;h2 id="the-roadmap"&gt;The roadmap&lt;/h2&gt;
&lt;p&gt;While nbterm is obviously more limited than the Notebook, there are several potential improvement directions. Having rich(er) outputs is one of them. The terminal is pretty much limited to showing characters, but people have done great things with ASCII art. An attempt has been made a while ago with an &lt;a href="https://github.com/domitry/matascii"&gt;ASCII back-end for matplotlib&lt;/a&gt;. And although it’s only on macOS for now, some terminals are capable of showing real pictures, and there exists &lt;a href="https://github.com/daleroberts/itermplot"&gt;a Matplotlib back-end for iTerm2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another nice feature would be to add some interactivity. In the Notebook, this is typically achieved using widgets, but they are inherently web-based, so this is not an option. Maybe we could imagine something similar to &lt;a href="https://github.com/jupyter-widgets/ipywidgets"&gt;ipywidgets&lt;/a&gt; for the terminal, and have simple things like sliders, buttons, menus and such. I am keeping an eye on the awesome &lt;a href="https://github.com/willmcgugan/rich"&gt;Rich library&lt;/a&gt;, with which you can already create dashboards, and GUI applications in the future.&lt;/p&gt;
&lt;h2 id="try-it"&gt;Try it!&lt;/h2&gt;
&lt;p&gt;nbterm really has the look and feel of the Notebook you already know and love, with (almost) the same key bindings, so you won’t be lost. As coders, we love the terminal, and libraries like &lt;a href="https://github.com/prompt-toolkit/python-prompt-toolkit"&gt;prompt-toolkit&lt;/a&gt; and &lt;a href="https://github.com/willmcgugan/rich"&gt;Rich&lt;/a&gt; in Python, or &lt;a href="https://github.com/jupyter-xeus/cpp-terminal/"&gt;cpp-terminal&lt;/a&gt; in C++, make it possible to build beautiful applications. You can install nbterm today using your favorite package manager:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nbterm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mamba&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nbterm&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;conda-forge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Be sure to update frequently, as it is improving every day. And if you want to contribute, please get in touch on the &lt;a href="https://github.com/davidbrochart/nbterm"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="acknowledgements"&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;The development of nbterm is sponsored by &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://twitter.com/davidbrochart"&gt;David Brochart&lt;/a&gt; is a scientific software developer at QuantStack. He is a contributor to several libraries in the Jupyter ecosystem, such as &lt;a href="https://github.com/jupyter/nbclient"&gt;nbclient&lt;/a&gt;, &lt;a href="https://github.com/jupyter/jupyter_client"&gt;jupyter-client&lt;/a&gt;, &lt;a href="https://github.com/jupyter-server/jupyter_server"&gt;jupyter-server&lt;/a&gt;, &lt;a href="https://github.com/ipython/ipykernel"&gt;ipykernel&lt;/a&gt;, and &lt;a href="https://github.com/jupyter-widgets/ipywidgets"&gt;ipywidgets&lt;/a&gt;.&lt;/p&gt;
</content><category term="Jupyter Notebook"/></entry></feed>