Migrating from IPython3 to Jupyter - startup and custom scripts

1,824 views
Skip to first unread message

Tony Hirst

unread,
Oct 28, 2015, 9:49:52 AM10/28/15
to Project Jupyter
I'm trying to update some build scripts for a virtual machine and have a handful of questions about changes going from IPython 3 notebooks to Jupyter:

1) in my IPython build, I had a py file in a user profile /startup dir that loads some packages, %matplotlb inline etc into each python notebook on startup. Can I continue to use this file? Where should I put it?

2)  in my IPython build, I preinstalled several extensions using a custom.js script  - can I continue to use this or a modified version of it? Where should it go?

3) in my IPython build, I had a load of stuff in a user /custom folder (custom.js to autoload extensions, custom.css to style the notebooks, some image various, export templates etc). Can I continue to use these or a modified version of them? Where do they go? Can I move everything to ~/.jupyter/custom/  and expect it to work? 

thanks
tony

MinRK

unread,
Oct 28, 2015, 10:32:10 AM10/28/15
to jup...@googlegroups.com
On Wed, Oct 28, 2015 at 2:49 PM, Tony Hirst <tony....@gmail.com> wrote:
I'm trying to update some build scripts for a virtual machine and have a handful of questions about changes going from IPython 3 notebooks to Jupyter:

1) in my IPython build, I had a py file in a user profile /startup dir that loads some packages, %matplotlb inline etc into each python notebook on startup. Can I continue to use this file? Where should I put it?

There has been no change in IPython startup files, they continue to work in IPython profiles.
 

2)  in my IPython build, I preinstalled several extensions using a custom.js script  - can I continue to use this or a modified version of it? Where should it go?

Yes, you can. custom.js now lives in ~/.jupyter/custom/custom.js, but its behavior is otherwise the same.
 

3) in my IPython build, I had a load of stuff in a user /custom folder (custom.js to autoload extensions, custom.css to style the notebooks, some image various, export templates etc). Can I continue to use these or a modified version of them? Where do they go? Can I move everything to ~/.jupyter/custom/  and expect it to work? 

Extra Javascript, frontend resources, etc. should generally go in nbextensions folder (see `jupyter nbextension install`). This has not changed from IPython 2 or 3, other than the name for installing them (formerly `ipython install-nbextension`). I'm not sure how you got export templates in the static/custom directory, or how they could be used once there. How did that work, exactly?

-MinRK
 

thanks
tony

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/ff2b7904-7f31-4b5e-ad7b-801c9d8aa03b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tony Hirst

unread,
Oct 28, 2015, 2:32:52 PM10/28/15
to Project Jupyter
Thanks for that...

1) in my IPython build, I had a py file in a user profile /startup dir that loads some packages, %matplotlb inline etc into each python notebook on startup. Can I continue to use this file? Where should I put it?

There has been no change in IPython startup files, they continue to work in IPython profiles.


My understanding was that Jupyter doesn't do user profiles.
What I want to do is just run:

jupyter notebook

and have the startup files preload. (I'm happy to dump the idea of profiles / different setups for different users altogether.)
 
I guess I was hoping for something like:

JUPYTERCONFIGDIR=$(/usr/local/bin/jupyter --config-dir)
STARTUP=$JUPYTERCONFIGDIR/startup
mkdir -p $STARTUP
cp $CUSTOMFILES/startup_script.ipy $STARTUP/startup_script.ipy

Alternatively, a simple worked example showing how to migrate from something like:

ipython3 notebook --profile myprofile --ip 0.0.0.0

to something including:

jupyter notebook

that has the same effect.



 

2)  in my IPython build, I preinstalled several extensions using a custom.js script  - can I continue to use this or a modified version of it? Where should it go?

Yes, you can. custom.js now lives in ~/.jupyter/custom/custom.js, but its behavior is otherwise the same.

Ah - ok..

Hmm..


from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir
jupyter_config_dir()

-> /root/.jupyter

!ls /root/.jupyter/custom/

-> custom.css custom.js [as used w/ ipython custom/ previously]

But it doesn't seem to be picked up at all. Notebooks show a default http://127.0.0.1:8888/custom/custom.css

 
And the custom.js doesn't appear to have done anything?

