Cleanup User Documentation

This commit is contained in:
Jeremy Tuloup 2022-03-04 17:37:52 +01:00
parent 58d701a383
commit c31203e42f
7 changed files with 8 additions and 1046 deletions

View File

@ -1,98 +0,0 @@
Comms
=====
*Comms* allow custom messages between the frontend and the kernel. They are used,
for instance, in `ipywidgets <https://ipywidgets.readthedocs.io/en/latest/>`__ to
update widget state.
A comm consists of a pair of objects, in the kernel and the frontend, with an
automatically assigned unique ID. When one side sends a message, a callback on
the other side is triggered with that message data. Either side, the frontend
or kernel, can open or close the comm.
.. seealso::
`Custom Messages <https://jupyter-client.readthedocs.io/en/latest/messaging.html#custom-messages>`__
The messaging specification section on comms
Opening a comm from the kernel
------------------------------
First, the function to accept the comm must be available on the frontend. This
can either be specified in a `requirejs` module, or registered in a registry, for
example when an :doc:`extension <extending/frontend_extensions>` is loaded.
This example shows a frontend comm target registered in a registry:
.. code-block:: javascript
Jupyter.notebook.kernel.comm_manager.register_target('my_comm_target',
function(comm, msg) {
// comm is the frontend comm instance
// msg is the comm_open message, which can carry data
// Register handlers for later messages:
comm.on_msg(function(msg) {...});
comm.on_close(function(msg) {...});
comm.send({'foo': 0});
});
Now that the frontend comm is registered, you can open the comm from the kernel:
.. code-block:: python
from ipykernel.comm import Comm
# Use comm to send a message from the kernel
my_comm = Comm(target_name='my_comm_target', data={'foo': 1})
my_comm.send({'foo': 2})
# Add a callback for received messages.
@my_comm.on_msg
def _recv(msg):
# Use msg['content']['data'] for the data in the message
This example uses the IPython kernel; it's up to each language kernel what API,
if any, it offers for using comms.
Opening a comm from the frontend
--------------------------------
This is very similar to above, but in reverse. First, a comm target must be
registered in the kernel. For instance, this may be done by code displaying
output: it will register a target in the kernel, and then display output
containing Javascript to connect to it.
.. code-block:: python
def target_func(comm, open_msg):
# comm is the kernel Comm instance
# msg is the comm_open message
# Register handler for later messages
@comm.on_msg
def _recv(msg):
# Use msg['content']['data'] for the data in the message
comm.send({'echo': msg['content']['data']})
# Send data to the frontend on creation
comm.send({'foo': 5})
get_ipython().kernel.comm_manager.register_target('my_comm_target', target_func)
This example uses the IPython kernel again; this example will be different in
other kernels that support comms. Refer to the specific language kernel's
documentation for comms support.
And then open the comm from the frontend:
.. code-block:: javascript
const comm = Jupyter.notebook.kernel.comm_manager.new_comm('my_comm_target', {'foo': 6})
// Send data
comm.send({'foo': 7})
// Register a handler
comm.on_msg(function(msg) {
console.log(msg.content.data.foo);
});

View File

