IPEP 16: Notebook multi directory dashboard and URL mapping - ShuaiYAN/ipython GitHub Wiki
Author | Zach Sailer <[email protected]> |
Status | Active |
Created | April 4, 2013 |
Updated | October 18, 2013 |
Discussion | #3166 |
PR | #4303 |
This proposes a new web service API design which supports multi-directory navigation for the IPython Notebook. It frees the user to open notebooks in a different location than the server.
Currently, it is not possible to open a notebooks in different directories under a single server. A notebook must be in the same location as the server if the user wants to open it. This prevents users from the ability to organize their notebooks into different subdirectories. It should be possible navigate to any notebook in a subdirectory under a single server.
On the development side of things, the current Notebook web service needs some standardization and reorganization. Providing consistent messaging and error handling between the client and server will simplify the web services and make future development/growth easier.
The following list describes a quick overview of the changes made by this proposal.
- Notebooks are no longer identified by an immutable UUID. Instead, they are tracked by their name and file-system path (relative to server's location).
- The kernel manager and notebook manager are completely independent of one another. The kernel manager no longer maps a notebook to it's kernel using a UUID.
- A new session manager holds the mapping between kernels and notebooks.
- All handling of requests between the client and server are organized into RESTful APIs.
- All messaging between the client and server is done using standardized JSON objects.
- The URL mapping is adjusted to reflect the new APIs and multidirectory support.
The URL is adjusted for the removal of the notebook IDs. It will display the name and path (relative to server's location) of the notebook. With the reorganization of the web services, new arguments are added to the URL to call the correct API. The API URLs can be seen in the IPython web services section below. This new mapping to a specific notebook is dynamic and can change with notebook rename. The current URL mapping for IPython notebook can be found here.
The chart below shows the new URL scheme for the dashboard and notebooks (seen by users).
Note the first element tree
(for the dashboard) and notebooks
(for notebooks).
HTTP verb | URL | Action |
---|---|---|
GET |
/ | redirects to "/tree" URL |
GET |
/tree | navigates user to dashboard at the top level directory of the current file system |
GET |
/tree/foo/bar | navigates user to dashboard for the "foo/bar" directory |
GET |
/login | navigates to login page; if no user profile is defined, it navigates user to dashboard |
GET |
/logout | logs out of current profile, and navigates user to login page |
GET |
/notebooks/foo/bar/[:notebook_name] | go to live notebook view of the named notebook |
The Notebook web service is organized into the APIs listed below. Each service handles all requests and returns the proper status code, JSON data, and URL redirects.
This documentation describes the JSON messaging structures for the multidirectory IPython Notebook. In handling HTTP request, we pass all information between the server and client using JSON standard models. Each standard model is shown at the beginning of the sections below. This format follows to the principles described in RESTful web-services.
- Notebooks
- Kernels
- Sessions
This web-service handles all HTTP requests on ".ipynb" files. The full notebook model in JSON is shown below. The content
field is not always included in the notebook model because of the weight it can carry. It is typically included when the client makes a request for a particular notebook.
{
"name": "My Notebook.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-10-01T14:22:36.123456+00:00",
"modified": "2013-10-02T11:29:27.616675+00:00",
"content":{
"metadata":{},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": []
}
}
Note about paths: When a path
key appears in the RESTful API,
it is always the path relative to the root notebook server directory.
In replies from the notebook server, this path SHALL NOT start with '/',
and SHALL NOT end with '/'.
In requests to the server, it SHOULD NOT start or end with '/'.
The path separator MUST BE '/', it is not platform dependent.
The path SHALL BE unicode, not url-escaped.
Some requests (notably resource creation via POST / PUT requests) set a Location header. This value will be the url-escaped path, not the unicode path.
Client requests will never specify a whole model. They will only specify those values that should indicate a change.
The timestamps in the notebook model are read-only. A request to the server to update or upload a notebook model should never contain the timestamp keys (they will be ignored).
Since the path
and name
are specified in the URL,
these keys are generally omitted from requests as well.
The one exception being saving an existing notebook to a new location,
in which case the new name and path are given in the model,
and the current name and path are in the URL.
The type
field can also be omitted by the client, but will
always be provided by the servers.
POST always creates a new notebook. There are a few ways to create notebooks: simple creation, uploading, and copying existing notebooks. In each case, POST requests are always made to a directory URL, in which case the server picks the new notebook's name. If you want to specify the new notebook's name, make a PUT request to the full path URL.
Creates a new notebook. If a POST, the name will be the first unused name of the form "Untitled#.ipynb"
, with the first available integer.
POST /api/notebooks/[:path]
PUT /api/notebooks/[:path]/[:name.ipynb]
status: 201 Created
Location: /api/notebooks/foo/bar/Untitled0.ipynb
{
"name": "Untitled0.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-09-01T09:15:14.12345+00:00",
"modified": "2013-10-02T11:29:27.616675+00:00"
}
Uploads a new notebook to path
. If a POST, the name will be the first unused name of the form "Untitled#.ipynb"
.
POST /api/notebooks/[:path]
PUT /api/notebooks/[:path]/[:name.ipynb]
- content
- The actual notebook structure
Example:
{
"content": {
"metadata":{},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": []
}
}
status: 201 Created
Location: /api/notebooks/foo/bar/MyNotebook.ipynb
{
"name": "MyNotebook.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-09-01T09:15:14.12345+00:00",
"modified": "2013-09-01T09:15:14.12345+00:00"
}
Create a new notebook from a copy of an existing notebook.
If POST, the new notebook will have a name of the form {copy_from}-Copy#.ipynb
,
with the first available integer.
POST /api/notebooks/[:path]
PUT /api/notebooks/[:path]/[:name.ipynb]
- copy_from
- The notebook name to copy from
Example:
{
"copy_from" : "MyNotebook.ipynb"
}
status: 201 Created
Location: /api/notebooks/foo/bar/MyNotebook-Copy0.ipynb
{
"name": "MyNotebook-Copy0.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-10-01T12:21:20.123456+00:00",
"modified": "2013-09-01T09:15:14.12345+00:00"
}
Returns a list of notebook models in the directory path
.
GET /api/notebooks/[:path]
status: 200 OK
[
{
"name": "notebook1.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-10-01T12:21:20.123456+00:00",
"modified": "2013-10-02T11:29:27.616675+00:00"
},
{
"name": "notebook2.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-10-01T12:21:20.123456+00:00",
"modified": "2013-10-02T11:29:27.616675+00:00"
}
]
For IPython 2.0 only: listing notebooks in this release will also return directories in the path as well. These models will be removed from the notebook listing for 3.0 once we have a proper contents web service. Directories have the following model:
{
"name": "bam",
"path": "foo/bar",
"type": "directory",
"created": "2013-10-01T12:21:20.123456+00:00",
"modified": "2013-10-02T11:29:27.616675+00:00"
}
The list of models will be sorted in the following order:
-
Index.ipynb
if it exists. - All directories in alphabetical order.
- All notebooks in alphabetical order.
Returns the notebook model for a given notebook path, including the full document content.
GET /api/notebooks/[:path]/[:name.ipynb]
status: 200 OK
{
"name": "notebook1.ipynb",
"path": "foo/bar",
"type": "notebook",
"modified": "2013-10-02T11:29:27.616675+00:00",
"created": "2013-10-01T12:21:20.123456+00:00",
"content":{
"metadata": {},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": []
}
}
This request renames the notebook and returns the updated model without content.
PATCH /api/notebooks/[:path]/[:name.ipynb]
- name
- The new notebook filename (e.g. `notebook.ipynb`)
- path
- The new notebook path (e.g. `foo/bar`)
status: 200 OK
Location: /api/notebooks/foo/bar/notebook1.ipynb
{
"name": "notebook1.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-10-01T12:21:20.123456+00:00",
"modified": "2013-10-04T14:32:19.123456+00:00"
}
Update an existing notebook in-place. This is how standard saves are performed. If the path and/or name of the notebook are specified in the model, the notebook will be saved to the new location specified in the model. After doing this, future PUT requests must use the URL for the new path.
Returns the updated notebook model without content.
PUT /api/notebooks/[:path]/[:name.ipynb]
- name
- The new notebook name (`my notebook.ipynb`), if changed
- path
- The new path for the notebook, if changed
- content
- The actual body of the notebook document
Example:
{
"name": "notebook1.ipynb",
"path": "foo/bar",
"content": {
"metadata":{},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": []
}
}
status: 200 OK
{
"name": "notebook1.ipynb",
"path": "foo/bar",
"type": "notebook",
"created": "2013-10-01T12:21:20.123456+00:00",
"modified": "2013-10-04T14:32:19.123456+00:00"
}
Deletes a notebook from the specified location.
DELETE /api/notebooks/[:path]/[:name.ipynb]
status: 204 No Content
List checkpoints for a given notebook. There will typically be zero or one results.
GET /api/notebooks/[:path]/[:name.ipynb]/checkpoints
status: 200 OK
[
{
"id" : "checkpoint-id",
"last_modified" : "2013-10-18T23:54:40+00:00"
}
]
Create a new checkpoint with the current state of a notebook. With the default FileNotebookManager, only one checkpoint is supported, so creating new checkpoints clobbers existing ones.
POST /api/notebooks/[:path]/[:name.ipynb]/checkpoints
status: 201 Created
{
"id" : "checkpoint-id",
"last_modified" : "2013-10-18T23:54:40+00:00"
}
Restore a notebook to a particular checkpointed state.
POST /api/notebooks/[:path]/[:name.ipynb]/checkpoints/[checkpoint_id]
status: 204 No Content
Delete a checkpoint.
DELETE /api/notebooks/[:path]/[:name.ipynb]/checkpoints/[checkpoint_id]
status: 204 No Content
This webservice manages all running kernels. The kernel model in JSON is shown below:
{
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
Lists the JSON data for all kernels currently running.
GET /api/kernels
status: 200 OK
[
{
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
},
{
"id": "4f567fb0-2455-4bc9-a137-69daac27e9a2"
}
]
GET /api/kernels/[:kernel_id]
status: 200 OK
{
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
Start an IPython kernel and create a UUID for the kernel.
POST /api/kernels
status: 201 Created
{
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
Kills the kernel and deletes the ID.
DELETE /api/kernels/[:kernel-id]
status: 204 No Content
Send a SIGINT to the kernel process.
POST /api/kernels/[:kernel_id]/interrupt
status: 204 No Content
Kill and restart a kernel, preserving the ID.
POST /api/kernels/[:kernel_id]/restart
status: 200 OK
Location: /api/kernels/b7e1a137-a434-4598-846e-ee51fb06c306
{
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
A session maps a notebook to a kernel. When a notebook is opened in the Web Notebook, a session is created and a kernel is started. The model for a session:
{
"id": "d7753a2c-14da-4ae9-95b8-7b96b11aebe7",
"notebook": {
"name": "notebook1.ipynb",
"path": "foo/bar",
}
"kernel": {
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
}
Returns a list of all currently running sessions.
GET /api/sessions
status: 200 OK
[
{
"id": "d7753a2c-14da-4ae9-95b8-7b96b11aebe7",
"notebook": {
"name": "notebook1.ipynb",
"path": "foo/bar",
}
"kernel": {
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
},
{
"id": "b4dfa62c-0e91-4111-9d1f-0c59069c6602",
"notebook": {
"name": "notebook1.ipynb",
"path": "foo/bar",
}
"kernel": {
"id": "4adcb1a3-2e7f-4e82-af2e-d76f5815467a"
}
}
]
Creates a new Session for a given notebook.
POST /api/sessions
- notebook
-
- name
- The filename of the notebook
- path
- Path to the notebook's directory
Example:
{
"notebook" : {
"name": "Untitled0.ipynb",
"path": "foo/bar"
}
}
status: 201 Created
{
"id": "d7753a2c-14da-4ae9-95b8-7b96b11aebe7",
"notebook": {
"name": "Untitled0.ipynb",
"path": "foo/bar",
},
"kernel": {
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
}
GET /api/sessions/[:session_id]
status: 200 OK
{
"id": "d7753a2c-14da-4ae9-95b8-7b96b11aebe7",
"notebook": {
"name": "Untitled0.ipynb",
"path": "foo/bar",
},
"kernel": {
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
}
This can be used to rename the notebook, or move it to a new directory.
PATCH /api/sessions/[:session_id]
- notebook
-
- name
- The new filename of the notebook
- path
- Path to the notebook's new directory
Example:
{
"notebook" : {
"name": "Untitled0.ipynb",
"path": "foo/bar"
}
}
status: 200 OK
{
"id": "d7753a2c-14da-4ae9-95b8-7b96b11aebe7",
"notebook": {
"name": "new_name.ipynb",
"path": "foo/bar",
},
"kernel": {
"id": "b7e1a137-a434-4598-846e-ee51fb06c306"
}
}
Deleting a session terminates the session's kernel, and removes the session mapping.
DELETE /api/sessions/[:session_id]
status: 204 No Content
The notebook dashboard only shows '.ipynb' files. In the future, we'd like to show all files in a current directory and open them in an editor-like environment. Also, we need a web service which handles all creation and deletion of folders. This IPEP doesn't include these capabilities yet, but it is something we'd like to do.
The second thing to consider is the notion of projects
. A project is analogous to a
repository on Github, where all files, notebooks, and sub-directories are located inside the
project's file system. This IPEP only proposes implementing the ability to navigate through a
hierarchical file system within a single project. When the server launches under this
implementation, a dashboard opens at the top-level directory of a project (i.e. $HOME). The user
can move through parent directories and sub-directories within this project, but cannot switch
projects in the current server. They must relaunch a server in the new project's location on their
file system.
In the future, we would like to give the notebook the ability to switch between and create new projects on a single server. This will require small adjustments to this proposed URL scheme. The goal would be to create a new top-level "projects page" where the user's projects are listed. When one is clicked, the page is directed to the normal dashboard described above, with the project's file system of notebooks, sub-directories, and other files.
Go to the PR #4303.
Go to the IPEP 16 discussion issue #3166.