Skip to content

Commit

Permalink
Bootstrap structure for a widget examples repo
Browse files Browse the repository at this point in the history
  • Loading branch information
jtpio committed Mar 15, 2021
1 parent 3721f28 commit 49b0345
Show file tree
Hide file tree
Showing 64 changed files with 26,113 additions and 26 deletions.
154 changes: 154 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
name: CI

on:
push:
branches: [ main ]
pull_request:
branches: "*"

jobs:
build_extensions:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
example:
- hello-world
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Path filter
id: filter
uses: dorny/paths-filter@v2
with:
filters: |
extension:
- '${{ matrix.example }}/**'
- name: Cache lerna
if: steps.filter.outputs.extension == 'true'
uses: actions/cache@v2
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-lerna-${{ hashFiles('**/package.json') }}
restore-keys: |
${{ runner.os }}-lerna-
- name: Check config files
if: steps.filter.outputs.extension == 'true'
run: |
diff hello-world/tsconfig.json ${EXAMPLE_FOLDER}/tsconfig.json
diff hello-world/.eslintignore ${EXAMPLE_FOLDER}/.eslintignore
diff hello-world/.eslintrc.js ${EXAMPLE_FOLDER}/.eslintrc.js
diff hello-world/.gitignore ${EXAMPLE_FOLDER}/.gitignore
env:
EXAMPLE_FOLDER: ${{ matrix.example }}
shell: bash
- name: Install node
if: steps.filter.outputs.extension == 'true'
uses: actions/setup-node@v2
with:
node-version: "12.x"
- name: Install Python
if: steps.filter.outputs.extension == 'true'
uses: actions/setup-python@v2
with:
python-version: "3.7"
architecture: "x64"
- name: Get pip cache dir
if: steps.filter.outputs.extension == 'true'
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
shell: bash
- name: Cache pip
if: steps.filter.outputs.extension == 'true'
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip-${{ hashFiles('**/environment.yml') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install the Python dependencies
if: steps.filter.outputs.extension == 'true'
run: |
python -m pip install --upgrade pip jupyter_packaging~=0.7.9 jupyterlab~=3.0
- name: Install the NPM dependencies
if: steps.filter.outputs.extension == 'true'
run: |
cd ${EXAMPLE_FOLDER}
yarn
env:
EXAMPLE_FOLDER: ${{ matrix.example }}
shell: bash
- name: Lint the files
if: steps.filter.outputs.extension == 'true'
run: |
cd ${EXAMPLE_FOLDER}
jlpm run eslint:check
env:
EXAMPLE_FOLDER: ${{ matrix.example }}
shell: bash
- name: Build and check by extension
if: steps.filter.outputs.extension == 'true'
run: |
cd ${EXAMPLE_FOLDER}
pip install -e .
jupyter labextension list 2>&1 | grep -ie "@jupyter-widget-examples/*.*OK"
python -m jupyterlab.browser_check
pip uninstall -y $(python setup.py --name)
env:
EXAMPLE_FOLDER: ${{ matrix.example }}
shell: bash

build_all:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Cache lerna
uses: actions/cache@v2
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-lerna-${{ hashFiles('**/package.json') }}
restore-keys: |
${{ runner.os }}-lerna-
- name: Install node
uses: actions/setup-node@v2
with:
node-version: "12.x"
- name: Install Python
uses: actions/setup-python@v2
with:
python-version: "3.7"
architecture: "x64"
- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
shell: bash
- name: Cache pip
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip-${{ hashFiles('**/environment.yml') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install the Python dependencies
run: python -m pip install jupyter_packaging~=0.7.9 jupyterlab~=3.0 pytest pytest-check-links
- name: Bootstrap the jlpm deps
run: jlpm
- name: Build all the extensions
run: |
jlpm build-ext
jlpm lint:check
jlpm install-ext
# Check links as last step as new tutorial may set links not yet valid (like file not yet in master)
pytest --check-links
18 changes: 16 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
*.ipynb_checkpoints
*.swp
.DS_Store
*.bundle.*
lib/
node_modules/
*.egg-info/
.ipynb_checkpoints
*.tsbuildinfo
*.lock
__pycache__

# Ensure embedme does not run on node_modules README.md files.
**/node_modules/**/README.md

static
labextension
nbextension
6 changes: 6 additions & 0 deletions .lintstagedrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}": [
"prettier --write",
"git add"
]
}
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
**/node_modules
**/lib
**/package.json
**/labextension
**/.pytest_cache
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"singleQuote": true
}
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BSD 3-Clause License

