Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use copier #305

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:

- name: Install dependencies
run: |
python -m pip install cookiecutter
python -m pip install copier>=7.1.0 jinja2-time

- name: Create pure frontend extension
env:
Expand All @@ -39,8 +39,9 @@ jobs:
run: |
set -eux
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json, os; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']=d['kind'][0]; d['labextension_name']=os.getenv('NAME'); cookiecutter('.', extra_context=d, no_input=True)"
pushd ${PYNAME}
mkdir ${NAME}
python -c "from copier import run_auto; import json, os; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']=d['kind'][0]; d['labextension_name']=os.getenv('NAME'); run_all('.', os.getenv('NAME'), data=d, vcs_ref='HEAD')"
pushd ${NAME}
python -m pip install "jupyterlab>=4.0.0b0,<5"
jlpm
jlpm stylelint-config-prettier-check
Expand Down Expand Up @@ -73,13 +74,14 @@ jobs:

- name: Install dependencies
run: |
python -m pip install cookiecutter
python -m pip install copier>=7.1.0 jinja2-time

- name: Create pure frontend extension
run: |
set -eux
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']=d['kind'][0]; d['test']='n'; cookiecutter('.', extra_context=d, no_input=True)"
mkdir myextension
python -c "from copier import run_auto; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']=d['kind'][0]; d['test']='n'; run_all('.', 'myextension', data=d, vcs_ref='HEAD')"
pushd myextension
pip install "jupyterlab>=4.0.0b0,<5"
jlpm
Expand Down Expand Up @@ -112,13 +114,14 @@ jobs:

- name: Install dependencies
run: |
python -m pip install cookiecutter
python -m pip install copier>=7.1.0 jinja2-time

- name: Create pure frontend extension
run: |
set -eux
mkdir myextension
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']=d['kind'][0]; d['has_settings']='y'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from copier import run_auto; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']=d['kind'][0]; d['has_settings']='y'; run_all('.', 'myextension', data=d, vcs_ref='HEAD')"
pushd myextension
pip install "jupyterlab>=4.0.0b0,<5"
jlpm
Expand Down Expand Up @@ -155,12 +158,14 @@ jobs:

- name: Install dependencies
run: |
python -m pip install cookiecutter build
python -m pip install "copier>=7.1.0" jinja2-time build

- name: Create server extension pip install
run: |
set -eux
mkdir myextension
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from copier import run_auto; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; run_all('.', 'myextension', data=d, vcs_ref='HEAD')"
cd myextension
cat pyproject.toml
pip install .
Expand All @@ -185,8 +190,10 @@ jobs:

- name: Create server extension pip develop
run: |
set -eux
mkdir myextension
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from copier import run_auto; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; run_all('.', 'myextension', data=d, vcs_ref='HEAD')"
cd myextension
python -m pip install -e .[test]
python -m pip install "jupyterlab>=4.0.0b0,<5"
Expand Down Expand Up @@ -216,12 +223,14 @@ jobs:
jupyter labextension uninstall myextension
python -m pip uninstall -y myextension jupyterlab

python -c "import shutil; shutil.rmtree('myextension')"
rm -rf myextension

- name: Install server extension from a tarball
run: |
set -eux
mkdir myextension
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from copier import run_auto; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; run_all('.', 'myextension', data=d, vcs_ref='HEAD')"
cd myextension
python -m pip install "jupyterlab>=4.0.0b0,<5"
jupyter lab clean --all
Expand Down Expand Up @@ -316,8 +325,9 @@ jobs:
- name: Create pure frontend extension
run: |
set -eux
mkdir mytheme
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='theme'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from copier import run_auto; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='theme'; run_all('.', 'mytheme', data=d, vcs_ref='HEAD')"
pushd mytheme
python -m pip install "jupyterlab>=4.0.0b0,<5"
jlpm
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ node_modules/
*.tsbuildinfo
.eslintcache
.stylelintcache
{{cookiecutter.python_name}}/static

# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python
Expand Down
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
# JupyterLab extension-cookiecutter-ts
# JupyterLab extension template

