diff --git a/package.json b/package.json index e201774..a4800b5 100644 --- a/package.json +++ b/package.json @@ -1,127 +1,127 @@ { - "name": "@pyviz/jupyterlab_pyviz", - "version": "3.0.3", - "description": "A JupyterLab extension for rendering HoloViz content.", - "keywords": [ - "jupyter", - "jupyterlab", - "jupyterlab-extension" - ], - "homepage": "https://github.com/holoviz/pyviz_comms", - "bugs": { - "url": "https://github.com/holoviz/pyviz_comms/issues" - }, - "license": "BSD-3-Clause", - "author": { - "name": "Philipp Rudiger" - }, - "files": [ - "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", - "style/**/*.{css,.js,eot,gif,html,jpg,json,png,svg,woff2,ttf}", - "schema/*.json", - "style/index.js" - ], - "main": "lib/index.js", - "types": "lib/index.d.ts", - "style": "style/index.css", - "repository": { - "type": "git", - "url": "https://github.com/holoviz/pyviz_comms.git" - }, - "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 pyviz_comms/labextension pyviz_comms/_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 prettier && jlpm eslint", - "lint:check": "jlpm prettier:check && jlpm eslint:check", - "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:src": "tsc -w --sourceMap" - }, - "dependencies": { - "@jupyterlab/application": "^4.0.3", - "@jupyterlab/apputils": "^4.1.3", - "@jupyterlab/coreutils": "^6.0.3", - "@jupyterlab/docregistry": "^4.0.3", - "@jupyterlab/fileeditor": "^4.0.3", - "@jupyterlab/mainmenu": "^4.0.3", - "@jupyterlab/notebook": "^4.0.3", - "@jupyterlab/settingregistry": "^4.0.3", - "@jupyterlab/ui-components": "^4.0.3", - "@lumino/coreutils": "^2.1.1", - "@lumino/signaling": "^2.1.1", - "tippy.js": "^6" - }, - "resolutions": { - "@lumino/widgets": "^2.1.1", - "react": "^17.0.1", - "react-dom": "^17.0.1" - }, - "peerDependencies": { - "@jupyter-widgets/base": "^2 || ^3 || ^4 || ^5 || ^6", - "@jupyter-widgets/jupyterlab-manager": "^5.0.4" - }, - "devDependencies": { - "@jupyter-widgets/base": "^2 || ^3 || ^4 || ^5 || ^6", - "@jupyter-widgets/jupyterlab-manager": "^5.0.7", - "@jupyterlab/builder": "^4.0.0", - "@jupyterlab/testutils": "^3.0.0", - "@types/json-schema": "^7.0.11", - "@types/node": "^14.14.16", - "@types/react": "^18.0.26", - "@types/react-dom": "^17.0.0", - "@typescript-eslint/eslint-plugin": "^5.55.0", - "@typescript-eslint/parser": "^5.55.0", - "css-loader": "^6.7.1", - "eslint": "^8.36.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^5.0.0", - "npm-run-all": "^4.1.5", - "prettier": "^3.0.0", - "rimraf": "^4.4.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" - }, - "sideEffects": [ - "style/*.css", - "style/index.js" - ], - "styleModule": "style/index.js", - "jupyterlab": { - "extension": true, - "outputDir": "pyviz_comms/labextension", - "schemaDir": "schema", - "sharedPackages": { - "@jupyter-widgets/jupyterlab-manager": { - "bundled": false, - "singleton": true - }, - "@jupyter-widgets/base": { - "bundled": false, - "singleton": true - } - } + "name": "@pyviz/jupyterlab_pyviz", + "version": "3.0.3", + "description": "A JupyterLab extension for rendering HoloViz content.", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/holoviz/pyviz_comms", + "bugs": { + "url": "https://github.com/holoviz/pyviz_comms/issues" + }, + "license": "BSD-3-Clause", + "author": { + "name": "Philipp Rudiger" + }, + "files": [ + "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", + "style/**/*.{css,.js,eot,gif,html,jpg,json,png,svg,woff2,ttf}", + "schema/*.json", + "style/index.js" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "repository": { + "type": "git", + "url": "https://github.com/holoviz/pyviz_comms.git" + }, + "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 pyviz_comms/labextension pyviz_comms/_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 prettier && jlpm eslint", + "lint:check": "jlpm prettier:check && jlpm eslint:check", + "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:src": "tsc -w --sourceMap" + }, + "dependencies": { + "@jupyterlab/application": "^4.0.3", + "@jupyterlab/apputils": "^4.1.3", + "@jupyterlab/coreutils": "^6.0.3", + "@jupyterlab/docregistry": "^4.0.3", + "@jupyterlab/fileeditor": "^4.0.3", + "@jupyterlab/mainmenu": "^4.0.3", + "@jupyterlab/notebook": "^4.0.3", + "@jupyterlab/settingregistry": "^4.0.3", + "@jupyterlab/ui-components": "^4.0.3", + "@lumino/coreutils": "^2.1.1", + "@lumino/signaling": "^2.1.1", + "tippy.js": "^6" + }, + "resolutions": { + "@lumino/widgets": "^2.1.1", + "react": "^17.0.1", + "react-dom": "^17.0.1" + }, + "peerDependencies": { + "@jupyter-widgets/base": "^2 || ^3 || ^4 || ^5 || ^6", + "@jupyter-widgets/jupyterlab-manager": "^5.0.4" + }, + "devDependencies": { + "@jupyter-widgets/base": "^2 || ^3 || ^4 || ^5 || ^6", + "@jupyter-widgets/jupyterlab-manager": "^5.0.7", + "@jupyterlab/builder": "^4.0.0", + "@jupyterlab/testutils": "^3.0.0", + "@types/json-schema": "^7.0.11", + "@types/node": "^14.14.16", + "@types/react": "^18.0.26", + "@types/react-dom": "^17.0.0", + "@typescript-eslint/eslint-plugin": "^5.55.0", + "@typescript-eslint/parser": "^5.55.0", + "css-loader": "^6.7.1", + "eslint": "^8.36.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.0.0", + "npm-run-all": "^4.1.5", + "prettier": "^3.0.0", + "rimraf": "^4.4.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" + }, + "sideEffects": [ + "style/*.css", + "style/index.js" + ], + "styleModule": "style/index.js", + "jupyterlab": { + "extension": true, + "outputDir": "pyviz_comms/labextension", + "schemaDir": "schema", + "sharedPackages": { + "@jupyter-widgets/jupyterlab-manager": { + "bundled": false, + "singleton": true + }, + "@jupyter-widgets/base": { + "bundled": false, + "singleton": true + } } + } } diff --git a/pyviz_comms/__init__.py b/pyviz_comms/__init__.py index bac6ce5..877fb37 100644 --- a/pyviz_comms/__init__.py +++ b/pyviz_comms/__init__.py @@ -3,6 +3,7 @@ import uuid import traceback import json +import builtins try: from StringIO import StringIO @@ -24,11 +25,11 @@ def _jupyter_labextension_paths(): 'dest': data['name'] }] -# Required only to monkeypatch get_ipython in the test suite -try: - get_ipython() -except NameError: - get_ipython = None +_in_ipython = hasattr(builtins, '__IPYTHON__') + +# Setting this so we can check the launched jupyter has pyviz_comms installed +if not (_in_ipython and sys.argv[0].endswith('ipykernel_launcher.py')): + os.environ['_PYVIZ_COMMS_INSTALLED'] = '1' # nb_mime_js is used to enable the necessary mime type support in classic notebook comm_path = os.path.dirname(os.path.abspath(__file__)) @@ -53,14 +54,12 @@ class extension(param.ParameterizedFunction): _repeat_execution_in_cell = False def __new__(cls, *args, **kwargs): - try: - exec_count = get_ipython().execution_count + if _in_ipython: + exec_count = get_ipython().execution_count # noqa: F821 extension._repeat_execution_in_cell = (exec_count == cls._last_execution_count) # Update the last count on this base class only so that every new instance # creation obtains the updated count. extension._last_execution_count = exec_count - except Exception: - pass return param.ParameterizedFunction.__new__(cls, *args, **kwargs) @classmethod @@ -611,7 +610,7 @@ class JupyterCommManager(CommManager): } return messages.next().then(processIteratorResult); } - }) + }) var sendClosure = (data, metadata, buffers, disposeOnDone) => { return comm_promise.then((comm) => { comm.send(data, metadata, buffers, disposeOnDone); diff --git a/pyviz_comms/tests/test_extension.py b/pyviz_comms/tests/test_extension.py index f03613f..5e2d991 100644 --- a/pyviz_comms/tests/test_extension.py +++ b/pyviz_comms/tests/test_extension.py @@ -1,8 +1,10 @@ +import builtins + import pytest + import pyviz_comms from pyviz_comms import extension - # Store the default values to reset them in the get_ipython fixture LAST_EXECUTION_COUNT = extension._last_execution_count REPEAT_EXECUTION_IN_CELL = extension._repeat_execution_in_cell @@ -23,18 +25,19 @@ def bump(cls): def _get_ipython(): return ExecutionCount - + + builtins.get_ipython = _get_ipython + pyviz_comms._in_ipython = True + yield _get_ipython extension._last_execution_count = LAST_EXECUTION_COUNT extension._repeat_execution_in_cell = REPEAT_EXECUTION_IN_CELL -def test_get_ipython_fixture(monkeypatch, get_ipython): +def test_get_ipython_fixture(get_ipython): # Test the get_ipython fixture - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) - class sub_extension(extension): def __call__(self, *args, **params): pass @@ -60,9 +63,7 @@ def test_get_ipython_fixture_reset(get_ipython): assert extension._repeat_execution_in_cell == REPEAT_EXECUTION_IN_CELL -def test_extension_count_one_cell_one_extension(monkeypatch, get_ipython): - - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) +def test_extension_count_one_cell_one_extension(get_ipython): class sub_extension(extension): def __call__(self, *args, **params): @@ -84,9 +85,7 @@ def __call__(self, *args, **params): assert sub_extension._repeat_execution_in_cell == extension._repeat_execution_in_cell -def test_extension_count_one_cell_extensions_branched(monkeypatch, get_ipython): - - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) +def test_extension_count_one_cell_extensions_branched(get_ipython): class sub_extension1(extension): def __call__(self, *args, **params): @@ -107,9 +106,7 @@ def __call__(self, *args, **params): assert sub_extension1._repeat_execution_in_cell == extension._repeat_execution_in_cell -def test_extension_count_one_cell_parent_first(monkeypatch, get_ipython): - - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) +def test_extension_count_one_cell_parent_first(get_ipython): class parent_extension(extension): def __call__(self, *args, **params): @@ -132,9 +129,7 @@ def __call__(self, *args, **params): assert parent_extension._repeat_execution_in_cell is True -def test_extension_count_one_cell_subclass_first(monkeypatch, get_ipython): - - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) +def test_extension_count_one_cell_subclass_first(get_ipython): class parent_extension(extension): def __call__(self, *args, **params): @@ -153,9 +148,7 @@ def __call__(self, *args, **params): assert parent_extension._repeat_execution_in_cell is True -def test_extension_count_two_cells_one_extension(monkeypatch, get_ipython): - - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) +def test_extension_count_two_cells_one_extension(get_ipython): class sub_extension(extension): def __call__(self, *args, **params): @@ -183,9 +176,8 @@ def __call__(self, *args, **params): assert sub_extension._repeat_execution_in_cell == extension._repeat_execution_in_cell -def test_extension_count_two_cells_extensions_branched(monkeypatch, get_ipython): +def test_extension_count_two_cells_extensions_branched(get_ipython): - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) class sub_extension1(extension): def __call__(self, *args, **params): @@ -228,9 +220,7 @@ def __call__(self, *args, **params): assert sub_extension1._repeat_execution_in_cell == extension._repeat_execution_in_cell -def test_extension_count_two_cells_parent_first(monkeypatch, get_ipython): - - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) +def test_extension_count_two_cells_parent_first(get_ipython): class parent_extension(extension): def __call__(self, *args, **params): @@ -271,9 +261,7 @@ def __call__(self, *args, **params): assert sub_extension._repeat_execution_in_cell == extension._repeat_execution_in_cell -def test_extension_count_two_cells_subclass_first(monkeypatch, get_ipython): - - monkeypatch.setattr(pyviz_comms, 'get_ipython', get_ipython) +def test_extension_count_two_cells_subclass_first(get_ipython): class parent_extension(extension): def __call__(self, *args, **params):