Copyright (c) 2020, Project Jupyter Contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
97 changes: 73 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,80 @@
# What and why
Documentation on how to make a custom jupyter widget. The docs are currently pretty limited on details with creating a custom widget (being worked on - see [here](https://github.com/jupyter-widgets/ipywidgets/issues/2731)). This is probably because its really hard to write good documentation. So here I take the opposite approach, whenever I learn something about widgets I try to write about it here immediately (not worrying about writing it well). So I make no guarantees as to intelligibility or even correctness (though I strive for both). When I don't have the time/motivation to open the files and actually write things down I will put whatever links and scattered thoughts into an [issue](https://github.com/ianhi/custom-ipywidget-howto/issues) so it may be helpful to look at those as well.

# Good resources
To learn widgets I recommend the following resources outside this:
1. [Low Level Widget Tutorial](https://github.com/jupyter-widgets/ipywidgets/blob/master/docs/source/examples/Widget%20Low%20Level.ipynb)
- [Rendered on readthedocs - less good](https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Low%20Level.html)
- The images aren't rendering properly for some reason see [this issue](https://github.com/jupyter-widgets/ipywidgets/issues/2908)
2. Look at widgets made by the people at QuantStack - they know the most about making widgets. Some widgets I have found to be particularly helpful are:
- [ipympl](https://github.com/matplotlib/ipympl)
- [ipycanvas](https://github.com/martinRenou/ipycanvas)
- [ipycytoscape](https://github.com/quantstack/ipycytoscape)
3. [QuantStack Gitter](https://gitter.im/QuantStack/Lobby)
- They've been very helpful everytime I've asked a question
## Starting making a widget
When you want to start making a widget start from https://github.com/jupyter-widgets/widget-ts-cookiecutter
# Custom Jupyter Widgets by Example

[![Github Actions Status](https://github.com/jupyter-widgets/widget-examples/workflows/CI/badge.svg)](https://github.com/jupyter-widgets/widget-examples/actions?query=workflow%3ACI)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jupyterlab/extension-examples/master?urlpath=lab)

The goal of this repository is to show how to develop custom [Jupyter Widgets](https://github.com/jupyter-widgets/widget-examples), presented as short tutorial series.

## Getting Started

```bash
# clone the repository
git clone https://github.com/jupyter-widgets/widget-examples.git jupyter-widget-examples
```

## Develop by Examples

Start with the [Hello World](hello-world) and then jump to the topic you are interested in.

- [Hello World](hello-world)

### [Hello World](hello-world)

Set up the development environment and print to the console.

TODO: add screenshot

## Develop and Use the Examples

### Build and Install all the widgets at once

```bash
# TODO
```

### Build and Install one Example

Go to the example directory you want to install, e.g. `cd ./hello-world`, and run the following commands:

```bash
# TODO
```

### Change the Sources

If you want to develop and iterate on the code, you will need to open 2 terminals.

In terminal 1, go to the extension folder and run the following:

```bash
yarn watch
```

Then in terminal 2, start JupyterLab with the watch flag:

```bash
pip install cookiecutter
cookiecutter https://github.com/jupyter-widgets/widget-ts-cookiecutter.git
jupyter lab --watch
```
It's also nice to add linting for the typescript side of things. See this PR https://github.com/jupyter-widgets/widget-ts-cookiecutter/pull/78 for adding it.

# Contributing
From there, you can change your extension source code, it will be recompiled,
and you can refresh your browser to see your changes.

We are using [embedme](https://github.com/zakhenry/embedme) to embed code snippets into the markdown READMEs. If you make changes to the source code, ensure you update the README and run `jlpm embedme` from the root of the repository to regenerate the READMEs.

## Install a Custom Jupyter Widget

Once your widget is published on [pypi.org](https://pypi.org/) (outside of this scope), you can install it
with the following command:

```bash
pip install <published_widget>
```

If you find something wrong or figure out something that isn't in here you should totally open an issue or a PR and I'll include it.
## About JupyterLab

# shameless plugs
TODO

1. If you want to help make a widget I'm partway through making an image segmentation widget and mostly writing stuff here as I discover them things along the way. If that's interesting feel free to help with it and maybe we can both learn more :) https://github.com/ianhi/ipysegment
## Community Guidelines and Code of Conduct

2. I'm also trying to build better tools for looking at microscopy data in jupyter. This will likely involve making custom widgets https://github.com/ianhi/jupyter-microscopy this would be another low stakes widget playground.
This examples repository is a Jupyter project and follows the Jupyter
[Community Guides and Code of Conduct](https://jupyter.readthedocs.io/en/latest/community/content-community.html).
12 changes: 12 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: jupyter-widget-examples
channels:
- conda-forge
dependencies:
- ipywidgets=7.6,<8
- jupyter-packaging>=0.7.9,<0.8.0
- jupyterlab=3
- nodejs
- pytest
- pytest-check-links
- python=3
- yarn
2 changes: 2 additions & 0 deletions hello-world/.coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
omit = hello_world/tests/*
5 changes: 5 additions & 0 deletions hello-world/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dist
coverage
**/*.d.ts
tests
28 changes: 28 additions & 0 deletions hello-world/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended'
],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.eslint.json',
sourceType: 'module'
},
plugins: ['@typescript-eslint'],
rules: {
'@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/quotes': [
'error',
'single',
{ avoidEscape: true, allowTemplateLiterals: false }
],
curly: ['error', 'all'],
eqeqeq: 'error',
'prefer-arrow-callback': 'error'
}
};
Loading

0 comments on commit 49b0345

Please sign in to comment.