[![Github Actions Status](https://github.com/jupyterlab/extension-cookiecutter-ts/workflows/CI/badge.svg)](https://github.com/jupyterlab/extension-cookiecutter-ts/actions/workflows/main.yml)

A [cookiecutter](https://github.com/audreyr/cookiecutter) template for creating
A [copier](https://copier.readthedocs.io) template for creating
a JupyterLab extension. Three kinds of extension are supported:
- _frontend_: Pure frontend extension written in TypeScript.
- _server_: Extension with frontend (in TypeScript) and backend (in Python) parts.
- _theme_: Theme for JupyterLab (using CSS variables).

> See also [extension-cookiecutter-js](https://github.com/jupyterlab/extension-cookiecutter-js)
for an extension in CommonJS.

## Use the template to create package

Install cookiecutter.
1. Install copier and some plugins.

```sh
pip install "copier>=7.1.0" jinja2-time
```
pip install cookiecutter

2. Go into the extension directory

```sh
mkdir myextension
cd myextension
```

Use cookiecutter to generate a package, following the prompts to fill in the name and authorship of your new JupyterLab extension.
3. Use copier to generate a package, following the prompts to fill in the name and authorship of your new JupyterLab extension.

```
cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts --checkout 4.0
copier https://github.com/jupyterlab/extension-cookiecutter-ts .
```

The available options are:
Expand All @@ -41,15 +45,15 @@ The available options are:
- `test`: Whether to add test set ups and skeletons for the extension or not
- `repository`: Version Control System repository URI

If you'd like to generate a package for a older release, use the `--vcs-ref` option and give a tag or commit from this repository.

If you'd like to generate a package for a specific JupyterLab release, use the `--checkout` option and give a tag or commit from this repository.

```
cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts --checkout v1.0
cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts --checkout v2.0
cookiecutter https://github.com/jupyterlab/extension-cookiecutter-ts --checkout 3.0
```sh
copier --vcs-ref v4.0.0 https://github.com/jupyterlab/extension-cookiecutter-ts
```

> If you are looking for a template compatible with JupyterLab version prior to 4.0.0, look at
> the [cookiecutter template](https://github.com/jupyterlab/extension-cookiecutter-ts).

## A simple example

Your new extension includes a very simple example of a working extension. Use this example as a guide to build your own extension. Have a look at the [extension examples](https://github.com/jupyterlab/extension-examples) repository for more information on various JupyterLab features.
14 changes: 4 additions & 10 deletions cookiecutter.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
{
"kind": ["frontend", "server", "theme"],
"author_name": "My Name",
"author_email": "me@test.com",
"labextension_name": "{% if cookiecutter.kind == 'theme' %}mytheme{% else %}myextension{% endif %}",
"python_name": "{{ cookiecutter.labextension_name | replace('-', '_') }}",
"project_short_description": "A JupyterLab extension.",
"has_settings": "n",
"has_binder": "n",
"test": "y",
"repository": "https://github.com/github_username/{{ cookiecutter.labextension_name }}"
"_copy_without_render": [
"copier.yml",
"template"
]
}
57 changes: 57 additions & 0 deletions copier.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
_min_copier_version: "7.1.0"
_subdirectory: template
_jinja_extensions:
- jinja2_time.TimeExtension

kind:
type: str
help: What is your extension kind?
choices:
- frontend
- server
- theme

author_name:
type: str
help: Author name?
placeholder: "My Name"

author_email:
type: str
help: Author email?
placeholder: "me@test.com"

labextension_name:
type: str
help: JavaScript extension name?
default: "{% if kind == 'theme' %}mytheme{% else %}myextension{% endif %}"

python_name:
type: str
help: Python package name?
default: "{{ labextension_name | replace('-', '_') }}"

project_short_description:
type: str
help: Extension short description
default: "A JupyterLab extension."

has_settings:
type: bool
help: Does the extension have settings?
default: no

has_binder:
type: bool
help: Do you want to set up a Binder example?
default: no

test:
type: bool
help: Do you want to set up tests for the extension?
default: yes

repository:
type: str
help: Git remote repository URL?
placeholder: https://github.com/github_username/my-extension
55 changes: 19 additions & 36 deletions hooks/post_gen_project.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env python
import sys
from pathlib import Path
from subprocess import CalledProcessError, check_call

PROJECT_DIRECTORY = Path.cwd()

TEMPLATE_URI = "https://github.com/jupyterlab/extension-cookiecutter-ts.git"

def remove_path(path: Path) -> None:
"""Remove the provided path.
Expand All @@ -22,38 +24,19 @@ def remove_path(path: Path) -> None:

if __name__ == "__main__":

if not "{{ cookiecutter.has_settings }}".lower().startswith("y"):
remove_path(PROJECT_DIRECTORY / "schema")

if "{{ cookiecutter.kind }}".lower() == "theme":
for f in (
"style/index.js",
"style/base.css"
):
remove_path(PROJECT_DIRECTORY / f)
else:
remove_path(PROJECT_DIRECTORY / "style/variables.css")

if not "{{ cookiecutter.kind }}".lower() == "server":
for f in (
"{{ cookiecutter.python_name }}/handlers.py",
"src/handler.ts",
"jupyter-config",
"conftest.py",
"{{ cookiecutter.python_name }}/tests"
):
remove_path(PROJECT_DIRECTORY / f)

if not "{{ cookiecutter.has_binder }}".lower().startswith("y"):
remove_path(PROJECT_DIRECTORY / "binder")
remove_path(PROJECT_DIRECTORY / ".github/workflows/binder-on-pr.yml")

if not "{{ cookiecutter.test }}".lower().startswith("y"):
remove_path(PROJECT_DIRECTORY / ".github" / "workflows" / "update-integration-tests.yml")
remove_path(PROJECT_DIRECTORY / "src" / "__tests__")
remove_path(PROJECT_DIRECTORY / "ui-tests")
remove_path(PROJECT_DIRECTORY / "{{ cookiecutter.python_name }}" / "tests")
remove_path(PROJECT_DIRECTORY / "babel.config.js")
remove_path(PROJECT_DIRECTORY / "conftest.py")
remove_path(PROJECT_DIRECTORY / "jest.config.js")
remove_path(PROJECT_DIRECTORY / "tsconfig.test.json")
remove_path(PROJECT_DIRECTORY / "template")
remove_path(PROJECT_DIRECTORY / "copier.yml")

try:
import copier
except ImportError:
try:
check_call([sys.executable, "-m", "pip", "install", "copier>=6.2.0"])
except CalledProcessError:
check_call([sys.executable, "-m", "pip", "install", "--pre", "copier>=6.2.0"])

from copier import run_copy

extension_name = input("What is your extension name?")
module_name = extension_name.replace("-", "_")
run_copy(TEMPLATE_URI, PROJECT_DIRECTORY / module_name, data={ "labextension_name": extension_name, "python_name": module_name})
Loading