@ -11,129 +11,17 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Starting with Jupyter Notebook 5.0, you can customize the `command` mode shortcuts from within the Notebook Application itself. \n",
"You can customize the `command` mode shortcuts from within the Notebook Application itself. \n",
"\n",
"Head to the **`Help`** menu and select the **`Edit keyboard Shortcuts`** item.\n",
"Head to the **Settings** menu and select the **Settings Editor** item.\n",
"A dialog will guide you through the process of adding custom keyboard shortcuts.\n",
"\n",
"Keyboard shortcut set from within the Notebook Application will be persisted to your configuration file. \n",
"A single action may have several shortcuts attached to it."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Keyboard Shortcut Customization (Pre Notebook 5.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Starting with IPython 2.0 keyboard shortcuts in command and edit mode are fully customizable. These customizations are made using the Jupyter JavaScript API. Here is an example that makes the `r` key available for running a cell:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%javascript\n",
"\n",
"Jupyter.keyboard_manager.command_shortcuts.add_shortcut('r', {\n",
" help : 'run cell',\n",
" help_index : 'zz',\n",
" handler : function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
" }}\n",
");"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\"By default the keypress `r`, while in command mode, changes the type of the selected cell to `raw`. This shortcut is overridden by the code in the previous cell, and thus the action no longer be available via the keypress `r`.\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are a couple of points to mention about this API:\n",
"\n",
"* The `help_index` field is used to sort the shortcuts in the Keyboard Shortcuts help dialog. It defaults to `zz`.\n",
"* When a handler returns `false` it indicates that the event should stop propagating and the default action should not be performed. For further details about the `event` object or event handling, see the jQuery docs.\n",
"* If you don't need a `help` or `help_index` field, you can simply pass a function as the second argument to `add_shortcut`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%javascript\n",
"\n",
"Jupyter.keyboard_manager.command_shortcuts.add_shortcut('r', function (event) {\n",
" IPython.notebook.execute_cell();\n",
" return false;\n",
"});"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Likewise, to remove a shortcut, use `remove_shortcut`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%javascript\n",
"\n",
"Jupyter.keyboard_manager.command_shortcuts.remove_shortcut('r');"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you want your keyboard shortcuts to be active for all of your notebooks, put the above API calls into your `custom.js` file."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Of course we provide name for majority of existing action so that you do not have to re-write everything, here is for example how to bind `r` back to it's initial behavior:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%javascript\n",
"\n",
"Jupyter.keyboard_manager.command_shortcuts.add_shortcut('r', 'jupyter-notebook:change-cell-to-raw');"
]
}
],
"metadata": {
"nbsphinx": {
"execute": "never"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
@ -150,6 +38,9 @@
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
},
"nbsphinx": {
"execute": "never"
}
},
"nbformat": 4,

View File

