notebook.rst 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. Notebook
  2. --------
  3. Background
  4. ~~~~~~~~~~
  5. .. _architecture-walkthrough:
  6. A JupyterLab architecture walkthrough from June 16, 2016, provides an overview of the notebook architecture.
  7. .. raw:: html
  8. <div class="jp-youtube-video">
  9. <iframe src="https://www.youtube-nocookie.com/embed/4Qm6oD_Rlw8?rel=0&amp;showinfo=0&amp;start=3326" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
  10. </div>
  11. The most complicated plugin included in the **JupyterLab application**
  12. is the **Notebook plugin**.
  13. The
  14. `NotebookWidgetFactory <http://jupyterlab.github.io/jupyterlab/classes/_notebook_src_widgetfactory_.notebookwidgetfactory.html>`__
  15. constructs a new
  16. `NotebookPanel <http://jupyterlab.github.io/jupyterlab/classes/_notebook_src_panel_.notebookpanel.html>`__
  17. from a model and populates the toolbar with default widgets.
  18. Structure of the Notebook plugin
  19. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  20. The Notebook plugin provides a model and widgets for dealing with
  21. notebook files.
  22. Model
  23. ^^^^^
  24. The
  25. `NotebookModel <http://jupyterlab.github.io/jupyterlab/classes/_notebook_src_model_.notebookmodel.html>`__
  26. contains an observable list of cells.
  27. A `cell
  28. model <http://jupyterlab.github.io/jupyterlab/modules/_cells_src_model_.html>`__
  29. can be:
  30. - a code cell
  31. - a markdown cell
  32. - raw cell
  33. A code cell contains a list of **output models**. The list of cells and
  34. the list of outputs can be observed for changes.
  35. Cell operations
  36. '''''''''''''''
  37. The NotebookModel cell list supports single-step operations such as
  38. moving, adding, or deleting cells. Compound cell list operations, such
  39. as undo/redo, are also supported by the NotebookModel. Right now,
  40. undo/redo is only supported on cells and is not supported on notebook
  41. attributes, such as notebook metadata. Currently, undo/redo for
  42. individual cell input content is supported by the CodeMirror editor's
  43. undo feature. (Note: CodeMirror editor's undo does not cover cell
  44. metadata changes.)
  45. Cursors and metadata
  46. ''''''''''''''''''''
  47. The notebook model and the cell model (i.e. notebook cells) support
  48. getting and setting metadata through cursors. You may request a cursor
  49. to write to a specific metadata key from a notebook model or a cell
  50. model.
  51. Notebook widget
  52. ^^^^^^^^^^^^^^^
  53. After the NotebookModel is created, the NotebookWidgetFactory constructs
  54. a new NotebookPanel from the model. The NotebookPanel widget is added to
  55. the DockPanel. The **NotebookPanel** contains:
  56. - a
  57. `Toolbar <http://jupyterlab.github.io/jupyterlab/modules/_apputils_src_toolbar_.html>`__
  58. - a `Notebook
  59. widget <http://jupyterlab.github.io/jupyterlab/classes/_notebook_src_widget_.notebook.html>`__.
  60. The NotebookPanel also adds completion logic.
  61. The **NotebookToolbar** maintains a list of widgets to add to the
  62. toolbar. The **Notebook widget** contains the rendering of the notebook
  63. and handles most of the interaction logic with the notebook itself (such
  64. as keeping track of interactions such as selected and active cells and
  65. also the current edit/command mode).
  66. The NotebookModel cell list provides ways to do fine-grained changes to
  67. the cell list.
  68. Higher level actions using NotebookActions
  69. ''''''''''''''''''''''''''''''''''''''''''
  70. Higher-level actions are contained in the
  71. `NotebookActions <http://jupyterlab.github.io/jupyterlab/modules/_notebook_src_actions_.notebookactions.html>`__
  72. namespace, which has functions, when given a notebook widget, to run a
  73. cell and select the next cell, merge or split cells at the cursor,
  74. delete selected cells, etc.
  75. Widget hierarchy
  76. ''''''''''''''''
  77. A Notebook widget contains a list of `cell
  78. widgets <http://jupyterlab.github.io/jupyterlab/modules/_cells_src_widget_.html>`__,
  79. corresponding to the cell models in its cell list.
  80. - Each cell widget contains an
  81. `InputArea <http://jupyterlab.github.io/jupyterlab/classes/_cells_src_inputarea_.inputarea.html>`__,
  82. - which contains n
  83. `CodeEditorWrapper <http://jupyterlab.github.io/jupyterlab/classes/_codeeditor_src_widget_.codeeditorwrapper.html>`__,
  84. - which contains a JavaScript CodeMirror instance.
  85. A
  86. `CodeCell <http://jupyterlab.github.io/jupyterlab/classes/_cells_src_widget_.codecell.html>`__
  87. also contains an
  88. `OutputArea <http://jupyterlab.github.io/jupyterlab/classes/_outputarea_src_widget_.outputarea.html>`__.
  89. An OutputArea is responsible for rendering the outputs in the
  90. `OutputAreaModel <http://jupyterlab.github.io/jupyterlab/classes/_outputarea_src_model_.outputareamodel.html>`__
  91. list. An OutputArea uses a notebook-specific
  92. `RenderMimeRegistry <http://jupyterlab.github.io/jupyterlab/classes/_rendermime_src_registry_.rendermimeregistry.html>`__
  93. object to render ``display_data`` output messages.
  94. Rendering output messages
  95. '''''''''''''''''''''''''
  96. A **Rendermime plugin** provides a pluggable system for rendering output
  97. messages. Default renderers are provided for markdown, html, images,
  98. text, etc. Extensions can register renderers to be used across the
  99. entire application by registering a handler and mimetype in the
  100. rendermime registry. When a notebook is created, it copies the global
  101. Rendermime singleton so that notebook-specific renderers can be added.
  102. The ipywidgets widget manager is an example of an extension that adds a
  103. notebook-specific renderer, since rendering a widget depends on
  104. notebook-specific widget state.
  105. How to extend the Notebook plugin
  106. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  107. We'll walk through two notebook extensions:
  108. - adding a button to the toolbar
  109. - adding an ipywidgets extension
  110. Adding a button to the toolbar
  111. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  112. Start from the cookie cutter extension template.
  113. ::
  114. pip install cookiecutter
  115. cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts
  116. cd my-cookie-cutter-name
  117. Install the dependencies. Note that extensions are built against the
  118. released npm packages, not the development versions.
  119. ::
  120. npm install --save @jupyterlab/notebook @jupyterlab/application @jupyterlab/apputils @jupyterlab/docregistry @phosphor/disposable
  121. Copy the following to ``src/index.ts``:
  122. .. code:: typescript
  123. import {
  124. IDisposable, DisposableDelegate
  125. } from '@phosphor/disposable';
  126. import {
  127. JupyterLab, JupyterLabPlugin
  128. } from '@jupyterlab/application';
  129. import {
  130. ToolbarButton
  131. } from '@jupyterlab/apputils';
  132. import {
  133. DocumentRegistry
  134. } from '@jupyterlab/docregistry';
  135. import {
  136. NotebookActions, NotebookPanel, INotebookModel
  137. } from '@jupyterlab/notebook';
  138. /**
  139. * The plugin registration information.
  140. */
  141. const plugin: JupyterLabPlugin<void> = {
  142. activate,
  143. id: 'my-extension-name:buttonPlugin',
  144. autoStart: true
  145. };
  146. /**
  147. * A notebook widget extension that adds a button to the toolbar.
  148. */
  149. export
  150. class ButtonExtension implements DocumentRegistry.IWidgetExtension<NotebookPanel, INotebookModel> {
  151. /**
  152. * Create a new extension object.
  153. */
  154. createNew(panel: NotebookPanel, context: DocumentRegistry.IContext<INotebookModel>): IDisposable {
  155. let callback = () => {
  156. NotebookActions.runAll(panel.notebook, context.session);
  157. };
  158. let button = new ToolbarButton({
  159. className: 'myButton',
  160. onClick: callback,
  161. tooltip: 'Run All'
  162. });
  163. let i = document.createElement('i');
  164. i.classList.add('fa', 'fa-fast-forward');
  165. button.node.appendChild(i);
  166. panel.toolbar.insertItem(0, 'runAll', button);
  167. return new DisposableDelegate(() => {
  168. button.dispose();
  169. });
  170. }
  171. }
  172. /**
  173. * Activate the extension.
  174. */
  175. function activate(app: JupyterLab) {
  176. app.docRegistry.addWidgetExtension('Notebook', new ButtonExtension());
  177. };
  178. /**
  179. * Export the plugin as default.
  180. */
  181. export default plugin;
  182. Run the following commands:
  183. ::
  184. npm install
  185. npm run build
  186. jupyter labextension install .
  187. jupyter lab
  188. Open a notebook and observe the new "Run All" button.
  189. The *ipywidgets* third party extension
  190. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  191. This discussion will be a bit confusing since we've been using the term
  192. *widget* to refer to *phosphor widgets*. In the discussion below,
  193. *ipython widgets* will be referred to as *ipywidgets*. There is no
  194. intrinsic relation between *phosphor widgets* and *ipython widgets*.
  195. The *ipywidgets* extension registers a factory for a notebook *widget*
  196. extension using the `Document
  197. Registry <http://jupyterlab.github.io/jupyterlab/classes/_docregistry_src_registry_.documentregistry.html>`__.
  198. The ``createNew()`` function is called with a NotebookPanel and
  199. `DocumentContext <http://jupyterlab.github.io/jupyterlab/interfaces/_docregistry_src_registry_.documentregistry.icontext.html>`__.
  200. The plugin then creates a ipywidget manager (which uses the context to
  201. interact the kernel and kernel's comm manager). The plugin then
  202. registers an ipywidget renderer with the notebook instance's rendermime
  203. (which is specific to that particular notebook).
  204. When an ipywidget model is created in the kernel, a comm message is sent
  205. to the browser and handled by the ipywidget manager to create a
  206. browser-side ipywidget model. When the model is displayed in the kernel,
  207. a ``display_data`` output is sent to the browser with the ipywidget
  208. model id. The renderer registered in that notebook's rendermime is asked
  209. to render the output. The renderer asks the ipywidget manager instance
  210. to render the corresponding model, which returns a JavaScript promise.
  211. The renderer creates a container *phosphor widget* which it hands back
  212. synchronously to the OutputArea, and then fills the container with the
  213. rendered *ipywidget* when the promise resolves.
  214. Note: The ipywidgets third party extension has not yet been released.