Skip to content

Commit

Permalink
Merge pull request #814 from jcb91/init_cell
Browse files Browse the repository at this point in the history
[init_cell] updates
  • Loading branch information
jcb91 committed Dec 5, 2016
2 parents 3c290a2 + 861cf38 commit 1dcb6e5
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 29 deletions.
38 changes: 36 additions & 2 deletions src/jupyter_contrib_nbextensions/nbextensions/init_cell/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
init_cell
=========

Add a cell toolbar selector to mark cells as 'initialization' cells.
Such initialization cells are run on notebook load, or on clicking the provided button in the main toolbar.
Add a cell toolbar selector to mark cells as 'initialization' cells .
Such initialization cells are run:

* on clicking the provided button in the main toolbar
![main toolabr button](icon.png)
* by default, on kernel ready notification for trusted notebooks.
This is configurable (see options section).
In untrusted notebooks, a warning is displayed if the cells would otherwise
have been run.


Options
-------

This nbextension provides option configurable using the
[jupyter_nbextensions_configurator](https://github.com/Jupyter-contrib/jupyter_nbextensions_configurator).

The running of initialization cells on kernel ready notification can be
frustrating if your kernel is attached to multiple frontends, or is persistent
between frontend reloads (e.g. reloading the notebook browser page without
killing the kernel).
As such, the option `init_cell.run_on_kernel_ready` in the notebook config
section controls whether this behaviour occurs.
The server's config value can also be overridden on a per-notebook basis by
setting `notebook.metadata.init_cell.run_on_kernel_ready`.


Internals
---------

Cells are marked as initialization cells in their metadata, as

cell.metadata.init_cell = true

The running of initialization cells on kernel ready is bound to the Jupyter
event `kernel_ready.Kernel`.
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@ Name: Initialization cells
Main: main.js
Icon: icon.png
Link: README.md
Description: Add a cell toolbar selector to mark cells as 'initialization' cells. Such initialization cells are run on notebook load, or on clicking the provided button in the main toolbar
Description: |
Add a cell toolbar selector to mark cells as 'initialization' cells. Such
initialization cells can be run by on clicking the provided button in the
main toolbar, or configurably, run automatically on notebook load.
Parameters:
- name: init_cell.run_on_kernel_ready
description: |
Run input cells whenever a kernel_ready.Kernel event is fired. See readme for further details.
input_type: checkbox
default: true
106 changes: 80 additions & 26 deletions src/jupyter_contrib_nbextensions/nbextensions/init_cell/main.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
define([
'jquery',
'base/js/namespace',
'base/js/events'
], function (
$,
IPython,
events
) {
var ctb = IPython.CellToolbar;
define(function (require, exports, module) {
// requirments
var $ = require('jquery');
var dialog = require('base/js/dialog');
var events = require('base/js/events');
var Jupyter = require('base/js/namespace');
var utils = require('base/js/utils');
var CellToolbar = require('notebook/js/celltoolbar').CellToolbar;
var CodeCell = require('notebook/js/codecell').CodeCell;
var ConfigSection = require('services/config').ConfigSection;

var init_cell_ui_callback = ctb.utils.checkbox_ui_generator(
var log_prefix = '[' + module.id + ']';
var options = { // updated from server's config on loading nbextension
run_on_kernel_ready: true,
};

var init_cell_ui_callback = CellToolbar.utils.checkbox_ui_generator(
'Initialisation Cell',
// setter
function(cell, value) {
function (cell, value) {
cell.metadata.init_cell = value;
},
// getter
function(cell) {
function (cell) {
// if init_cell is undefined, it'll be interpreted as false anyway
return cell.metadata.init_cell;
}
);

var run_init_cells = function(){
console.log('init_cell : running all initialization cells');
function run_init_cells () {
console.log(log_prefix, 'running all initialization cells');
var num = 0;
var cells = IPython.notebook.get_cells();
for(var ii in cells) {
var cells = Jupyter.notebook.get_cells();
for (var ii = 0; ii < cells.length; ii++) {
var cell = cells[ii];
if((cell instanceof IPython.CodeCell) && cell.metadata.init_cell === true ) {
if ((cell instanceof CodeCell) && cell.metadata.init_cell === true ) {
cell.execute();
num++;
}
}
console.log('init_cell : finished running ' + num + ' initialization cell' + (num !== 1 ? 's' : ''));
};
console.log(log_prefix, 'finished running ' + num + ' initialization cell' + (num !== 1 ? 's' : ''));
}

var load_ipython_extension = function() {
// register action
var prefix = 'auto';
var action_name = 'run-initialization-cells';
var action = {
Expand All @@ -45,17 +51,65 @@ define([
help_index : 'zz',
handler : run_init_cells
};
var action_full_name = IPython.notebook.keyboard_manager.actions.register(action, action_name, prefix);
var action_full_name = Jupyter.notebook.keyboard_manager.actions.register(action, action_name, prefix);

IPython.toolbar.add_buttons_group([action_full_name]);
// add toolbar button
Jupyter.toolbar.add_buttons_group([action_full_name]);

// Register a callback to create a UI element for a cell toolbar.
ctb.register_callback('init_cell.is_init_cell', init_cell_ui_callback, 'code');
CellToolbar.register_callback('init_cell.is_init_cell', init_cell_ui_callback, 'code');
// Register a preset of UI elements forming a cell toolbar.
ctb.register_preset('Initialisation Cell', ['init_cell.is_init_cell']);
CellToolbar.register_preset('Initialisation Cell', ['init_cell.is_init_cell']);

var base_url = utils.get_body_data('baseUrl');
var conf_section = new ConfigSection('notebook', {'base_url': base_url});
conf_section.load()
.then(
function on_success (new_config_data) {
// update options from server config
$.extend(true, options, new_config_data.init_cell);
// update from metadata
return new Promise(function (resolve, reject) {
function update_options_from_nb_metadata () {
var md_opts = Jupyter.notebook.metadata.init_cell;
if (md_opts !== undefined) {
console.log(log_prefix, 'updating options from notebook metadata:', md_opts);
$.extend(true, options, md_opts);
}
resolve(options);
}
if (Jupyter.notebook) {
update_options_from_nb_metadata();
}
else {
events.on('notebook_loaded.Notebook', update_options_from_nb_metadata);
}
});
}, function on_error (err) {
console.warn(log_prefix, 'error loading options from config:', err);
console.warn(log_prefix, 'Using default options:', options);
})
.then(function () {
if (options.run_on_kernel_ready) {
if (!Jupyter.notebook.trusted) {
dialog.modal({
title : 'Initialization cells in untrusted notebook',
body : 'This notebook is not trusted, so initialization cells will not be automatically run on kernel load. You can still run them manually, though.',
buttons: {'OK': {'class' : 'btn-primary'}},
notebook: Jupyter.notebook,
keyboard_manager: Jupyter.keyboard_manager,
});
return;
}

// whenever a (new) kernel becomes ready, run all initialization cells
events.on('kernel_ready.Kernel', run_init_cells);
if (Jupyter.notebook && Jupyter.notebook.kernel && Jupyter.notebook.kernel.info_reply.status === 'ok') {
// kernel is already ready
run_init_cells();
}
// whenever a (new) kernel becomes ready, run all initialization cells
events.on('kernel_ready.Kernel', run_init_cells);
}
});
};

return {
Expand Down

0 comments on commit 1dcb6e5

Please sign in to comment.