Skip to content

Commit 276d6d6

Browse files
committed
Initial commit
0 parents  commit 276d6d6

File tree

19 files changed

+499
-0
lines changed

19 files changed

+499
-0
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.py[cod]
2+
3+
# Cookiecutter
4+
output/
5+
bower_components

README.md

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
Cookiecutter template for custom Jupyter widget project
2+
=======================================================
3+
4+
[![Documentation Status](https://readthedocs.org/projects/ipywidgets/badge/?version=latest)](http://ipywidgets.readthedocs.org/en/latest/?badge=latest)
5+
[![Join the chat at https://gitter.im/ipython/ipywidgets](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ipython/ipywidgets?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6+
7+
A [cookiecutter](https://github.com/audreyr/cookiecutter) template for a custom
8+
Jupyter widget project.
9+
10+
Goals
11+
-----
12+
13+
This project is meant to help custom widget authors get started with the
14+
packaging and the distribution of Jupyter interactive widgets.
15+
16+
It produces a project for a Jupyter interactive widget library following the
17+
current best practices for using interactive widgets. An implementation for a
18+
placeholder "Hello World" widget is provided.
19+
20+
More Advanced Examples
21+
----------------------
22+
23+
Popular widget libraries such as
24+
[bqplot](https://github.com/bloomberg/bqplot),
25+
[pythreejs](https://github.com/jovyan/pythreejs) and
26+
[ipyleaflet](https://github.com/ellisonbg/ipyleaflet)
27+
follow exactly the same template and directory structure. They can serve as
28+
more advanced examples of usage of the Jupyter widget infrastructure.
29+
30+
Usage
31+
-----
32+
33+
You first need to get cookiecutter
34+
35+
$ pip install cookiecutter
36+
37+
Then you can run
38+
39+
$ cookiecutter https://github.com/jupyter/widget-cookiecutter.git
40+
41+
You will be asked for basic information about your project. The required fields
42+
are:
43+
44+
- `author_name`: your name or the name of your organization,
45+
- `author_email`: the contact email for the project,
46+
- `github_project_name`: name of the GitHub repository,
47+
- `github_organization_name`: name of the GitHub user or organization holding
48+
the repository,
49+
- `python_package_name`: name of the Python backend package.
50+
- `npm_package_name`: name for the npm package holding the JavaScript
51+
implementation.
52+
- `project_short_description` : a short description for the project that will
53+
be used for both the back-end and front-end packages.

cookiecutter.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"author_name": "",
3+
"author_email": "",
4+
"github_project_name": "jupyter-widget-example",
5+
"github_organization_name": "jupyter",
6+
"python_package_name": "ipywidgetexample",
7+
"npm_package_name": "jupyter-widget-example",
8+
"project_short_description": "A Custom Jupyter Widget Library"
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
*.egg-info/
2+
.ipynb_checkpoints/
3+
dist/
4+
build/
5+
*.py[cod]
6+
node_modules/
7+
8+
# Compiled javascript
9+
{{ cookiecutter.python_package_name }}/static/
10+
11+
# OS X
12+
.DS_Store
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
recursive-include {{ cookiecutter.python_package_name }}/static *.*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{{ cookiecutter.github_project_name }}
2+
===============================
3+
4+
{{ cookiecutter.project_short_description }}
5+
6+
Installation
7+
------------
8+
9+
To install use pip:
10+
11+
$ pip install {{ cookiecutter.python_package_name }}
12+
$ jupyter nbextension enable --py --sys-prefix {{ cookiecutter.python_package_name }}
13+
14+
15+
For a development installation (requires npm),
16+
17+
$ git clone https://github.com/{{ cookiecutter.github_organization_name }}/{{ cookiecutter.github_project_name }}.git
18+
$ cd {{ cookiecutter.python_package_name }}
19+
$ pip install -e .
20+
$ jupyter nbextension install --py --symlink --user {{ cookiecutter.python_package_name }}
21+
$ jupyter nbextension enable --py --user {{ cookiecutter.python_package_name }}
22+
23+
The project also contains a conda recipe. The resulting conda package can be
24+
installed with the `conda install` command. Unlike when installing from pypi,
25+
the notebook extension is automatically enabled.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
- To release a new version of {{ cookiecutter.python_package_name }} on PyPI:
2+
3+
Update _version.py (set release version, remove 'dev')
4+
git add and git commit
5+
python setup.py sdist upload
6+
python setup.py bdist_wheel upload
7+
git tag -a X.X.X -m 'comment'
8+
Update _version.py (add 'dev' and increment minor)
9+
git add and git commit
10+
git push
11+
git push --tags
12+
13+
- To release a new version of {{ cookiecutter.npm_package_name }} on NPM:
14+
15+
# nuke the `dist` and `node_modules`
16+
git clean -fdx
17+
npm install
18+
npm publish
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{{ cookiecutter.project_short_description }}
2+
3+
Package Install
4+
---------------
5+
6+
**Prerequisites**
7+
- [node](http://nodejs.org/)
8+
9+
```bash
10+
npm install --save {{ cookiecutter.npm_package_name }}
11+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "{{ cookiecutter.npm_package_name}}",
3+
"version": "0.0.1",
4+
"description": "{{ cookiecutter.project_short_description }}",
5+
"author": "{{ cookiecutter.author_name }}",
6+
"main": "src/index.js",
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/{{ cookiecutter.github_organization_name }}/{{ cookiecutter.github_project_name }}.git"
10+
},
11+
"scripts": {
12+
"prepublish": "webpack",
13+
"test": "echo \"Error: no test specified\" && exit 1"
14+
},
15+
"devDependencies": {
16+
"json-loader": "^0.5.4",
17+
"webpack": "^1.12.14"
18+
},
19+
"dependencies": {
20+
"jupyter-js-widgets": "^1.1.1",
21+
"underscore": "^1.8.3"
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Entry point for the npmcdn bundle containing custom model definitions.
2+
//
3+
// It differs from the notebook bundle in that it does not need to define a
4+
// dynamic baseURL for the static assets and may load some css that would
5+
// already be loaded by the notebook otherwise.
6+
7+
// Export everything from example.js and the npm package version number.
8+
module.exports = require('./example.js');
9+
module.exports['version'] = require('../package.json').version;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var widgets = require('jupyter-js-widgets');
2+
var _ = require('underscore');
3+
4+
5+
// Custom Model. Custom widgets models must at least provide default values
6+
// for model attributes, including `_model_name`, `_view_name`, `_model_module`
7+
// and `_view_module` when different from the base class.
8+
//
9+
// When serialiazing entire widget state for embedding, only values different from the
10+
// defaults will be specified.
11+
var HelloModel = widgets.DOMWidgetModel.extend({
12+
defaults: _.extend({}, widgets.DOMWidgetModel.prototype.defaults, {
13+
_model_name : 'HelloModel',
14+
_view_name : 'HelloView',
15+
_model_module : '{{ cookiecutter.npm_package_name }}',
16+
_view_module : '{{ cookiecutter.npm_package_name }}',
17+
value : 'Hello World'
18+
})
19+
});
20+
21+
22+
// Custom View. Renders the widget model.
23+
var HelloView = widgets.DOMWidgetView.extend({
24+
render: function() {
25+
this.value_changed();
26+
this.model.on('change:value', this.value_changed, this);
27+
},
28+
29+
value_changed: function() {
30+
this.el.textContent = this.model.get('value');
31+
}
32+
});
33+
34+
35+
module.exports = {
36+
HelloModel : HelloModel,
37+
HelloView : HelloView
38+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This file contains the javascript that is run when the notebook is loaded.
2+
// It contains some requirejs configuration and the `load_ipython_extension`
3+
// which is required for any notebook extension.
4+
5+
// Configure requirejs
6+
if (window.require) {
7+
window.require.config({
8+
map: {
9+
"*" : {
10+
"{{ cookiecutter.npm_package_name }}": "nbextensions/{{ cookiecutter.npm_package_name }}/index",
11+
"jupyter-js-widgets": "nbextensions/jupyter-js-widgets/extension"
12+
}
13+
}
14+
});
15+
}
16+
17+
// Export the required load_ipython_extention
18+
module.exports = {
19+
load_ipython_extension: function() {}
20+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Entry point for the notebook bundle containing custom model definitions.
2+
//
3+
// Setup notebook base URL
4+
//
5+
// Some static assets may be required by the custom widget javascript. The base
6+
// url for the notebook is not known at build time and is therefore computed
7+
// dynamically.
8+
__webpack_public_path__ = document.querySelector('body').getAttribute('data-base-url') + 'nbextensions/example/';
9+
10+
11+
// Export everything from example and the npm package version number.
12+
module.exports = require('./example.js');
13+
module.exports['version'] = require('../package.json').version;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
var version = require('./package.json').version;
2+
3+
// Custom webpack loaders are generally the same for all webpack bundles, hence
4+
// stored in a separate local variable.
5+
var loaders = [
6+
{ test: /\.json$/, loader: 'json-loader' },
7+
];
8+
9+
10+
module.exports = [
11+
{// Notebook extension
12+
//
13+
// This bundle only contains the part of the JavaScript that is run on
14+
// load of the notebook. This section generally only performs
15+
// some configuration for requirejs, and provides the legacy
16+
// "load_ipython_extension" function which is required for any notebook
17+
// extension.
18+
//
19+
entry: './src/extension.js',
20+
output: {
21+
filename: 'extension.js',
22+
path: '../{{ cookiecutter.python_package_name }}/static',
23+
libraryTarget: 'amd'
24+
}
25+
},
26+
{// Bundle for the notebook containing the custom widget views and models
27+
//
28+
// This bundle contains the implementation for the custom widget views and
29+
// custom widget.
30+
// It must be an amd module
31+
//
32+
entry: './src/index.js',
33+
output: {
34+
filename: 'index.js',
35+
path: '../{{ cookiecutter.python_package_name }}/static',
36+
libraryTarget: 'amd'
37+
},
38+
devtool: 'source-map',
39+
module: {
40+
loaders: loaders
41+
},
42+
externals: ['jupyter-js-widgets']
43+
},
44+
{// Embeddable {{ cookiecutter.npm_package_name }} bundle
45+
//
46+
// This bundle is generally almost identical to the notebook bundle
47+
// containing the custom widget views and models.
48+
//
49+
// The only difference is in the configuration of the webpack public path
50+
// for the static assets.
51+
//
52+
// It will be automatically distributed by npmcdn to work with the static
53+
// widget embedder.
54+
//
55+
// The target bundle is always `dist/index.js`, which is the path required
56+
// by the custom widget embedder.
57+
//
58+
entry: './src/embed.js',
59+
output: {
60+
filename: 'index.js',
61+
path: './dist/',
62+
libraryTarget: 'amd',
63+
publicPath: 'https://npmcdn.com/{{ cookiecutter.npm_package_name }}@' + version + '/dist/'
64+
},
65+
devtool: 'source-map',
66+
module: {
67+
loaders: loaders
68+
},
69+
externals: ['jupyter-js-widgets']
70+
}
71+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[bdist_wheel]
2+
universal=1

0 commit comments

Comments
 (0)