From bbbc392f6e24aa64cdb717bdbf1e783249ed23a5 Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Wed, 9 Aug 2023 13:52:44 +0000 Subject: [PATCH] Update to JupyterLab 4 --- .copier-answers.yml | 14 ++ .eslintignore | 5 - .eslintrc.js | 39 ---- .github/workflows/build.yml | 80 ++++++- .github/workflows/check-release.yml | 16 +- .github/workflows/enforce-label.yml | 2 + .github/workflows/prep-release.yml | 1 - .github/workflows/publish-release.yml | 13 +- .gitignore | 132 ++++------- .prettierignore | 4 +- .prettierrc | 3 - .yarnrc.yml | 3 + RELEASE.md | 118 ++++++++-- package.json | 323 +++++++++++++++++--------- pyproject.toml | 86 ++----- setup.py | 1 - style/base.css | 5 + style/index.css | 1 + style/index.js | 1 + tsconfig.json | 17 +- 20 files changed, 507 insertions(+), 357 deletions(-) create mode 100644 .copier-answers.yml delete mode 100644 .eslintignore delete mode 100644 .eslintrc.js delete mode 100644 .prettierrc create mode 100644 .yarnrc.yml create mode 100644 style/base.css create mode 100644 style/index.css create mode 100644 style/index.js diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 0000000..c4b18f1 --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,14 @@ +# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY +_commit: v4.1.0 +_src_path: https://github.com/jupyterlab/extension-template +author_email: '' +author_name: ipylab contributors +has_binder: false +has_settings: false +kind: frontend +labextension_name: ipylab +project_short_description: Control JupyterLab from Python notebooks +python_name: ipylab +repository: https://github.com/jtpio/ipylab +test: false + diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 4cb87e8..0000000 --- a/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -dist -docs -coverage -**/*.d.ts \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index a30694b..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,39 +0,0 @@ -module.exports = { - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:prettier/recommended', - ], - parser: '@typescript-eslint/parser', - parserOptions: { - project: 'tsconfig.json', - sourceType: 'module', - }, - plugins: ['@typescript-eslint'], - rules: { - '@typescript-eslint/naming-convention': [ - 'error', - { - selector: 'interface', - format: ['PascalCase'], - custom: { - regex: '^I[A-Z]', - match: true, - }, - }, - ], - '@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', - }, -}; diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cdbba3e..c80e04d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,29 +2,87 @@ name: Build on: push: - branches: [ main ] + branches: main pull_request: - branches: - - '*' + branches: '*' jobs: build: runs-on: ubuntu-latest + steps: - name: Checkout uses: actions/checkout@v3 + - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - name: Install dependencies + run: python -m pip install -U "jupyterlab>=4.0.0,<5" + + - name: Lint the extension run: | - python -m pip install --upgrade pip jupyterlab~=3.0 - - name: Install the ipylab Python package and JupyterLab extension - run: | - python -m pip install . - jupyter labextension list 2>&1 | grep -ie "ipylab.*enabled.*ok" - - - name: Browser check + set -eux + jlpm + jlpm run lint:check + + - name: Build the extension run: | + set -eux + python -m pip install .[test] + + jupyter labextension list + jupyter labextension list 2>&1 | grep -ie "ipylab.*OK" python -m jupyterlab.browser_check - - name: Check ipylab can be imported + + - name: Package the extension + run: | + set -eux + + pip install build + python -m build + pip uninstall -y "ipylab" jupyterlab + + - name: Upload extension packages + uses: actions/upload-artifact@v3 + with: + name: extension-artifacts + path: dist/ipylab* + if-no-files-found: error + + test_isolated: + needs: build + runs-on: ubuntu-latest + + steps: + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + architecture: 'x64' + - uses: actions/download-artifact@v3 + with: + name: extension-artifacts + - name: Install and Test run: | - python -c "from ipylab import JupyterFrontEnd" + set -eux + # Remove NodeJS, twice to take care of system and locally installed node versions. + sudo rm -rf $(which node) + sudo rm -rf $(which node) + + pip install "jupyterlab>=4.0.0,<5" ipylab*.whl + + + jupyter labextension list + jupyter labextension list 2>&1 | grep -ie "ipylab.*OK" + python -m jupyterlab.browser_check --no-browser-test + + + check_links: + name: Check Links + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v3 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1 diff --git a/.github/workflows/check-release.yml b/.github/workflows/check-release.yml index 8ef6186..032d142 100644 --- a/.github/workflows/check-release.yml +++ b/.github/workflows/check-release.yml @@ -1,14 +1,9 @@ name: Check Release on: push: - branches: - - main + branches: ["main"] pull_request: - branches: - - main - -permissions: - contents: write + branches: ["*"] jobs: check_release: @@ -16,15 +11,16 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - + - name: Install Dependencies + run: | + pip install -e . - name: Check Release uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 with: + token: ${{ secrets.GITHUB_TOKEN }} - version_spec: next - name: Upload Distributions uses: actions/upload-artifact@v3 diff --git a/.github/workflows/enforce-label.yml b/.github/workflows/enforce-label.yml index 354a046..725feab 100644 --- a/.github/workflows/enforce-label.yml +++ b/.github/workflows/enforce-label.yml @@ -6,6 +6,8 @@ on: jobs: enforce-label: runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - name: enforce-triage-label uses: jupyterlab/maintainer-tools/.github/actions/enforce-label@v1 diff --git a/.github/workflows/prep-release.yml b/.github/workflows/prep-release.yml index 7a2a18d..6f09281 100644 --- a/.github/workflows/prep-release.yml +++ b/.github/workflows/prep-release.yml @@ -32,7 +32,6 @@ jobs: token: ${{ secrets.ADMIN_GITHUB_TOKEN }} version_spec: ${{ github.event.inputs.version_spec }} post_version_spec: ${{ github.event.inputs.post_version_spec }} - target: ${{ github.event.inputs.target }} branch: ${{ github.event.inputs.branch }} since: ${{ github.event.inputs.since }} since_last_stable: ${{ github.event.inputs.since_last_stable }} diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index dbaaeaa..1ddf2e2 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -15,6 +15,10 @@ on: jobs: publish_release: runs-on: ubuntu-latest + permissions: + # This is useful if you want to use PyPI trusted publisher + # and NPM provenance + id-token: write steps: - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 @@ -23,7 +27,6 @@ jobs: uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2 with: token: ${{ secrets.ADMIN_GITHUB_TOKEN }} - target: ${{ github.event.inputs.target }} branch: ${{ github.event.inputs.branch }} release_url: ${{ github.event.inputs.release_url }} steps_to_skip: ${{ github.event.inputs.steps_to_skip }} @@ -31,14 +34,14 @@ jobs: - name: Finalize Release id: finalize-release env: - PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }} - TWINE_USERNAME: __token__ + # The following are needed if you use legacy PyPI set up + # PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + # PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }} + # TWINE_USERNAME: __token__ NPM_TOKEN: ${{ secrets.NPM_TOKEN }} uses: jupyter-server/jupyter-releaser/.github/actions/finalize-release@v2 with: token: ${{ secrets.ADMIN_GITHUB_TOKEN }} - target: ${{ github.event.inputs.target }} release_url: ${{ steps.populate-release.outputs.release_url }} - name: "** Next Step **" diff --git a/.gitignore b/.gitignore index ea6cf53..f11690b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,20 @@ +*.bundle.* +lib/ +node_modules/ +*.log +.eslintcache +.stylelintcache +*.egg-info/ +.ipynb_checkpoints +*.tsbuildinfo +ipylab/labextension +# Version file is handled by hatchling +ipylab/_version.py + +# Created by https://www.gitignore.io/api/python +# Edit at https://www.gitignore.io/?templates=python + +### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -8,7 +25,6 @@ __pycache__/ # Distribution / packaging .Python -env/ build/ develop-eggs/ dist/ @@ -20,9 +36,12 @@ lib64/ parts/ sdist/ var/ -*.egg-info/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -37,126 +56,69 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ +.nox/ .coverage .coverage.* .cache nosetests.xml +coverage/ coverage.xml -*,cover +*.cover .hypothesis/ +.pytest_cache/ # Translations *.mo *.pot -# Django stuff: -*.log -local_settings.py - -# Flask instance folder -instance/ - # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ -docs/source/_static/embed-bundle.js -docs/source/_static/embed-bundle.js.map # PyBuilder target/ -# IPython Notebook -.ipynb_checkpoints - # pyenv .python-version # celery beat schedule file celerybeat-schedule -# dotenv -.env - -# virtualenv -venv/ -ENV/ +# SageMath parsed files +*.sage.py # Spyder project settings .spyderproject +.spyproject # Rope project settings .ropeproject -# ========================= -# Operating System Files -# ========================= +# Mr Developer +.mr.developer.cfg +.project +.pydevproject -# OSX -# ========================= +# mkdocs documentation +/site -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Windows -# ========================= - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json -# Windows Installer files -*.cab -*.msi -*.msm -*.msp +# Pyre type checker +.pyre/ -# Windows shortcuts -*.lnk +# End of https://www.gitignore.io/api/python +# OSX files +.DS_Store -# NPM -# ---- - -**/node_modules/ -ipylab/nbextension/static/index.* -ipylab/labextension/*.tgz - -# Coverage data -# ------------- -**/coverage/ - -# Packed lab extensions -ipylab/labextension -# generated -ipylab/_version.py - -package-lock.json +# Yarn cache +.yarn/ -.vscode +# extension update +_temp_extension diff --git a/.prettierignore b/.prettierignore index 07b724b..ff70eda 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,5 +2,5 @@ node_modules **/node_modules **/lib **/package.json -ipylab/labextension -docs +!/package.json +ipylab diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 544138b..0000000 --- a/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "singleQuote": true -} diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000..fe1125f --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1,3 @@ +enableImmutableInstalls: false + +nodeLinker: node-modules diff --git a/RELEASE.md b/RELEASE.md index 1a5c1cb..71a60d7 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,23 +1,111 @@ -# Making a new release of `ipylab` +# Making a new release of ipylab -The recommended way to make a release is to use [`jupyter_releaser`](https://jupyter-releaser.readthedocs.io/en/latest/get_started/making_release_from_repo.html). +The extension can be published to `PyPI` and `npm` manually or using the [Jupyter Releaser](https://github.com/jupyter-server/jupyter_releaser). -This repository contains the two workflows located under https://github.com/jtpio/ipylab/actions: +## Manual release -- Step 1: Prep Release -- Step 2: Publish Release +### Python package -### Specifying a version spec +This extension can be distributed as Python packages. All of the Python +packaging instructions are in the `pyproject.toml` file to wrap your extension in a +Python package. Before generating a package, you first need to install some tools: -The `next` version spec is supported and will bump the packages as follows. For example: +```bash +pip install build twine hatch +``` -- `0.1.0a0` -> `0.1.0a1` -- `0.1.0b7` -> `0.1.0b8` -- `0.1.0` -> `0.1.1` +Bump the version using `hatch`. By default this will create a tag. +See the docs on [hatch-nodejs-version](https://github.com/agoose77/hatch-nodejs-version#semver) for details. -You can also specify the Python version directly as the `version_spec` when using the -releaser workflows. For example: +```bash +hatch version +``` -- `0.1.0b8` -- `0.1.1` -- `1.2.0rc0` +Make sure to clean up all the development files before building the package: + +```bash +jlpm clean:all +``` + +You could also clean up the local git repository: + +```bash +git clean -dfX +``` + +To create a Python source package (`.tar.gz`) and the binary package (`.whl`) in the `dist/` directory, do: + +```bash +python -m build +``` + +> `python setup.py sdist bdist_wheel` is deprecated and will not work for this package. + +Then to upload the package to PyPI, do: + +```bash +twine upload dist/* +``` + +### NPM package + +To publish the frontend part of the extension as a NPM package, do: + +```bash +npm login +npm publish --access public +``` + +## Automated releases with the Jupyter Releaser + +The extension repository should already be compatible with the Jupyter Releaser. + +Check out the [workflow documentation](https://jupyter-releaser.readthedocs.io/en/latest/get_started/making_release_from_repo.html) for more information. + +Here is a summary of the steps to cut a new release: + +- Add tokens to the [Github Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) in the repository: + - `ADMIN_GITHUB_TOKEN` (with "public_repo" and "repo:status" permissions); see the [documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) + - `NPM_TOKEN` (with "automation" permission); see the [documentation](https://docs.npmjs.com/creating-and-viewing-access-tokens) +- Set up PyPI + +
Using PyPI trusted publisher (modern way) + +- Set up your PyPI project by [adding a trusted publisher](https://docs.pypi.org/trusted-publishers/adding-a-publisher/) + - The _workflow name_ is `publish-release.yml` and the _environment_ should be left blank. +- Ensure the publish release job as `permissions`: `id-token : write` (see the [documentation](https://docs.pypi.org/trusted-publishers/using-a-publisher/)) + +
+ +
Using PyPI token (legacy way) + +- If the repo generates PyPI release(s), create a scoped PyPI [token](https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#saving-credentials-on-github). We recommend using a scoped token for security reasons. + +- You can store the token as `PYPI_TOKEN` in your fork's `Secrets`. + + - Advanced usage: if you are releasing multiple repos, you can create a secret named `PYPI_TOKEN_MAP` instead of `PYPI_TOKEN` that is formatted as follows: + + ```text + owner1/repo1,token1 + owner2/repo2,token2 + ``` + + If you have multiple Python packages in the same repository, you can point to them as follows: + + ```text + owner1/repo1/path/to/package1,token1 + owner1/repo1/path/to/package2,token2 + ``` + +
+ +- Go to the Actions panel +- Run the "Step 1: Prep Release" workflow +- Check the draft changelog +- Run the "Step 2: Publish Release" workflow + +## Publishing to `conda-forge` + +If the package is not on conda forge yet, check the documentation to learn how to add it: https://conda-forge.org/docs/maintainer/adding_pkgs.html + +Otherwise a bot should pick up the new version publish to PyPI, and open a new PR on the feedstock repository automatically. diff --git a/package.json b/package.json index 0097db5..aebba5e 100644 --- a/package.json +++ b/package.json @@ -1,117 +1,222 @@ { - "name": "ipylab", - "version": "0.7.1", - "description": "Control JupyterLab from Python notebooks", - "keywords": [ - "jupyter", - "jupyterlab", - "jupyterlab-extension", - "widgets" + "name": "ipylab", + "version": "0.7.1", + "description": "Control JupyterLab from Python notebooks", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension", + "widgets" + ], + "files": [ + "lib/**/*.js", + "dist/*.js", + "style/*.css", + "style/*.js", + "style/index.js" + ], + "homepage": "https://github.com/jtpio/ipylab", + "bugs": { + "url": "https://github.com/jtpio/ipylab/issues" + }, + "license": "BSD-3-Clause", + "author": { + "name": "ipylab contributors", + "email": "" + }, + "main": "lib/index.js", + "style": "style/widget.css", + "styleModule": "style/style.js", + "types": "./lib/index.d.ts", + "sideEffects": [ + "style/*.css", + "style/style.js", + "style/index.js" + ], + "repository": { + "type": "git", + "url": "https://github.com/jtpio/ipylab" + }, + "scripts": { + "build": "jlpm build:lib && jlpm build:labextension:dev", + "build:labextension": "jupyter labextension build .", + "build:labextension:dev": "jupyter labextension build --development True .", + "build:lib": "tsc --sourceMap", + "build:lib:prod": "tsc", + "build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension", + "clean": "jlpm clean:lib", + "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", + "clean:labextension": "rimraf ipylab/labextension ipylab/_version.py", + "clean:lib": "rimraf lib tsconfig.tsbuildinfo", + "clean:lintcache": "rimraf .eslintcache .stylelintcache", + "eslint": "jlpm eslint:check --fix", + "eslint:check": "eslint . --cache --ext .ts,.tsx", + "install:extension": "jlpm build", + "lint": "jlpm stylelint && jlpm prettier && jlpm eslint", + "lint:check": "jlpm stylelint:check && jlpm prettier:check && jlpm eslint:check", + "prepack": "npm run build", + "prettier": "jlpm prettier:base --write --list-different", + "prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"", + "prettier:check": "jlpm prettier:base --check", + "stylelint": "jlpm stylelint:check --fix", + "stylelint:check": "stylelint --cache \"style/**/*.css\"", + "watch": "run-p watch:src watch:labextension", + "watch:labextension": "jupyter labextension watch .", + "watch:lib": "tsc -w", + "watch:src": "tsc -w --sourceMap" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}": [ + "prettier --write", + "git add" ], - "files": [ - "lib/**/*.js", - "dist/*.js", - "style/*.css", - "style/*.js" + "**/*{.py}": [ + "black", + "git add" + ] + }, + "dependencies": { + "@jupyter-widgets/base": "^1 || ^2 || ^3 || ^4 || ^5 || ^6", + "@jupyter-widgets/controls": "^3 || ^4 || ^5", + "@jupyterlab/application": "^4.0.4", + "@jupyterlab/apputils": "^4.1.4", + "@jupyterlab/observables": "^5.0.4", + "@lumino/algorithm": "^2.0.0", + "@lumino/commands": "^2.0.1", + "@lumino/disposable": "^2.0.0", + "@lumino/messaging": "^2.0.0", + "@lumino/widgets": "^2.0.1" + }, + "devDependencies": { + "@jupyterlab/builder": "^4.0.0", + "@types/expect.js": "^0.3.29", + "@types/json-schema": "^7.0.11", + "@types/node": "^18.7.8", + "@types/react": "^18.0.26", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", + "css-loader": "^6.7.1", + "eslint": "^8.36.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-jsdoc": "^39.3.6", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-react": "^7.30.1", + "expect.js": "^0.3.1", + "fs-extra": "^10.1.0", + "husky": "^8.0.1", + "lint-staged": "^13.0.3", + "mkdirp": "^1.0.4", + "npm-run-all": "^4.1.5", + "prettier": "^3.0.0", + "rimraf": "^5.0.1", + "source-map-loader": "^1.0.2", + "style-loader": "^3.3.1", + "stylelint": "^15.10.1", + "stylelint-config-recommended": "^13.0.0", + "stylelint-config-standard": "^34.0.0", + "stylelint-prettier": "^4.0.0", + "typescript": "~5.0.2", + "yjs": "^13.5.40" + }, + "jupyterlab": { + "extension": "lib/plugin", + "outputDir": "ipylab/labextension", + "sharedPackages": { + "@jupyter-widgets/base": { + "bundled": false, + "singleton": true + } + } + }, + "eslintConfig": { + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" ], - "homepage": "https://github.com/jtpio/ipylab", - "bugs": { - "url": "https://github.com/jtpio/ipylab/issues" + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "tsconfig.json", + "sourceType": "module" }, - "license": "BSD-3-Clause", - "author": { - "name": "ipylab contributors", - "email": "" - }, - "main": "lib/index.js", - "style": "style/widget.css", - "styleModule": "style/style.js", - "types": "./lib/index.d.ts", - "sideEffects": [ - "style/*.css", - "style/style.js" + "plugins": [ + "@typescript-eslint" ], - "repository": { - "type": "git", - "url": "https://github.com/jtpio/ipylab" - }, - "scripts": { - "build": "jlpm run build:lib && jlpm run build:labextension:dev", - "build:prod": "jlpm run build:lib && jlpm run build:labextension", - "build:lib": "tsc", - "build:labextension": "jupyter labextension build .", - "build:labextension:dev": "jupyter labextension build --development True .", - "clean": "jlpm run clean:lib ipylab/labextension", - "clean:lib": "rimraf lib tsconfig.tsbuildinfo", - "clean:all": "jlpm run clean:lib && jlpm run clean:labextension", - "clean:labextension": "rimraf ipylab/labextension", - "eslint": "eslint . --ext .ts,.tsx --fix", - "eslint:check": "eslint . --ext .ts,.tsx", - "lint": "jlpm && jlpm run prettier && jlpm run eslint", - "lint:check": "jlpm run prettier:check && jlpm run eslint:check", - "prepack": "npm run build", - "prettier": "prettier --write \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\" \"!dist/**\" \"!docs/**\"", - "prettier:check": "prettier --list-different \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\" \"!dist/**\" \"!docs/**\"", - "watch": "npm-run-all -p watch:*", - "watch:lib": "tsc -w", - "watch:labextension": "jupyter labextension watch ." - }, - "husky": { - "hooks": { - "pre-commit": "lint-staged" + "rules": { + "@typescript-eslint/naming-convention": [ + "error", + { + "selector": "interface", + "format": [ + "PascalCase" + ], + "custom": { + "regex": "^I[A-Z]", + "match": true + } } - }, - "lint-staged": { - "**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}": [ - "prettier --write", - "git add" - ], - "**/*{.py}": [ - "black", - "git add" - ] - }, - "dependencies": { - "@jupyter-widgets/base": "^1 || ^2 || ^3 || ^4 || ^5 || ^6", - "@jupyter-widgets/controls": "^3 || ^4 || ^5", - "@jupyterlab/application": "^3.4.5", - "@jupyterlab/apputils": "^3.4.5", - "@jupyterlab/observables": "^4.4.5", - "@lumino/algorithm": "^1.9.2", - "@lumino/commands": "^1.20.1", - "@lumino/disposable": "^1.10.2", - "@lumino/messaging": "^1.10.2", - "@lumino/widgets": "^1.34.0" - }, - "devDependencies": { - "@jupyterlab/builder": "^3.4.5", - "@types/expect.js": "^0.3.29", - "@types/node": "^18.7.8", - "@typescript-eslint/eslint-plugin": "^5.33.1", - "@typescript-eslint/parser": "^5.33.1", - "eslint": "^8.22.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-jsdoc": "^39.3.6", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.30.1", - "expect.js": "^0.3.1", - "fs-extra": "^10.1.0", - "husky": "^8.0.1", - "lint-staged": "^13.0.3", - "mkdirp": "^1.0.4", - "npm-run-all": "^4.1.5", - "prettier": "^2.7.1", - "rimraf": "^3.0.2", - "typescript": "~4.7.4" - }, - "jupyterlab": { - "extension": "lib/plugin", - "outputDir": "ipylab/labextension/", - "sharedPackages": { - "@jupyter-widgets/base": { - "bundled": false, - "singleton": true - } + ], + "@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" + } + }, + "eslintIgnore": [ + "node_modules", + "dist", + "coverage", + "**/*.d.ts" + ], + "prettier": { + "singleQuote": true, + "trailingComma": "none", + "arrowParens": "avoid", + "endOfLine": "auto", + "overrides": [ + { + "files": "package.json", + "options": { + "tabWidth": 4 + } + } + ] + }, + "stylelint": { + "extends": [ + "stylelint-config-recommended", + "stylelint-config-standard", + "stylelint-prettier/recommended" + ], + "rules": { + "property-no-vendor-prefix": null, + "selector-no-vendor-prefix": null, + "value-no-vendor-prefix": null } -} + } +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 4b9ff00..ecef468 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,5 @@ [build-system] -requires = [ - "hatchling", - "jupyterlab~=3.1", - "hatch-nodejs-version", -] +requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<5", "hatch-nodejs-version"] build-backend = "hatchling.build" [project] @@ -14,11 +10,9 @@ requires-python = ">=3.8" classifiers = [ "Framework :: Jupyter", "Framework :: Jupyter :: JupyterLab", - "Framework :: Jupyter :: JupyterLab :: 3", + "Framework :: Jupyter :: JupyterLab :: 4", "Framework :: Jupyter :: JupyterLab :: Extensions", "Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", "License :: OSI Approved :: BSD License", "Programming Language :: Python", "Programming Language :: Python :: 3", @@ -28,90 +22,54 @@ classifiers = [ "Programming Language :: Python :: 3.11", ] dependencies = [ - "ipywidgets>=7.6.0,<9", ] dynamic = ["version", "description", "authors", "urls", "keywords"] [tool.hatch.version] source = "nodejs" -[tool.hatch.build.hooks.version] -path = "ipylab/_version.py" - [tool.hatch.metadata.hooks.nodejs] fields = ["description", "authors", "urls"] -[project.optional-dependencies] -dev = [ - "black", - "pre-commit", -] -docs = [ - "jupyter_sphinx", - "nbsphinx-link", - "nbsphinx>=0.2.13,<0.4.0", - "pypandoc", - "pytest_check_links", - "recommonmark", - "sphinx>=1.5", - "sphinx_rtd_theme", -] -test = [ - "pytest", - "pytest-cov", -] - -[tool.hatch.build] -artifacts = [ - "ipylab/nbextension/static/index.*", - "ipylab/labextension/*.tgz", - "ipylab/labextension", -] +[tool.hatch.build.targets.sdist] +artifacts = ["ipylab/labextension"] +exclude = [".github", "binder"] [tool.hatch.build.targets.wheel.shared-data] -"ipylab/labextension/static" = "share/jupyter/labextensions/ipylab/static" +"ipylab/labextension" = "share/jupyter/labextensions/ipylab" "install.json" = "share/jupyter/labextensions/ipylab/install.json" -"ipylab/labextension/build_log.json" = "share/jupyter/labextensions/ipylab/build_log.json" -"ipylab/labextension/package.json" = "share/jupyter/labextensions/ipylab/package.json" -[tool.hatch.build.targets.sdist] -exclude = [ - ".binder", - ".github", -] +[tool.hatch.build.hooks.version] +path = "ipylab/_version.py" [tool.hatch.build.hooks.jupyter-builder] -dependencies = [ - "hatch-jupyter-builder>=0.8.2", -] +dependencies = ["hatch-jupyter-builder>=0.5"] build-function = "hatch_jupyter_builder.npm_builder" ensured-targets = [ "ipylab/labextension/static/style.js", "ipylab/labextension/package.json", ] -skip-if-exists = [ - "ipylab/labextension/static/style.js", -] - -[tool.hatch.build.hooks.jupyter-builder.editable-build-kwargs] -build_dir = "ipylab/labextension" -source_dir = "src" -build_cmd = "build" -npm = [ - "jlpm", -] +skip-if-exists = ["ipylab/labextension/static/style.js"] [tool.hatch.build.hooks.jupyter-builder.build-kwargs] build_cmd = "build:prod" -npm = [ - "jlpm", -] +npm = ["jlpm"] + +[tool.hatch.build.hooks.jupyter-builder.editable-build-kwargs] +build_cmd = "install:extension" +npm = ["jlpm"] +source_dir = "src" +build_dir = "ipylab/labextension" [tool.jupyter-releaser.options] version_cmd = "hatch version" [tool.jupyter-releaser.hooks] -before-build-npm = ["python -m pip install jupyterlab~=3.1", "jlpm", "jlpm build:prod"] +before-build-npm = [ + "python -m pip install 'jupyterlab>=4.0.0,<5'", + "jlpm", + "jlpm build:prod" +] before-build-python = ["jlpm clean:all"] [tool.check-wheel-contents] diff --git a/setup.py b/setup.py index b6c6681..aefdf20 100644 --- a/setup.py +++ b/setup.py @@ -1,2 +1 @@ -# setup.py shim for use with applications that require it. __import__("setuptools").setup() diff --git a/style/base.css b/style/base.css new file mode 100644 index 0000000..e11f457 --- /dev/null +++ b/style/base.css @@ -0,0 +1,5 @@ +/* + See the JupyterLab Developer Guide for useful CSS Patterns: + + https://jupyterlab.readthedocs.io/en/stable/developer/css.html +*/ diff --git a/style/index.css b/style/index.css new file mode 100644 index 0000000..8a7ea29 --- /dev/null +++ b/style/index.css @@ -0,0 +1 @@ +@import url('base.css'); diff --git a/style/index.js b/style/index.js new file mode 100644 index 0000000..a028a76 --- /dev/null +++ b/style/index.js @@ -0,0 +1 @@ +import './base.css'; diff --git a/tsconfig.json b/tsconfig.json index a634d00..9897917 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,23 @@ { "compilerOptions": { + "allowSyntheticDefaultImports": true, + "composite": true, "declaration": true, "esModuleInterop": true, + "incremental": true, + "jsx": "react", "module": "esnext", "moduleResolution": "node", "noEmitOnError": true, + "noImplicitAny": true, "noUnusedLocals": true, - "outDir": "lib", + "preserveWatchOutput": true, "resolveJsonModule": true, + "outDir": "lib", "rootDir": "src", - "skipLibCheck": true, - "sourceMap": true, "strict": true, - "strictNullChecks": false, - "strictPropertyInitialization": false, - "target": "es2017" + "strictNullChecks": true, + "target": "ES2018" }, - "include": ["src/**/*.ts", "src/**/*.tsx"] + "include": ["src/*"] }