@ -1,603 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Embracing web standards"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One of the main reasons why we developed the current notebook web application \n",
"was to embrace the web technology. \n",
"\n",
"By being a pure web application using HTML, JavaScript, and CSS, the Notebook can get \n",
"all the web technology improvement for free. Thus, as browser support for different \n",
"media extend, the notebook web app should be able to be compatible without modification. \n",
"\n",
"This is also true with performance of the User Interface as the speed of JavaScript VM increases. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The other advantage of using only web technology is that the code of the interface is fully accessible to the end user and is modifiable live.\n",
"Even if this task is not always easy, we strive to keep our code as accessible and reusable as possible.\n",
"This should allow us - with minimum effort - development of small extensions that customize the behavior of the web interface. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tampering with the Notebook application"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The first tool that is available to you and that you should be aware of are browser \"developers tool\". The exact naming can change across browser and might require the installation of extensions. But basically they can allow you to inspect/modify the DOM, and interact with the JavaScript code that runs the frontend.\n",
"\n",
" - In Chrome and Safari, Developer tools are in the menu `View > Developer > JavaScript Console` \n",
" - In Firefox you might need to install [Firebug](http://getfirebug.com/)\n",
" \n",
"Those will be your best friends to debug and try different approaches for your extensions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Injecting JS"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Using magics"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The above tools can be tedious for editing edit long JavaScript files. Therefore we provide the `%%javascript` magic. This allows you to quickly inject JavaScript into the notebook. Still the JavaScript injected this way will not survive reloading. Hence, it is a good tool for testing and refining a script.\n",
"\n",
"You might see here and there people modifying css and injecting js into the notebook by reading file(s) and publishing them into the notebook.\n",
"Not only does this often break the flow of the notebook and make the re-execution of the notebook broken, but it also means that you need to execute those cells in the entire notebook every time you need to update the code.\n",
"\n",
"This can still be useful in some cases, like the `%autosave` magic that allows you to control the time between each save. But this can be replaced by a JavaScript dropdown menu to select the save interval."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"## you can inspect the autosave code to see what it does.\n",
"%autosave??"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### custom.js"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To inject JavaScript we provide an entry point: `custom.js` that allows the user to execute and load other resources into the notebook.\n",
"JavaScript code in `custom.js` will be executed when the notebook app starts and can then be used to customize almost anything in the UI and in the behavior of the notebook.\n",
"\n",
"`custom.js` can be found in the `~/.jupyter/custom/custom.js`. You can share your custom.js with others."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Back to theory"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from jupyter_core.paths import jupyter_config_dir\n",
"jupyter_dir = jupyter_config_dir()\n",
"jupyter_dir"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and custom js is in "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import os.path\n",
"custom_js_path = os.path.join(jupyter_dir, 'custom', 'custom.js')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# my custom js\n",
"if os.path.isfile(custom_js_path):\n",
" with open(custom_js_path) as f:\n",
" print(f.read())\n",
"else:\n",
" print(\"You don't have a custom.js file\") "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that `custom.js` is meant to be modified by user. When writing a script, you can define it in a separate file and add a line of configuration into `custom.js` that will fetch and execute the file."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Warning** : even if modification of `custom.js` takes effect immediately after browser refresh (except if browser cache is aggressive), *creating* a file in `static/` directory needs a **server restart**."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise :"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" - Create a `custom.js` in the right location with the following content:\n",
"```javascript\n",
"alert(\"hello world from custom.js\")\n",
"```\n",
"\n",
" - Restart your server and open any notebook.\n",
" - Be greeted by custom.js"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Have a look at [default custom.js](https://github.com/jupyter/notebook/blob/4.0.x/notebook/static/custom/custom.js), to see it's content and for more explanation."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### For the quick ones : "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We've seen above that you can change the autosave rate by using a magic. This is typically something I don't want to type every time, and that I don't like to embed into my workflow and documents. (readers don't care what my autosave time is). Let's build an extension that allows us to do it. "
]
},
{
"cell_type": "markdown",
"metadata": {
"foo": true
},
"source": [
"Create a dropdown element in the toolbar (DOM `Jupyter.toolbar.element`), you will need \n",
"\n",
"- `Jupyter.notebook.set_autosave_interval(milliseconds)`\n",
"- know that 1 min = 60 sec, and 1 sec = 1000 ms"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```javascript\n",
"\n",
"var label = jQuery('<label/>').text('AutoScroll Limit:');\n",
"var select = jQuery('<select/>')\n",
" //.append(jQuery('<option/>').attr('value', '2').text('2min (default)'))\n",
" .append(jQuery('<option/>').attr('value', undefined).text('disabled'))\n",
"\n",
" // TODO:\n",
" //the_toolbar_element.append(label)\n",
" //the_toolbar_element.append(select);\n",
" \n",
"select.change(function() {\n",
" var val = jQuery(this).val() // val will be the value in [2]\n",
" // TODO\n",
" // this will be called when dropdown changes\n",
"\n",
"});\n",
"\n",
"var time_m = [1,5,10,15,30];\n",
"for (var i=0; i < time_m.length; i++) {\n",
" var ts = time_m[i];\n",
" //[2] ____ this will be `val` on [1] \n",
" // | \n",
" // v \n",
" select.append($('<option/>').attr('value', ts).text(thr+'min'));\n",
" // this will fill up the dropdown `select` with\n",
" // 1 min\n",
" // 5 min\n",
" // 10 min\n",
" // 10 min\n",
" // ...\n",
"}\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### A non-interactive example first"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I like my cython to be nicely highlighted\n",
"\n",
"```javascript\n",
"Jupyter.config.cell_magic_highlight['magic_text/x-cython'] = {}\n",
"Jupyter.config.cell_magic_highlight['magic_text/x-cython'].reg = [/^%%cython/]\n",
"```\n",
"\n",
"`text/x-cython` is the name of CodeMirror mode name, `magic_` prefix will just patch the mode so that the first line that contains a magic does not screw up the highlighting. `reg`is a list or regular expression that will trigger the change of mode."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Get more documentation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sadly, you will have to read the js source file (but there are lots of comments) and/or build the JavaScript documentation using yuidoc.\n",
"If you have `node` and `yui-doc` installed:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```bash\n",
"$ cd ~/jupyter/notebook/notebook/static/notebook/js/\n",
"$ yuidoc . --server\n",
"warn: (yuidoc): Failed to extract port, setting to the default :3000\n",
"info: (yuidoc): Starting YUIDoc@0.3.45 using YUI@3.9.1 with NodeJS@0.10.15\n",
"info: (yuidoc): Scanning for yuidoc.json file.\n",
"info: (yuidoc): Starting YUIDoc with the following options:\n",
"info: (yuidoc):\n",
"{ port: 3000,\n",
" nocode: false,\n",
" paths: [ '.' ],\n",
" server: true,\n",
" outdir: './out' }\n",
"info: (yuidoc): Scanning for yuidoc.json file.\n",
"info: (server): Starting server: http://127.0.0.1:3000\n",
"```\n",
"\n",
"and browse http://127.0.0.1:3000 to get documentation"
]
},
{
"cell_type": "markdown",
"metadata": {
"foo": true
},
"source": [
"#### Some convenience methods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By browsing the documentation you will see that we have some convenience methods that allows us to avoid re-inventing the UI every time :\n",
"```javascript\n",
"Jupyter.toolbar.add_buttons_group([\n",
" {\n",
" 'label' : 'run qtconsole',\n",
" 'icon' : 'fa-terminal', // select your icon from \n",
" // http://fontawesome.io/icons/\n",
" 'callback': function(){Jupyter.notebook.kernel.execute('%qtconsole')}\n",
" }\n",
" // add more button here if needed.\n",
" ]);\n",
"```\n",
"with a [lot of icons] you can select from. \n",
"\n",
"[lot of icons]: http://fontawesome.io/icons/"
]
},
{
"cell_type": "markdown",
"metadata": {
"foo": true
},
"source": [
"## Cell Metadata"
]
},
{
"cell_type": "markdown",
"metadata": {
"foo": true
},
"source": [
"The most requested feature is generally to be able to distinguish an individual cell in the notebook, or run a specific action with them.\n",
"To do so, you can either use `Jupyter.notebook.get_selected_cell()`, or rely on `CellToolbar`. This allows you to register a set of actions and graphical elements that will be attached to individual cells."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Cell Toolbar"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can see some example of what can be done by toggling the `Cell Toolbar` selector in the toolbar on top of the notebook. It provides two default `presets` that are `Default` and `slideshow`. Default allows the user to edit the metadata attached to each cell manually."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we define a function that takes at first parameter an element on the DOM in which to inject UI element. The second element is the cell this element wis registered with. Then we will need to register that function and give it a name.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Register a callback"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"%%javascript\n",
"var CellToolbar = Jupyter.CellToolbar\n",
"var toggle = function(div, cell) {\n",
" var button_container = $(div)\n",
"\n",
" // let's create a button that shows the current value of the metadata\n",
" var button = $('<button/>').addClass('btn btn-mini').text(String(cell.metadata.foo));\n",
"\n",
" // On click, change the metadata value and update the button label\n",
" button.click(function(){\n",
" var v = cell.metadata.foo;\n",
" cell.metadata.foo = !v;\n",
" button.text(String(!v));\n",
" })\n",
"\n",
" // add the button to the DOM div.\n",
" button_container.append(button);\n",
"}\n",
"\n",
" // now we register the callback under the name foo to give the\n",
" // user the ability to use it later\n",
" CellToolbar.register_callback('tuto.foo', toggle);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Registering a preset"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This function can now be part of many `preset` of the CellToolBar."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"foo": true,
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"%%javascript\n",
"Jupyter.CellToolbar.register_preset('Tutorial 1',['tuto.foo','default.rawedit'])\n",
"Jupyter.CellToolbar.register_preset('Tutorial 2',['slideshow.select','tuto.foo'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You should now have access to two presets :\n",
"\n",
" - Tutorial 1\n",
" - Tutorial 2\n",
" \n",
"And check that the buttons you defined share state when you toggle preset. \n",
"Also check that the metadata of the cell is modified when you click the button, and that when saved on reloaded the metadata is still available."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Try to wrap the all code in a file, put this file in `{jupyter_dir}/custom/<a-name>.js`, and add \n",
"\n",
"```\n",
"require(['custom/<a-name>']);\n",
"```\n",
"\n",
"in `custom.js` to have this script automatically loaded in all your notebooks.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`require` is provided by a [JavaScript library](http://requirejs.org/) that allow you to express dependency. For simple extension like the previous one we directly mute the global namespace, but for more complex extension you could pass a callback to `require([...], <callback>)` call, to allow the user to pass configuration information to your plugin.\n",
"\n",
"In Python language, \n",
"\n",
"```javascript\n",
"require(['a/b', 'c/d'], function( e, f){\n",
" e.something()\n",
" f.something()\n",
"})\n",
"```\n",
"\n",
"could be read as\n",
"```python\n",
"import a.b as e\n",
"import c.d as f\n",
"e.something()\n",
"f.something()\n",
"```\n",
"\n",
"\n",
"See for example @damianavila [\"ZenMode\" plugin](https://github.com/ipython-contrib/jupyter_contrib_nbextensions/blob/b29c698394239a6931fa4911440550df214812cb/src/jupyter_contrib_nbextensions/nbextensions/zenmode/main.js#L32) :\n",
"\n",
"```javascript\n",
"\n",
"// read that as\n",
"// import custom.zenmode.main as zenmode\n",
"require(['custom/zenmode/main'],function(zenmode){\n",
" zenmode.background('images/back12.jpg');\n",
"})\n",
"```\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### For the quickest"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Try to use [the following](https://github.com/ipython/ipython/blob/1.x/IPython/html/static/notebook/js/celltoolbar.js#L367) to bind a dropdown list to `cell.metadata.difficulty.select`. \n",
"\n",
"It should be able to take the 4 following values :\n",
"\n",
" - `<None>`\n",
" - `Easy`\n",
" - `Medium`\n",
" - `Hard`\n",
" \n",
"We will use it to customize the output of the converted notebook depending on the tag on each cell"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# %load soln/celldiff.js"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@ -171,7 +171,7 @@ Other clients may connect to the same kernel.
When each kernel is started, the notebook server prints to the terminal a
message like this::
[NotebookApp] Kernel started: 87f7d2c0-13e3-43df-8bb8-1bd37aaf3373
[JupyterNotebookApp] Kernel started: 87f7d2c0-13e3-43df-8bb8-1bd37aaf3373
This long string is the kernel's ID which is sufficient for getting the
information necessary to connect to the kernel. If the notebook uses the IPython

View File

@ -1,227 +0,0 @@
.. _server_security:
Security in the Jupyter notebook server
=======================================
Since access to the Jupyter notebook server means access to running arbitrary code,
it is important to restrict access to the notebook server.
For this reason, notebook 4.3 introduces token-based authentication that is **on by default**.
.. note::
If you enable a password for your notebook server,
token authentication is not enabled by default,
and the behavior of the notebook server is unchanged from versions earlier than 4.3.
When token authentication is enabled, the notebook uses a token to authenticate requests.
This token can be provided to login to the notebook server in three ways:
- in the ``Authorization`` header, e.g.::
Authorization: token abcdef...
- In a URL parameter, e.g.::
https://my-notebook/tree/?token=abcdef...
- In the password field of the login form that will be shown to you if you are not logged in.
When you start a notebook server with token authentication enabled (default),
a token is generated to use for authentication.
This token is logged to the terminal, so that you can copy/paste the URL into your browser::
[I 11:59:16.597 NotebookApp] The Jupyter Notebook is running at:
http://localhost:8888/?token=c8de56fa4deed24899803e93c227592aef6538f93025fe01
If the notebook server is going to open your browser automatically
(the default, unless ``--no-browser`` has been passed),
an *additional* token is generated for launching the browser.
This additional token can be used only once,
and is used to set a cookie for your browser once it connects.
After your browser has made its first request with this one-time-token,
the token is discarded and a cookie is set in your browser.
At any later time, you can see the tokens and URLs for all of your running servers with :command:`jupyter notebook list`::
$ jupyter notebook list
Currently running servers:
http://localhost:8888/?token=abc... :: /home/you/notebooks
https://0.0.0.0:9999/?token=123... :: /tmp/public
http://localhost:8889/ :: /tmp/has-password
For servers with token-authentication enabled, the URL in the above listing will include the token,
so you can copy and paste that URL into your browser to login.
If a server has no token (e.g. it has a password or has authentication disabled),
the URL will not include the token argument.
Once you have visited this URL,
a cookie will be set in your browser and you won't need to use the token again,
unless you switch browsers, clear your cookies, or start a notebook server on a new port.
Alternatives to token authentication
------------------------------------
If a generated token doesn't work well for you,
you can set a password for your notebook.
:command:`jupyter notebook password` will prompt you for a password,
and store the hashed password in your :file:`jupyter_notebook_config.json`.
.. versionadded:: 5.0
:command:`jupyter notebook password` command is added.
It is possible to disable authentication altogether by setting the token and password to empty strings,
but this is **NOT RECOMMENDED**, unless authentication or access restrictions are handled at a different layer in your web application:
.. sourcecode:: python
c.NotebookApp.token = ''
c.NotebookApp.password = ''
.. _notebook_security:
Security in notebook documents
==============================
As Jupyter notebooks become more popular for sharing and collaboration,
the potential for malicious people to attempt to exploit the notebook
for their nefarious purposes increases. IPython 2.0 introduced a
security model to prevent execution of untrusted code without explicit
user input.
The problem
-----------
The whole point of Jupyter is arbitrary code execution. We have no
desire to limit what can be done with a notebook, which would negatively
impact its utility.
Unlike other programs, a Jupyter notebook document includes output.
Unlike other documents, that output exists in a context that can execute
code (via Javascript).
The security problem we need to solve is that no code should execute
just because a user has **opened** a notebook that **they did not
write**. Like any other program, once a user decides to execute code in
a notebook, it is considered trusted, and should be allowed to do
anything.
Our security model
------------------
- Untrusted HTML is always sanitized
- Untrusted Javascript is never executed
- HTML and Javascript in Markdown cells are never trusted
- **Outputs** generated by the user are trusted
- Any other HTML or Javascript (in Markdown cells, output generated by
others) is never trusted
- The central question of trust is "Did the current user do this?"
The details of trust
--------------------
When a notebook is executed and saved, a signature is computed from a
digest of the notebook's contents plus a secret key. This is stored in a
database, writable only by the current user. By default, this is located at::
~/.local/share/jupyter/nbsignatures.db # Linux
~/Library/Jupyter/nbsignatures.db # OS X
%APPDATA%/jupyter/nbsignatures.db # Windows
Each signature represents a series of outputs which were produced by code the
current user executed, and are therefore trusted.
When you open a notebook, the server computes its signature, and checks if it's
in the database. If a match is found, HTML and Javascript
output in the notebook will be trusted at load, otherwise it will be
untrusted.
Any output generated during an interactive session is trusted.
Updating trust
**************
A notebook's trust is updated when the notebook is saved. If there are
any untrusted outputs still in the notebook, the notebook will not be
trusted, and no signature will be stored. If all untrusted outputs have
been removed (either via ``Clear Output`` or re-execution), then the
notebook will become trusted.
While trust is updated per output, this is only for the duration of a
single session. A newly loaded notebook file is either trusted or not in its
entirety.
Explicit trust
**************
Sometimes re-executing a notebook to generate trusted output is not an
option, either because dependencies are unavailable, or it would take a
long time. Users can explicitly trust a notebook in two ways:
- At the command-line, with::
jupyter trust /path/to/notebook.ipynb
- After loading the untrusted notebook, with ``File / Trust Notebook``
These two methods simply load the notebook, compute a new signature, and add
that signature to the user's database.
Reporting security issues
-------------------------
If you find a security vulnerability in Jupyter, either a failure of the
code to properly implement the model described here, or a failure of the
model itself, please report it to security@ipython.org.
If you prefer to encrypt your security reports,
you can use :download:`this PGP public key <ipython_security.asc>`.
Affected use cases
------------------
Some use cases that work in Jupyter 1.0 became less convenient in
2.0 as a result of the security changes. We do our best to minimize
these annoyances, but security is always at odds with convenience.
Javascript and CSS in Markdown cells
************************************
While never officially supported, it had become common practice to put
hidden Javascript or CSS styling in Markdown cells, so that they would
not be visible on the page. Since Markdown cells are now sanitized (by
`Google Caja <https://developers.google.com/caja>`__), all Javascript
(including click event handlers, etc.) and CSS will be stripped.
We plan to provide a mechanism for notebook themes, but in the meantime
styling the notebook can only be done via either ``custom.css`` or CSS
in HTML output. The latter only have an effect if the notebook is
trusted, because otherwise the output will be sanitized just like
Markdown.
Collaboration
*************
When collaborating on a notebook, people probably want to see the
outputs produced by their colleagues' most recent executions. Since each
collaborator's key will differ, this will result in each share starting
in an untrusted state. There are three basic approaches to this:
- re-run notebooks when you get them (not always viable)
- explicitly trust notebooks via ``jupyter trust`` or the notebook menu
(annoying, but easy)
- share a notebook signatures database, and use configuration dedicated to the
collaboration while working on the project.
To share a signatures database among users, you can configure:
.. code-block:: python
c.NotebookNotary.data_dir = "/path/to/signature_dir"
to specify a non-default path to the SQLite database (of notebook hashes,
essentially). We are aware that SQLite doesn't work well on NFS and we are
`working out better ways to do this <https://github.com/jupyter/notebook/issues/1782>`_.

View File

@ -159,7 +159,7 @@ Resolving pywin32 Issues
This Worked An Hour Ago
-----------------------
The Jupyter stack is very complex and rightfully so, there's a lot going on. On occassion
The Jupyter stack is very complex and rightfully so, there's a lot going on. On occasion
you might find the system working perfectly well, then, suddenly, you can't get past a
certain cell due to ``import`` failures. In these situations, it's best to ask yourself
if any new python files were added to your notebook development area.

View File

@ -9,5 +9,4 @@ User Documentation
ui_components
examples/Notebook/examples_index.rst
troubleshooting
changelog
comms
changelog