Not sure if there are any log files I can check anywhere?

 

3) in my IPython build, I had a load of stuff in a user /custom folder (custom.js to autoload extensions, custom.css to style the notebooks, some image various, export templates etc). Can I continue to use these or a modified version of them? Where do they go? Can I move everything to ~/.jupyter/custom/  and expect it to work?
Extra Javascript, frontend resources, etc. should generally go in nbextensions folder (see `jupyter nbextension install`). This has not changed from IPython 2 or 3, other than the name for installing them (formerly `ipython install-nbextension`). I'm not sure how you got export templates in the static/custom directory, or how they could be used once there. How did that work, exactly?

The way I installed the extensions previously was to use a customised custom/custom.js including bits like:

// activate extensions only after Notebook is initialized
require(["base/js/events"], function (events) {
$([IPython.events]).on("app_initialized.NotebookApp", function () {
    /* load your extension here */
    IPython.load_extensions('codefolding/main');
    IPython.load_extensions('rubberband/main'); 
    IPython.load_extensions('exercise/main');
    #....
}); 

I'm basically trying to put together some puppet and shell scripts that will build a VM containing customised jupyter notebooks and a raft of other things that can then be given to remote students and will run for them fully customised from the start.

The export template thing... erm... ah -my mistake - it was actually a py file stored in custom/ that was used by an extension that made a custom nbconvert call.

Tony Hirst

unread,
Oct 28, 2015, 2:54:31 PM10/28/15
to Project Jupyter
So searching around, one suggestion - form a custom theming library (https://github.com/transcranial/jupyter-themer/blob/master/jupythemer/jupythemer.py ) is this... 

jupyter_dir = os.path.dirname(jupyter.__file__) custom_css_filepath = jupyter_dir + '/notebook/static/custom/custom.css' which looks far from ideal?!

MinRK

unread,
Oct 28, 2015, 3:40:20 PM10/28/15
to jup...@googlegroups.com

On Wed, Oct 28, 2015 at 7:32 PM, Tony Hirst <tony....@gmail.com> wrote:

Thanks for that...

1) in my IPython build, I had a py file in a user profile /startup dir that loads some packages, %matplotlb inline etc into each python notebook on startup. Can I continue to use this file? Where should I put it?

There has been no change in IPython startup files, they continue to work in IPython profiles.


My understanding was that Jupyter doesn't do user profiles.
What I want to do is just run:

jupyter notebook

and have the startup files preload. (I'm happy to dump the idea of profiles / different setups for different users altogether.)

Correct, Jupyter (the notebook server) doesn’t use profiles, but IPython (the Python kernel, where your code runs) still does. So anything in your profile_default/startup will still run when you start your IPython kernels.

 
I guess I was hoping for something like:

JUPYTERCONFIGDIR=$(/usr/local/bin/jupyter --config-dir)
STARTUP=$JUPYTERCONFIGDIR/startup
mkdir -p $STARTUP
cp $CUSTOMFILES/startup_script.ipy $STARTUP/startup_script.ipy

There’s no migration because the files in the original locations are still used. No changes are needed. The original startup files still have the same effect they always have.


Alternatively, a simple worked example showing how to migrate from something like:

ipython3 notebook --profile myprofile --ip 0.0.0.0

to something including:

jupyter notebook

that has the same effect.

If you want to use multiple IPython profiles with the notebook, you can do this with kernelspecs. You can make copies of the default IPython kernelspec and add --profile=foo to the argv list that’s used to start the kernel.

What’s important the is that the notebook server configuration shouldn’t be related to the IPython kernel config. You can use many different Kernel configs with one notebook server config, and vice versa.




 

2)  in my IPython build, I preinstalled several extensions using a custom.js script  - can I continue to use this or a modified version of it? Where should it go?

Yes, you can. custom.js now lives in ~/.jupyter/custom/custom.js, but its behavior is otherwise the same.

Ah - ok..

Hmm..


from jupyter_core.paths import jupyter_config_dir, jupyter_data_dir
jupyter_config_dir()

-> /root/.jupyter

!ls /root/.jupyter/custom/

-> custom.css custom.js [as used w/ ipython custom/ previously]

But it doesn't seem to be picked up at all. Notebooks show a default http://127.0.0.1:8888/custom/custom.css

 
And the custom.js doesn't appear to have done anything?

Not sure if there are any log files I can check anywhere?

Hm, might be some caching. You can try running the notebook with --debug, and also try refreshing the custom.css URL in an Incognito tab to clear the cache.


 

3) in my IPython build, I had a load of stuff in a user /custom folder (custom.js to autoload extensions, custom.css to style the notebooks, some image various, export templates etc). Can I continue to use these or a modified version of them? Where do they go? Can I move everything to ~/.jupyter/custom/  and expect it to work?
Extra Javascript, frontend resources, etc. should generally go in nbextensions folder (see `jupyter nbextension install`). This has not changed from IPython 2 or 3, other than the name for installing them (formerly `ipython install-nbextension`). I'm not sure how you got export templates in the static/custom directory, or how they could be used once there. How did that work, exactly?

The way I installed the extensions previously was to use a customised custom/custom.js including bits like:

// activate extensions only after Notebook is initialized
require(["base/js/events"], function (events) {
$([IPython.events]).on("app_initialized.NotebookApp", function () {
    /* load your extension here */
    IPython.load_extensions('codefolding/main');
    IPython.load_extensions('rubberband/main'); 
    IPython.load_extensions('exercise/main');
    #....
}); 

I'm basically trying to put together some puppet and shell scripts that will build a VM containing customised jupyter notebooks and a raft of other things that can then be given to remote students and will run for them fully customised from the start.

That custom.js should work the same, I’m not sure why it isn’t getting picked up. The only difference is where the extensions are installed. Migration should have taken care of moving them to the right place. You can check with ls $(jupyter --data-dir)/nbextensions.


The export template thing... erm... ah -my mistake - it was actually a py file stored in custom/ that was used by an extension that made a custom nbconvert call.
 
-MinRK
 

thanks
tony

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/ff2b7904-7f31-4b5e-ad7b-801c9d8aa03b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Project Jupyter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter+u...@googlegroups.com.
To post to this group, send email to jup...@googlegroups.com.

Tony Hirst

unread,
Oct 30, 2015, 10:13:28 AM10/30/15
to Project Jupyter
So... got it working... the custom.js actually required some tweaks..

First I took a crib from http://stackoverflow.com/a/32528610/454773 which suggested using:

 $([IPython.events]).on("notebook_loaded.Notebook", function () 

rather than $([IPython.events]).on("app_initialized.NotebookApp", function () 

That got the custom.js file to load, but raised an error with IPython.load_extensions() not being recognised.

Then I dumped the custom.js approach altogether in favour of https://github.com/sjpfenninger/ipython-extensions/commit/6ad96d01b1c38f26e5d5115875cc2e1931e51e7c which suggests the following:

By editing ``notebook.json`` manually. By default it is located at ``~/.jupyter/nbconfig/notebook.json``:
{
  "load_extensions": {
     "notify": true,
     "theme_toggle": true
   }
 }

for extensions notify, theme_toggle etc. (constructions ported over from original custom.js like codefolding/main also seem to work.

I am still getting some errors in the browser for many of the extensions (not sure if that's a legacy of previous experiments? caches?):

>Uncaught TypeError: Cannot read property 'load_ipython_extension' of undefined

and also warnings about: 
accessing `MarkdownCell` is deprecated. Use `require("notebook/js/textcell").MarkdownCell`

(not sure where this is? I have some tests of the form if (cell instanceof IPython.MarkdownCell) but I don't think they're throwing the error? certainly, error gets worse if I try if (cell instanceof require("notebook/js/textcell").MarkdownCell )

but even with those warnings/errors, the extensions still seem to work?

I appreciate that the whole notebook thing is made up of moving goalposts, so I'm not sure how long the above will continue to work. I wonder if it would make sense to have a continually maintained "user test" somewhere that has a simple docker script and config files, for example, that demonstrate how to configure a customised notebook with a tiny bit of custom styling, a couple of extensions, a user startup script etc so that technology optimistic educators - rather than developers - can quickly customise a working example for the current Jupyter/IPython build. A change history for files in that project would also provide an audit trail for what needs to change in moving from one version to the next?

Matthias Bussonnier

unread,
Oct 30, 2015, 1:06:41 PM10/30/15
to jup...@googlegroups.com

> On Oct 30, 2015, at 07:13, Tony Hirst <tony....@gmail.com> wrote:
>
> So... got it working... the custom.js actually required some tweaks..
>
> First I took a crib from http://stackoverflow.com/a/32528610/454773 which suggested using:
>
> $([IPython.events]).on("notebook_loaded.Notebook", function ()
>
> rather than $([IPython.events]).on("app_initialized.NotebookApp", function ()
>
> That got the custom.js file to load, but raised an error with IPython.load_extensions() not being recognised.
>
> Then I dumped the custom.js approach altogether in favour of https://github.com/sjpfenninger/ipython-extensions/commit/6ad96d01b1c38f26e5d5115875cc2e1931e51e7c which suggests the following:
>
> By editing ``notebook.json`` manually. By default it is located at ``~/.jupyter/nbconfig/notebook.json``:
> {
> "load_extensions": {
> "notify": true,
> "theme_toggle": true
> }
> }
>
> for extensions notify, theme_toggle etc. (constructions ported over from original custom.js like codefolding/main also seem to work.
>
> I am still getting some errors in the browser for many of the extensions (not sure if that's a legacy of previous experiments? caches?):
>
> >Uncaught TypeError: Cannot read property 'load_ipython_extension' of undefined


can you share the code of your extensions ?
The message also likely give you a file and line number for this error.

>
> and also warnings about:
> accessing `MarkdownCell` is deprecated. Use `require("notebook/js/textcell").MarkdownCell`
>
> (not sure where this is? I have some tests of the form if (cell instanceof IPython.MarkdownCell) but I don't think they're throwing the error? certainly, error gets worse if I try if (cell instanceof require("notebook/js/textcell").MarkdownCell )

The message is partially auto generated. it expect people to know what require is.

You extension should be written in a AMD form with a define statement.


define([your requirements]), function(binding name for your requirement){

... extension code.

})

in you case, likely

define([‘base/js/namespace’,’notebook/js/textcell’], function(IPython, text_mod){

var MarkdownCell = text_mod.MarkdownCell
...
})

in some (rare) cases you can use

define(function(){
var MardownCell = require("notebook/js/textcell").MarkdownCell
})


which will be rewritten as above automatically, one of these case is in the browser REPL.

>
> but even with those warnings/errors, the extensions still seem to work?

IT might be but you might be subject to race condition where it might not work if your machine is under heavy load, or only work if your machine is under heavy load.


>
> I appreciate that the whole notebook thing is made up of moving goalposts, so I'm not sure how long the above will continue to work.
> I wonder if it would make sense to have a continually maintained "user test" somewhere that has a simple docker script and config files, for example, that demonstrate how to configure a customised notebook with a tiny bit of custom styling, a couple of extensions, a user startup script etc so that technology optimistic educators - rather than developers - can quickly customise a working example for the current Jupyter/IPython build. A change history for files in that project would also provide an audit trail for what needs to change in moving from one version to the next?


Yes it would make sens, but it’s extremely sensitive to developer time, and it’s really hard to make a changeling with all the needed change.
Also we are a bit afraid of committing to that as we **know** it will change again in many way. We are not JS developers and me made a lot of bad design decision.

I’ve written some things that are mostly not too wrong on how JS extension work:

https://carreau.gitbooks.io/jupyter-book/content/

Thug it needs update and would greatly benefit from a rewriting and being moved to the official docs.

Hope that’s help.
--
M
> To view this discussion on the web visit https://groups.google.com/d/msgid/jupyter/f3376111-fb84-440d-9c27-a453c2e80212%40googlegroups.com.

Tony Hirst

unread,
Oct 30, 2015, 9:30:35 PM10/30/15
to Project Jupyter
Hi Matthias


can you share the code of your extensions ?

For example: 

define(['base/js/namespace'], function(IPython){

// add button to make codecell activity blue
"using strict";
 
var activityCodeCell = (function() {
/**
* Set codecell to activity 
*  @param {Object} cell current notebook cell
*/
//.addClass('ou_comment_prompt')
 
setActivity = function (cell) {
console.log("Run set activity");
var cp=cell.element;
var prompt = cell.element.find('div.inner_cell');
if (cell instanceof IPython.CodeCell)  {
if (cell.metadata.activity == 'activity') {
//Add coloured background
prompt.addClass('ou_activity_prompt'); 
cp.addClass('ou_activity_outer');
} else {
//Clear cell - remove coloured background
prompt.removeClass('ou_activity_prompt');
cp.removeClass('ou_activity_outer');
}
} else if (cell instanceof IPython.MarkdownCell)  {
if (!('activity' in cell.metadata) || (cell.metadata.activity=='clear')) {
//Clear cell - remove coloured background
cp.removeClass('ou_activity_outer');
prompt.removeClass('ou_activity_prompt')
} else {
if  (cell.metadata.activity == 'activityAns')  {
 //Colour outside, different colour inside
 cp.addClass('ou_activity_outer')
 prompt.removeClass('ou_activity_outer');
 prompt.addClass('ou_activity_prompt')
} else if  (cell.metadata.activity == 'activity')  {
 //Similar colour outside and inside
 cp.addClass('ou_activity_outer')
 prompt.addClass('ou_activity_outer')
}
}  
}
};

function toggleActivity() {
//the cell.metadata.activity=='clear' is a legacy check
console.log("Run toggle activity");
var cell = IPython.notebook.get_selected_cell();
if ((cell instanceof IPython.CodeCell)) {
if (!('activity' in cell.metadata) || (cell.metadata.activity=='clear')){
cell.metadata.activity = 'activity'; 
} else { //if (cell.metadata.activity=='activity') {
//cell.metadata.activity = 'clear'
delete cell.metadata.activity
}
setActivity(cell);
} else if (cell instanceof IPython.MarkdownCell) {
if (!('activity' in cell.metadata) || (cell.metadata.activity=='clear')) {
cell.metadata.activity = 'activity';
} else if (cell.metadata.activity == 'activity' ) {
  cell.metadata.activity = 'activityAns'
} else if (cell.metadata.activity == 'activityAns'){
  //cell.metadata.activity='clear'
  delete cell.metadata.activity
}
setActivity(cell);
}
};

 
/**
* Add run control buttons to toolbar and initialize codecells
*/
IPython.toolbar.add_buttons_group([
{
id : 'activity_codecell',
label : 'Toggle activity codecell',
icon : 'fa-tasks',
callback : toggleActivity
}
 ]);
 
function oustyle_notebook(){     
console.log("Run oustyle_notebook");    
/* loop through notebook and set style of activity cells defined in metadata */
var cells = IPython.notebook.get_cells();
for(var i in cells){
var cell = cells[i];
if ((cell instanceof IPython.CodeCell) || (cell instanceof IPython.MarkdownCell) ) {
if ('activity' in cell.metadata)
setActivity(cell);
}
 
};
}
 
//$([IPython.events]).on('create.Cell',create_cell);    
$([IPython.events]).on('notebook_loaded.Notebook',oustyle_notebook());
})();

})




The message also likely give you a file and line number for this error.


The warning is to elsewhere...?

Run oustyle_notebook
27  namespace.js:21 accessing `MarkdownCell` is deprecated. Use `require("notebook/js/textcell").MarkdownCell`
utils.js:21 Loaded extension: jupyter_activityCodeCell
utils.js:23 Uncaught TypeError: Cannot read property 'load_ipython_extension' of undefined

 

 
in you case, likely

define([‘base/js/namespace’,’notebook/js/textcell’], function(IPython, text_mod){

    var MarkdownCell = text_mod.MarkdownCell
    ...
})

what does text_mod relate to?


IT might be but you might be subject to race condition where it might not work if your machine is under heavy load, or only work if your machine is under heavy load.


ok - I have encountered races before but thought I'd sorted those...
 

Yes it would make sens, but it’s extremely sensitive to developer time, and it’s really hard to make a changeling with all the needed change.


I appreciate that, but as someone trying to promote the use of notebooks in an institution that supports distance education students, we develop courses over an 18 month period and have software freezes a couple of months before student use, which could then last up to a year.  Trying to update software on a 6 monthly basis during production, and now trying to fix a final release, creates considerable problems when trying to get stuff working, especially without internal developer support, when there are no current references.... (as has been pointed out to me before, stuff on the web on stack overflow and in old github issue threads is often flakey - not least when the underlying model is also subject to change.

I hugely appreciate all the work that's going on in the Jupyter project, but for those of us not active in the development conversations (and who are not developers), trying to find ways of using the notebooks and customising them for student use, it can also be a hugely time consuming and frustrating experience that a working reference to base things on would mitigate!;-) (Once again, I don't want to come across as negative - just saying that enthusiastic users also suffer from time constraints and error message pain!;-)
 
Also we are a bit afraid of committing to that as we **know** it will change again in many way. We are not JS developers and me made a lot of bad design decision.

Which maybe compounds user issues when there are no exemplar, simple working examples, no matter how horrible the js?! (I shared mine above - I make no claims about it other that it seems to do what I need. I was hoping that I could just do a function working proof of concept and our institutional devs would take it as spec they could build something of production quality around, but it's not worked out like that!)
 
I’ve written some things that are mostly not too wrong on how JS extension work:

https://carreau.gitbooks.io/jupyter-book/content/

Thug it needs update and would greatly benefit from a rewriting and being moved to the official docs.

Hope that’s help.

Thanks... if I can find ways of contributing back too, even in terms of simple write ups that could act as a starting point for further docs, I will.. time allowing!

tony

Jess Hamrick

unread,
Oct 30, 2015, 9:45:33 PM10/30/15
to jup...@googlegroups.com
Hi Tony,

Sorry that it’s been tough to get your extension working properly — the documentation on extensions definitely could be better, and things have changed a fair amount in the last year with how extensions are loaded. I think there are two things with the code you sent. First,

$([IPython.events]).on('notebook_loaded.Notebook',oustyle_notebook());

You probably don’t want to actually call oustyle_notebook here, just pass the function name.

Second, the reason why you are getting the error "Uncaught TypeError: Cannot read property 'load_ipython_extension' of undefined” is because the notebook expects your extension to have a function called “load_ipython_extension”. If you wrap your call to registering the callback for the notebook_loaded.Notebook event in a function called “load_extension” and then add:

    return {
        'load_ipython_extension': load_extension
    };

to your code (inside the define statement), then I believe that should fix it. You can take a look at the nbgrader create_assignment extension which does this:


I definitely think it would be helpful to have a working example somewhere, though as Matthias said, it’s really difficult to keep something like that up to date. A more reliable approach might be in the documentation (e.g. in the Jupyter book Matthias has been working on) to link to a few extensions that are known to be actively maintained that could be good starting points.

Cheers,
Jess


Matthias Bussonnier

unread,
Oct 31, 2015, 12:56:30 PM10/31/15
to jup...@googlegroups.com
Hi Tony,

On Oct 30, 2015, at 18:30, Tony Hirst <tony....@gmail.com> wrote:

Hi Matthias

can you share the code of your extensions ?



TL: DR; 

Here is the code of your extension fixed. 

https://gist.github.com/Carreau/2ec80dcb42edadac11b5/revision


One of the issue was confusion with event of Application loading, and notebook loading. 
App  loading append only once, Notebook loading can happened many time per App load (like revert to checkpoint)..
even Jess in her next mail got confused I think in between what your code was tying to do, and what to call when

Ask me if you want more details on why I did the changes I did. 




The message also likely give you a file and line number for this error.


The warning is to elsewhere...?

Run oustyle_notebook
27  namespace.js:21 accessing `MarkdownCell` is deprecated. Use `require("notebook/js/textcell").MarkdownCell`
utils.js:21 Loaded extension: jupyter_activityCodeCell
utils.js:23 Uncaught TypeError: Cannot read property 'load_ipython_extension' of undefined


Thanks that helps. 



 

 
in you case, likely

define([‘base/js/namespace’,’notebook/js/textcell’], function(IPython, text_mod){

    var MarkdownCell = text_mod.MarkdownCell
    ...
})

what does text_mod relate to?


text_mod is the variable that expose the 'notebook/js/textcell’ module.

to use a “python like” example:

import AAA.BBB as X
import CCC.DDD as Y

the Js equivalent is

define([‘AAA.BBB’, ‘CCC.DDD’]), function(X,Y){

})

Yes that’s confusing, but that’s how it is (it’s improving though but a new & better syntax is not available everywhere)





IT might be but you might be subject to race condition where it might not work if your machine is under heavy load, or only work if your machine is under heavy load.


ok - I have encountered races before but thought I'd sorted those...
 

Yes it would make sens, but it’s extremely sensitive to developer time, and it’s really hard to make a changeling with all the needed change.




I appreciate that, but as someone trying to promote the use of notebooks in an institution that supports distance education students, we develop courses over an 18 month period and have software freezes a couple of months before student use, which could then last up to a year.  Trying to update software on a 6 monthly basis during production, and now trying to fix a final release, creates considerable problems when trying to get stuff working, especially without internal developer support, when there are no current references.... (as has been pointed out to me before, stuff on the web on stack overflow and in old github issue threads is often flakey - not least when the underlying model is also subject to change.

We know, the issue is that none of us where real js developers, so the technical solution we give for user to load extension are often
not relying on strong technical infrastructure. We are also discovering a lot what user want to customize afterward, and realize  how we
should have built things. 

It’s really difficult to track all the discussion and actually fix wrong comments.



I hugely appreciate all the work that's going on in the Jupyter project, but for those of us not active in the development conversations (and who are not developers), trying to find ways of using the notebooks and customising them for student use, it can also be a hugely time consuming and frustrating experience that a working reference to base things on would mitigate!;-) (Once again, I don't want to come across as negative - just saying that enthusiastic users also suffer from time constraints and error message pain!;-)

We’ll try to do better, the new refactoring should get documentation that means API will stabilize. 
You do the right things by asking, and sharing the extension you did.

 
Also we are a bit afraid of committing to that as we **know** it will change again in many way. We are not JS developers and me made a lot of bad design decision.

Which maybe compounds user issues when there are no exemplar, simple working examples, no matter how horrible the js?! (I shared mine above - I make no claims about it other that it seems to do what I need. I was hoping that I could just do a function working proof of concept and our institutional devs would take it as spec they could build something of production quality around, but it's not worked out like that!)



Can give you more example. Not all are done in a correct way, but some are, and it’s easier to find things in a central place. 
(The  organization is not endorsed by the IPython or Jupyter project so nothing official here)


 
I’ve written some things that are mostly not too wrong on how JS extension work:

https://carreau.gitbooks.io/jupyter-book/content/

Thug it needs update and would greatly benefit from a rewriting and being moved to the official docs.

Hope that’s help.

Thanks... if I can find ways of contributing back too, even in terms of simple write ups that could act as a starting point for further docs, I will.. time allowing!

We always appreciate help, even just indication when something is unclear. 

Thanks, 
-- 
M

Tony Hirst

unread,
Nov 1, 2015, 3:35:52 PM11/1/15
to Project Jupyter
Hi Matthias

Thanks for that. Will read through the changes and try to apply similar ones to my other extensions...

Once again, I'm hugely impressed by the work you're all doing. I just hope we can do it justice with the way we're using the notebooks to support teachin'n'learnin':-)

Will try to feed in constructive comments and issues where and when I can. Is this group as good a place as any (my comments may be not quite well-specified enough to raise as github issues!)

tony

Matthias Bussonnier

unread,
Nov 1, 2015, 5:57:32 PM11/1/15
to jup...@googlegroups.com
Hi Tony,

We have github issues that are much less constructive than here, and
github issues allow people to subscribe and unsubscribe
on each thread individually. Also markdown is much easier to write or
refer to code.

Also if a mail thread get unresponded we will likely not come back to
it, a github issue always have a chance to be worked on later.

So don't hesitate to open github issues (up to you of course).

--
M
> --
> You received this message because you are subscribed to the Google Groups
> "Project Jupyter" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jupyter+u...@googlegroups.com.
> To post to this group, send email to jup...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/jupyter/2ee2766a-5347-4349-930b-cfa0f957666a%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages