diff --git a/.github/static/check_nbextensions.py b/.github/static/check_nbextensions.py new file mode 100755 index 0000000..1ec62aa --- /dev/null +++ b/.github/static/check_nbextensions.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +import json +from pathlib import Path +import subprocess +from typing import List, Union + + +def assert_extension(extensions: List[str]) -> None: + """Assert specific extension exists in the list of installed and enabled notebook extensions. + + "Validating: OK" will go to stderr, while the list of enabled extensions go to stdout. + """ + extensions_list_call = subprocess.run( + ["jupyter", "nbextension", "list"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + nbextensions = [ + _ for _ in extensions_list_call.stdout.decode().splitlines() if " " * 6 in _ + ] + enabled_nbextensions = [_ for _ in nbextensions if "enabled" in _] + validations = extensions_list_call.stderr.decode().splitlines() + + for extension in extensions: + assert extension in "".join( + nbextensions + ), f"{extension!r} not found in list of installed Jupyter NB extensions: {extensions_list_call.stdout.decode()}" + assert extension in "".join( + enabled_nbextensions + ), f"{extension!r} not found to be an enabled Jupyter NB extension: {extensions_list_call.stdout.decode()}" + for index, nbextension in enumerate(nbextensions): + if extension in nbextension: + assert "OK" in validations[index], ( + f"{extension!r} not found to be validated. Validations and output: " + f"{extensions_list_call.stderr.decode()}\n{extensions_list_call.stdout.decode()}" + ) + break + else: + raise RuntimeError( + f"By now, the extension {extension!r} should known to be an installed Jupyter NB " + "extension, but was not found in the list of Jupyter NB extensions: " + f"{extensions_list_call.stdout.decode()}" + ) + + +def get_extension_name(json_file: Union[str, Path]) -> List[str]: + """Retrieve extension name from `json_file`""" + if not isinstance(json_file, Path): + json_file = Path(json_file).resolve() + if not json_file.exists(): + raise RuntimeError(f"Could not find requested extension file at {json_file!r}") + + with open(json_file, "r") as handle: + extension_file: dict = json.load(handle) + + return [_ for _ in extension_file.get("load_extensions", {})] + + +if __name__ == "__main__": + extension_file = ( + Path(__file__) + .resolve() + .parent.parent.parent.joinpath("ipywidgets_extended.json") + ) + extension = get_extension_name(extension_file) + assert_extension(extension) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d35da0..cd47dab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,22 +47,25 @@ jobs: strategy: fail-fast: false matrix: - node-version: ['10', '12'] - python-version: [3.6, 3.7, 3.8, 3.9] + node-version: ['10', '13'] + python-version: [3.6, 3.9] steps: - name: Checkout repository uses: actions/checkout@v2 - - name: Install Node ${{ matrix.node-version}} + - name: Install Node ${{ matrix.node-version }} uses: actions/setup-node@v1 with: - node-version: ${{ matrix.node-version}} + node-version: ${{ matrix.node-version }} - - name: Set up Python ${{ matrix.python-version}} + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: - python-version: ${{ matrix.python-version}} + python-version: ${{ matrix.python-version }} + + - name: Install Python requirements + run: pip install -r requirements.txt - name: Check build and installation of PyPI source distribution env: @@ -75,3 +78,6 @@ jobs: mkdir -p /tmp/installation_dir cd /tmp/installation_dir pip install ${ORIGINAL_PWD}/${SDIST_DIR}/${SDIST_FILE} + + - name: Assert nbextension installed correctly + run: ./.github/static/check_nbextensions.py diff --git a/.github/workflows/publish-on-pypi.yml b/.github/workflows/publish-on-pypi.yml index 5d6616b..aa3c437 100644 --- a/.github/workflows/publish-on-pypi.yml +++ b/.github/workflows/publish-on-pypi.yml @@ -16,15 +16,21 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Install Node 13 + uses: actions/setup-node@v1 + with: + node-version: '13' + - name: Set up Python 3.9 uses: actions/setup-python@v2 with: python-version: 3.9 - - name: Update setuptools + - name: Update setuptools and install requirements run: | python -m pip install --upgrade pip pip install -U setuptools + pip install -r requirements.txt - name: Update version and tag run: .github/static/update_version.sh diff --git a/MANIFEST.in b/MANIFEST.in index 9c4c175..c13c667 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,31 @@ include LICENSE include README.md include requirements*.txt + include setupbase.py -include *.json -include *.js -recursive-include src *.ts + +include tsconfig.json +include package.json +include webpack.config.js +include ipywidgets_extended/labextension/*.tgz + +# Examples +graft examples + +# Tests +graft tests +prune tests/build + +# Javascript files +graft ipywidgets_extended/nbextension +graft src +prune **/node_modules +prune coverage +prune lib + +# Patterns to exclude from any directory +global-exclude *~ +global-exclude *.pyc +global-exclude *.pyo +global-exclude .git +global-exclude .ipynb_checkpoints diff --git a/ipywidgets_extended.json b/ipywidgets_extended.json index 85d76d5..ef48c66 100644 --- a/ipywidgets_extended.json +++ b/ipywidgets_extended.json @@ -1,5 +1,5 @@ { "load_extensions": { - "ipywidgets-extended/extension": true + "ipywidgets_extended/extension": true } } diff --git a/ipywidgets_extended/dropdown.py b/ipywidgets_extended/dropdown.py index bd80657..baf469f 100644 --- a/ipywidgets_extended/dropdown.py +++ b/ipywidgets_extended/dropdown.py @@ -20,10 +20,10 @@ class DropdownExtended(Dropdown): _model_name = traitlets.Unicode("DropdownExtendedModel").tag(sync=True) _model_module = traitlets.Unicode("ipywidgets-extended").tag(sync=True) - _model_module_version = traitlets.Unicode(__version__).tag(sync=True) + _model_module_version = traitlets.Unicode(f"^{__version__}").tag(sync=True) _view_name = traitlets.Unicode("DropdownExtendedView").tag(sync=True) _view_module = traitlets.Unicode("ipywidgets-extended").tag(sync=True) - _view_module_version = traitlets.Unicode(__version__).tag(sync=True) + _view_module_version = traitlets.Unicode(f"^{__version__}").tag(sync=True) # This being read-only means that it cannot be changed by the user. _disabled_options_labels = traitlets.List( diff --git a/package.json b/package.json index b22f4ae..19f7b8e 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,6 @@ "description": "Extensions to the Jupyter Widgets in the 'ipywidgets' pacakge.", "keywords": [ "jupyter", - "jupyterlab", - "jupyterlab-extension", "widgets" ], "files": [ @@ -48,7 +46,7 @@ "watch:nbextension": "webpack --watch" }, "dependencies": { - "@jupyter-widgets/base": "^1.2.0 || ^2 || ^3", + "@jupyter-widgets/base": "^1.2.0 || ^2 || ^3 || ^4", "@jupyter-widgets/controls": "^1.5.0 || ^2 || ^3" }, "devDependencies": { diff --git a/setup.py b/setup.py index b0dcd1c..2264fd3 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ ) setup( - name="ipywidgets-extended", + name=NAME.replace("_", "-"), version=get_version(Path(NAME) / "version.py"), license="BSD", author="Casper Welzel Andersen", diff --git a/tsconfig.json b/tsconfig.json index e483763..75169a2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,7 @@ "target": "es2015" }, "include": [ - "src/*.ts" + "src/**/*.ts", + "src/**/*.tsx" ] } diff --git a/webpack.config.js b/webpack.config.js index e3ca1e1..a1e3ae2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -9,7 +9,7 @@ const rules = [ ]; // Packages that shouldn't be bundled but loaded at runtime -const externals = ['@jupyter-widgets/base']; +const externals = ['@jupyter-widgets/base', '@jupyter-widgets/controls']; const resolve = { // Add '.ts' and '.tsx' as resolvable extensions. @@ -55,7 +55,7 @@ module.exports = [ path: path.resolve(__dirname, 'dist'), libraryTarget: 'amd', library: "ipywidgets-extended", - publicPath: 'https://unpkg.com/ipywidgets_extended@' + version + '/dist/' + publicPath: 'https://unpkg.com/ipywidgets-extended@' + version + '/dist/' }, devtool: 'source-map', module: {