From b36454a787b4841531029741dbec93aa3be265b4 Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Fri, 7 Feb 2025 01:57:36 -0500 Subject: [PATCH] Restore usage of flake8 and add to CI (#316) * Restore flake8 configuration * Fix f-strings missing placeholders * Fix undefined local with import star * Fix end of file should have one empty line * Fix trailing whitespace * Add pre-commit hooks * Add lint step to CI * Add pre-commit and hatch to dev dependencies * Add linting contributing instructions * Fix CI failure for old actions/cache version * Ignore duplicate files in wheel --- .babelrc | 2 +- .bowerrc | 2 +- .flake8 | 10 + .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/workflows/check-release.yml | 2 +- .github/workflows/pythonpackage.yml | 11 + .pre-commit-config.yaml | 12 + CONTRIBUTING.rst | 31 ++- RELEASE.md | 2 +- docs-translations/hi-IN/README.md | 4 +- docs-translations/ja-JP/README.md | 2 +- docs-translations/ko-KR/HowtoRun.md | 18 +- docs-translations/ko-KR/Installation.md | 8 +- docs-translations/ko-KR/README.md | 4 +- docs-translations/ko-KR/UIComponents.md | 5 - docs-translations/zh-CN/README.md | 4 +- docs/Makefile | 2 +- docs/autogen_config.py | 4 +- docs/jsdoc_config.json | 2 +- docs/jsdoc_plugin.js | 2 +- docs/shimming.md | 1 - .../_templates/sidebar-nav-bs-index.html | 4 +- docs/source/config_docs.rst | 2 +- docs/source/config_overview.rst | 2 +- docs/source/examples/utils/list_pyfiles.ipy | 2 +- docs/source/examples/utils/list_subdirs.ipy | 2 +- docs/source/extending/contents.rst | 12 +- docs/source/extending/frontend_extensions.rst | 4 +- docs/source/extending/keymaps.rst | 22 +- docs/source/frontend_config.rst | 2 +- docs/source/index.rst | 4 +- docs/source/nbclassic.rst | 20 +- docs/source/nbclassic_dev_faq.rst | 11 +- docs/source/notebook.rst | 2 +- docs/source/public_server.rst | 2 +- docs/source/user_docs.rst | 1 - git-hooks/README.md | 2 +- jupyter_server_config.d/nbclassic.json | 2 +- nbclassic/_sysinfo.py | 1 - nbclassic/bundler/__main__.py | 4 +- nbclassic/bundler/bundlerextensions.py | 52 ++-- nbclassic/bundler/handlers.py | 14 +- nbclassic/bundler/tarball_bundler.py | 4 +- .../resources/another_subdir/test_file.txt | 2 +- nbclassic/bundler/tests/resources/empty.ipynb | 2 +- .../tests/resources/subdir/test_file.txt | 2 +- nbclassic/bundler/tests/test_bundler_api.py | 8 +- nbclassic/bundler/tests/test_bundler_tools.py | 2 +- .../bundler/tests/test_bundlerextension.py | 16 +- nbclassic/bundler/zip_bundler.py | 12 +- nbclassic/i18n/babel_nbui.cfg | 2 +- nbclassic/i18n/fr_FR/LC_MESSAGES/nbclassic.po | 1 - nbclassic/i18n/zh_CN/LC_MESSAGES/nbclassic.po | 1 - nbclassic/i18n/zh_CN/LC_MESSAGES/nbjs.po | 1 - nbclassic/i18n/zh_CN/LC_MESSAGES/nbui.po | 1 - nbclassic/notebookapp.py | 4 +- nbclassic/shim.py | 2 +- nbclassic/shim_notebook.py | 6 +- nbclassic/static/acc_overwrite.less | 5 +- nbclassic/static/auth/less/logout.less | 1 - nbclassic/static/auth/less/style.less | 2 +- nbclassic/static/base/js/dialog.js | 30 +-- nbclassic/static/base/js/events.js | 6 +- nbclassic/static/base/js/keyboard.js | 42 ++-- nbclassic/static/base/js/markdown.js | 2 +- nbclassic/static/base/js/mathjaxutils.js | 4 +- nbclassic/static/base/js/namespace.js | 12 +- .../static/base/js/notificationwidget.js | 2 +- nbclassic/static/base/js/utils.js | 70 +++--- nbclassic/static/base/less/flexbox.less | 52 ++-- nbclassic/static/base/less/page.less | 2 +- nbclassic/static/bidi/numericshaping.js | 14 +- nbclassic/static/custom/custom-preload.js | 1 - nbclassic/static/custom/custom.css | 1 - nbclassic/static/edit/js/editor.js | 26 +- nbclassic/static/edit/js/main.js | 14 +- nbclassic/static/edit/js/menubar.js | 16 +- nbclassic/static/edit/js/notificationarea.js | 10 +- nbclassic/static/edit/js/savewidget.js | 10 +- nbclassic/static/edit/less/edit.less | 2 +- nbclassic/static/notebook/js/about.js | 2 +- nbclassic/static/notebook/js/cell.js | 40 +-- nbclassic/static/notebook/js/celltoolbar.js | 8 +- .../notebook/js/celltoolbarpresets/tags.js | 2 +- nbclassic/static/notebook/js/codecell.js | 40 +-- .../static/notebook/js/commandpalette.js | 6 +- nbclassic/static/notebook/js/completer.js | 6 +- .../static/notebook/js/kernelselector.js | 44 ++-- .../static/notebook/js/keyboardmanager.js | 18 +- nbclassic/static/notebook/js/main.js | 10 +- nbclassic/static/notebook/js/menubar.js | 52 ++-- nbclassic/static/notebook/js/notebook.js | 228 +++++++++--------- .../static/notebook/js/notificationarea.js | 16 +- nbclassic/static/notebook/js/pager.js | 8 +- nbclassic/static/notebook/js/quickhelp.js | 18 +- nbclassic/static/notebook/js/savewidget.js | 10 +- nbclassic/static/notebook/js/scrollmanager.js | 18 +- .../static/notebook/js/searchandreplace.js | 8 +- .../static/notebook/js/shortcuteditor.js | 20 +- nbclassic/static/notebook/js/textcell.js | 20 +- nbclassic/static/notebook/js/tooltip.js | 6 +- nbclassic/static/notebook/js/tour.js | 21 +- nbclassic/static/notebook/less/cell.less | 10 +- .../static/notebook/less/celltoolbar.less | 2 +- .../static/notebook/less/commandpalette.less | 4 +- .../static/notebook/less/highlight-refs.less | 2 +- nbclassic/static/notebook/less/menubar.less | 10 +- nbclassic/static/notebook/less/modal.less | 6 +- .../notebook/less/notificationarea.less | 8 +- .../notebook/less/notificationwidget.less | 1 - .../static/notebook/less/outputarea.less | 6 +- nbclassic/static/notebook/less/pager.less | 6 +- .../static/notebook/less/renderedhtml.less | 5 +- .../static/notebook/less/savewidget.less | 4 +- .../notebook/less/searchandreplace.less | 8 +- nbclassic/static/notebook/less/textcell.less | 2 +- nbclassic/static/notebook/less/tooltip.less | 2 +- nbclassic/static/robots.txt | 2 +- nbclassic/static/services/config.js | 26 +- nbclassic/static/services/contents.js | 8 +- nbclassic/static/services/kernels/comm.js | 46 ++-- nbclassic/static/services/kernels/kernel.js | 48 ++-- .../static/services/kernels/serialize.js | 12 +- nbclassic/static/terminal/js/main.js | 10 +- nbclassic/static/terminal/js/terminado.js | 4 +- nbclassic/static/tree/js/kernellist.js | 8 +- nbclassic/static/tree/js/main.js | 16 +- nbclassic/static/tree/js/newnotebook.js | 12 +- nbclassic/static/tree/js/sessionlist.js | 4 +- nbclassic/static/tree/js/terminallist.js | 8 +- nbclassic/static/tree/less/style.less | 2 +- nbclassic/templates/404.html | 1 - nbclassic/templates/page.html | 18 +- nbclassic/templates/tree.html | 10 +- nbclassic/tests/README.md | 2 +- nbclassic/tests/base/highlight.js | 4 +- nbclassic/tests/base/misc.js | 2 +- nbclassic/tests/base/security.js | 12 +- nbclassic/tests/base/utils.js | 8 +- nbclassic/tests/end_to_end/conftest.py | 2 +- .../end_to_end/test_clipboard_multiselect.py | 2 +- .../tests/end_to_end/test_dashboard_nav.py | 20 +- .../end_to_end/test_display_isolation.py | 2 +- nbclassic/tests/end_to_end/test_save.py | 3 +- .../tests/end_to_end/test_save_as_notebook.py | 6 +- .../tests/end_to_end/test_save_readonly_as.py | 6 +- nbclassic/tests/end_to_end/test_shutdown.py | 4 +- nbclassic/tests/notebook/attachments.js | 1 - nbclassic/tests/notebook/display_id.js | 4 +- nbclassic/tests/notebook/dualmode.js | 2 +- nbclassic/tests/notebook/dualmode_merge.js | 2 +- .../tests/notebook/execute_selected_cells.js | 4 +- nbclassic/tests/notebook/inject_js.js | 2 +- nbclassic/tests/notebook/markdown.js | 4 +- nbclassic/tests/notebook/output.js | 22 +- nbclassic/tests/notebook/roundtrip.js | 52 ++-- .../tests/notebook/safe_append_output.js | 2 +- nbclassic/tests/notebook/tags.js | 10 +- nbclassic/tests/services/kernel.js | 4 +- nbclassic/tests/services/serialize.js | 16 +- nbclassic/tests/util.js | 58 ++--- nbclassic/view/__init__.py | 2 +- nbclassic/view/handlers.py | 4 +- pyproject.toml | 9 + tools/build-main.js | 2 +- tools/security_deprecated.js | 24 +- tools/tests/CSS Reference.ipynb | 2 +- 169 files changed, 971 insertions(+), 931 deletions(-) create mode 100644 .flake8 create mode 100644 .pre-commit-config.yaml diff --git a/.babelrc b/.babelrc index cea726b87..169fbc0e2 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,3 @@ -{ +{ "presets": ["es2015"], } diff --git a/.bowerrc b/.bowerrc index 25442973e..0aef146bb 100644 --- a/.bowerrc +++ b/.bowerrc @@ -1,3 +1,3 @@ { "directory": "nbclassic/static/components" -} \ No newline at end of file +} diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..0b5fe4677 --- /dev/null +++ b/.flake8 @@ -0,0 +1,10 @@ +[flake8] +ignore = E, C, W, F401, F403, F811, F841, E402, I100, I101, D400 +builtins = c, get_config +exclude = + .cache, + .github, + docs, + .venv, + dist, + build diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 6b41c8fef..c8bd51c1d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -69,4 +69,4 @@ Paste the output from your command line running `jupyter nbclassic` here, use `- Paste the output from your browser Javascript console here, if applicable. - \ No newline at end of file + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 9f3008ad7..cc1b15a85 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,4 +2,4 @@ blank_issues_enabled: false contact_links: - name: Is this a common issue? See our Docs. url: https://nbclassic.readthedocs.io/en/latest/troubleshooting.html#what-to-do-when-things-go-wrong - about: Before opening an issue, make sure your issue hasn't already been addressed in the documentation. \ No newline at end of file + about: Before opening an issue, make sure your issue hasn't already been addressed in the documentation. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 47ad95cf2..31394daf5 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -36,4 +36,4 @@ Finally, please answer the following questions for yourself before submitting an \ No newline at end of file +--> diff --git a/.github/workflows/check-release.yml b/.github/workflows/check-release.yml index e5926657b..4d95a6a57 100644 --- a/.github/workflows/check-release.yml +++ b/.github/workflows/check-release.yml @@ -48,7 +48,7 @@ jobs: pip install -e . - name: Check Release if: ${{ matrix.group == 'check_release' }} - uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v1 + uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 with: version_spec: 100.100.100 token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 94e0c369e..78c6dbfb8 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -7,6 +7,17 @@ on: pull_request: jobs: + lint: + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5.3.0 + with: + python-version: '3.13' + - name: Lint with Pre-commit + uses: pre-commit/action@v3.0.1 build: runs-on: ${{ matrix.os }} strategy: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..c9e12e847 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,12 @@ +repos: +- repo: https://github.com/pycqa/flake8 + rev: 'e43806be3607110919eff72939fda031776e885a' # frozen: 7.1.1 + hooks: + - id: flake8 +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # frozen: v5.0.0 + hooks: + - id: check-yaml + - id: check-toml + - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 420c9ac5c..28be6f62f 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -84,6 +84,33 @@ running other instances of Jupyter NbClassic. You can try the following steps: a port that is neither the default nor in use, then it should be fine. 5. Verify the installation with the steps in the previous section. +Code Formatting and Linting +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All source code is linted using `Flake8 `_. When +code is modified and committed, staged files are automatically checked for PEP 8 +compliance using pre-commit git hooks (with help from `pre-commit +`_). Using a linter like `flake8` helps +maintain consistent code style and catches potential errors during pull request +reviews, streamlining the review process. Other checks are also run to look for +proper new lines at the end of files and to remove unnecessary whitespace. + +To install `pre-commit`, run:: + + pip install -e ".[dev]" + pre-commit install + +You can manually trigger the pre-commit hook at any time with:: + + pre-commit run + +This will check your code against the pre-commit checks and report any style +violations or potential issues. + +If you committed files before setting up the pre-commit hook with +`pre-commit install`, you can check all files using +`pre-commit run --all-files`. You will need to fix any reported issues and commit +the changes yourself afterward. Rebuilding JavaScript and CSS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -137,9 +164,9 @@ To run the Python tests, use:: For the end to end Pytest-Playwright tests you will need to install the browser binaries using:: playwright install - + Then you can run the end to end tests using:: - + pytest -sv nbclassic/tests/end_to_end If you want coverage statistics as well, you can run:: diff --git a/RELEASE.md b/RELEASE.md index 77e58889e..c7cbbd564 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -16,6 +16,6 @@ git clean -dffx python -m build tbump pip install twine -twine check dist/* +twine check dist/* twine upload dist/* ``` diff --git a/docs-translations/hi-IN/README.md b/docs-translations/hi-IN/README.md index 1774a3bcd..72cbaa04c 100644 --- a/docs-translations/hi-IN/README.md +++ b/docs-translations/hi-IN/README.md @@ -3,7 +3,7 @@ [![Google Group](https://img.shields.io/badge/-Google%20Group-lightgrey.svg)](https://groups.google.com/forum/#!forum/jupyter) [![Build Status](https://travis-ci.org/jupyter/notebook.svg?branch=master)](https://travis-ci.org/jupyter/notebook) [![Documentation Status](https://readthedocs.org/projects/jupyter-notebook/badge/?version=latest)](https://jupyter-notebook.readthedocs.io/en/stable/?badge=latest) - + Jupyter नोटबुक इंटरैक्टिव के लिए एक वेब-आधारित नोटबुक वातावरण है @@ -74,4 +74,4 @@ IPython कोडबेस का बिग स्प्लिट ™। IPython - [Korean Version of Installation](https://github.com/ChungJooHo/Jupyter_Kor_doc/) - [Documentation for Project Jupyter](https://jupyter.readthedocs.io/en/latest/index.html ) - [Issues](https://github.com/jupyter/nbclassic/issues) -- [Technical support - Jupyter Google Group](https://groups.google.com/forum/#!forum/jupyter) +- [Technical support - Jupyter Google Group](https://groups.google.com/forum/#!forum/jupyter) diff --git a/docs-translations/ja-JP/README.md b/docs-translations/ja-JP/README.md index 1c2b2667c..f408a7201 100644 --- a/docs-translations/ja-JP/README.md +++ b/docs-translations/ja-JP/README.md @@ -3,7 +3,7 @@ [![Google Group](https://img.shields.io/badge/-Google%20Group-lightgrey.svg)](https://groups.google.com/forum/#!forum/jupyter) [![Build Status](https://travis-ci.org/jupyter/notebook.svg?branch=master)](https://travis-ci.org/jupyter/notebook) [![Documentation Status](https://readthedocs.org/projects/jupyter-notebook/badge/?version=latest)](https://jupyter-notebook.readthedocs.io/en/stable/?badge=latest) - + 英語版のリンク : [[English Version](http://github.com/jupyter/nbclassic/)] Jupyter Notebookは、インタラクティブなWebベースのノートブック形式の環境です。 diff --git a/docs-translations/ko-KR/HowtoRun.md b/docs-translations/ko-KR/HowtoRun.md index eb070dea5..813acdf86 100644 --- a/docs-translations/ko-KR/HowtoRun.md +++ b/docs-translations/ko-KR/HowtoRun.md @@ -1,6 +1,6 @@ # Notebook 실행하기 - ## 첫 걸음 + ## 첫 걸음 1. 다음 명령어를 통해 Notebook 서버를 시작하세요 : $ jupyter notebook @@ -9,7 +9,7 @@ # Notebook 서버 시작하기 - + Notebook을 컴퓨터에 설치하였으면 Notebook 서버를 시작할 수 있습니다. 다음 명령어를 이용하여 Notebook서버를 시작할 수 있습니다. $ jupyter notebook @@ -19,12 +19,12 @@ $ jupyter notebook $ [I 08:58:24.417 NotebookApp] Serving notebooks from local directory: /Users/catherline $ [I 08:58:24.417 NotebookApp] 0 active kernels - $ [I 08:58:24.417 NotebookApp] The Jupyter Notebook is running at: http://localhost:8888/ + $ [I 08:58:24.417 NotebookApp] The Jupyter Notebook is running at: http://localhost:8888/ $ [I 08:58:24.417 NotebookApp] Use Control-C to stop this server and shut down all kernels 기본 브라우저를 통해 이 주소가 열립니다. - Notebook이 브라우저에 열리면, Notebook의 목록을 보여주는 Notebook Dashboard를 볼 수 있습니다. 대체로 가장 상위의 디렉토리를 열어줄 것입니다. + Notebook이 브라우저에 열리면, Notebook의 목록을 보여주는 Notebook Dashboard를 볼 수 있습니다. 대체로 가장 상위의 디렉토리를 열어줄 것입니다. **Notebook Dashboard** @@ -33,9 +33,9 @@ # Notebook 서버의 명령어 소개 ## 커스텀 IP 나 포트를 이용하여 시작하려면 어떻게 해야할까? - + 기본값으로, Notebook 서버는 포트 8888로 시작됩니다. 만약 포트8888이 사용할 수 없다면, Notebook 서버는 다른 가능한 포트를 찾습니다. 또한 임의로 포트를 설정해주는 것도 가능합니다. 예를 들어 포트 9999로 실행하면 : - + $ jupyter notebook --port 9999 @@ -45,13 +45,9 @@ $ jupyter notebook --no-browser - + ## Notebook 서버 옵션 도움말 보기 Notebook 서버는 --help 옵션을 통해 도움말 메시지를 제공합니다 : $ jupyter notebook --help - - - - diff --git a/docs-translations/ko-KR/Installation.md b/docs-translations/ko-KR/Installation.md index d5375d3b5..65acd343b 100644 --- a/docs-translations/ko-KR/Installation.md +++ b/docs-translations/ko-KR/Installation.md @@ -10,8 +10,8 @@ Python과 Jupyter를 설치할 때 Anaconda를 이용하는 것을 추천합니 새로운 이용자들은 Anaconda를 설치하는 것을 강력하게 추천합니다. Anaconda는 Python과 Jupyter를 쉽게 설치하게 해주고, 과학적인 계산과 데이터를 위한 자주 사용되는 패키지들의 설치에도 유용합니다. -설치 순서 : - +설치 순서 : + 1. Anaconda를 다운받으세요. Anaconda의 가장 최신의 Python 3버전을 다운 받는 것을 추천합니다. 2. 다운 받은 Anaconda 의 다운로드 페이지에 있는 설명을 읽고 설치해주세요. 3. 축하합니다. Jupyter Notebook 을 설치하셨습니다. Jupyter Notebook을 실행하려면 : @@ -19,11 +19,11 @@ Python과 Jupyter를 설치할 때 Anaconda를 이용하는 것을 추천합니 $ jupyter notebook ## 숙련된 Python 이용자 : pip을 통해 설치하기 - + Python 이용자라면, Anaconda 대신에 Python의 패키지 매니저 pip을 이용하여 설치하세요. 첫째로, 가장 최신의 pip인지를 확인하세요; 구 버전은 독립성에 문제가 있을 수 있습니다. - + $ pip install --upgrade pip 이제 다음을 이용하여 Jupyter Notebook를 설치하세요 : diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 0c6b135f7..a5431aa13 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -3,7 +3,7 @@ [![Google Group](https://img.shields.io/badge/-Google%20Group-lightgrey.svg)](https://groups.google.com/forum/#!forum/jupyter) [![Build Status](https://travis-ci.org/jupyter/notebook.svg?branch=master)](https://travis-ci.org/jupyter/notebook) [![Documentation Status](https://readthedocs.org/projects/jupyter-notebook/badge/?version=latest)](http://jupyter-notebook.readthedocs.io/en/stable/?badge=stable) - + English 버전 링크 : [[English Version](http://github.com/jupyter/nbclassic/)] Jupyter notebook 은 상호 교환을 위한 웹 기반 환경입니다. @@ -25,7 +25,7 @@ You can find the installation documentation for the 조금 더 심화된 Jupyter notebook의 사용은 다음 주소에서 볼 수 있습니다. [here](https://jupyter-notebook.readthedocs.io/en/stable/). -설치를 위해서는 +설치를 위해서는 [pip installed](https://pip.readthedocs.io/en/stable/installing/) 가 있는지 확인한 후 다음을 실행해주세요: $ pip install notebook diff --git a/docs-translations/ko-KR/UIComponents.md b/docs-translations/ko-KR/UIComponents.md index c582c7ead..f5487e0d2 100644 --- a/docs-translations/ko-KR/UIComponents.md +++ b/docs-translations/ko-KR/UIComponents.md @@ -31,8 +31,3 @@ jupyter notebook 명령어를 실행하면 가장 먼저 Notebook Dashboard가 이제 Notebook Dashboard 안의 Notebook 파일이 아닌 표시된 파일을 선택하여 열어야한다고 한다면, 파일은 파일 편집기로 열립니다. ![File Editor example](resources/file_editor.GIF "File Editor") - - - - - diff --git a/docs-translations/zh-CN/README.md b/docs-translations/zh-CN/README.md index 9e97d46e9..e87eaff6a 100644 --- a/docs-translations/zh-CN/README.md +++ b/docs-translations/zh-CN/README.md @@ -3,7 +3,7 @@ [![Google Group](https://img.shields.io/badge/-Google%20Group-lightgrey.svg)](https://groups.google.com/forum/#!forum/jupyter) [![Build Status](https://travis-ci.org/jupyter/notebook.svg?branch=master)](https://travis-ci.org/jupyter/notebook) [![Documentation Status](https://readthedocs.org/projects/jupyter-notebook/badge/?version=latest)](https://jupyter-notebook.readthedocs.io/en/stable/?badge=latest) - + Jupyter Notebook是用于交互的基于Web的笔记本环境 @@ -74,4 +74,4 @@ IPython代码库的Big Split™。 IPython 3是最后一个主要的整体 - [Korean Version of Installation](https://github.com/ChungJooHo/Jupyter_Kor_doc/) - [Documentation for Project Jupyter](https://jupyter.readthedocs.io/en/latest/index.html ) - [Issues](https://github.com/jupyter/nbclassic/issues) -- [Technical support - Jupyter Google Group](https://groups.google.com/forum/#!forum/jupyter) +- [Technical support - Jupyter Google Group](https://groups.google.com/forum/#!forum/jupyter) diff --git a/docs/Makefile b/docs/Makefile index 02cb617a3..1765c64af 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -176,7 +176,7 @@ linkcheck: @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." - + spelling: $(SPHINXBUILD) -b spelling $(ALLSPHINXOPTS) $(BUILDDIR)/spelling @echo "Spell check complete; look for any errors in the above output " \ diff --git a/docs/autogen_config.py b/docs/autogen_config.py index 6e654be7c..3cd7a989d 100644 --- a/docs/autogen_config.py +++ b/docs/autogen_config.py @@ -11,7 +11,7 @@ ==================================== The notebook server can be run with a variety of command line arguments. -A list of available options can be found below in the :ref:`options section +A list of available options can be found below in the :ref:`options section `. Defaults for these options can also be set by creating a file named @@ -29,7 +29,7 @@ Options ------- -This list of options can be generated by running the following and hitting +This list of options can be generated by running the following and hitting enter:: $ jupyter notebook --help diff --git a/docs/jsdoc_config.json b/docs/jsdoc_config.json index 91bf96d04..d8cfb200b 100644 --- a/docs/jsdoc_config.json +++ b/docs/jsdoc_config.json @@ -2,7 +2,7 @@ "markdown": { "parser": "gfm" }, - "plugins": [ + "plugins": [ "plugins/markdown" , "jsdoc_plugin.js" ], diff --git a/docs/jsdoc_plugin.js b/docs/jsdoc_plugin.js index 3fa303502..b4e4d2b0e 100644 --- a/docs/jsdoc_plugin.js +++ b/docs/jsdoc_plugin.js @@ -9,4 +9,4 @@ exports.handlers = { } } } -}; \ No newline at end of file +}; diff --git a/docs/shimming.md b/docs/shimming.md index f96cdda0e..ce747477c 100644 --- a/docs/shimming.md +++ b/docs/shimming.md @@ -66,4 +66,3 @@ Here's a snapshot of how JupyterApp's are initialized. The order of operations w ``` ## Where do we add the steps above? - diff --git a/docs/source/_templates/sidebar-nav-bs-index.html b/docs/source/_templates/sidebar-nav-bs-index.html index d43999f30..b717f06c9 100644 --- a/docs/source/_templates/sidebar-nav-bs-index.html +++ b/docs/source/_templates/sidebar-nav-bs-index.html @@ -7,7 +7,7 @@ font-weight: bold; } - + \ No newline at end of file + diff --git a/docs/source/config_docs.rst b/docs/source/config_docs.rst index 669da0096..c6a427763 100644 --- a/docs/source/config_docs.rst +++ b/docs/source/config_docs.rst @@ -12,4 +12,4 @@ Configuration security frontend_config examples/Notebook/Distributing Jupyter Extensions as Python Packages - extending/index.rst \ No newline at end of file + extending/index.rst diff --git a/docs/source/config_overview.rst b/docs/source/config_overview.rst index 523d03969..0edac7fa3 100644 --- a/docs/source/config_overview.rst +++ b/docs/source/config_overview.rst @@ -49,7 +49,7 @@ front-end NbClassic client (i.e. the familiar notebook interface). $ jupyter nbclassic --generate-config :ref:`Command line arguments for configuration ` settings are documented in the configuration file and the user documentation. - + - Review the section: :ref:`Running a Notebook server ` - Related: `Configuring a language kernel `_ to run in the Notebook server enables your server to run other languages, like R or Julia. diff --git a/docs/source/examples/utils/list_pyfiles.ipy b/docs/source/examples/utils/list_pyfiles.ipy index 71a9e5d75..4b15482e7 100644 --- a/docs/source/examples/utils/list_pyfiles.ipy +++ b/docs/source/examples/utils/list_pyfiles.ipy @@ -3,4 +3,4 @@ from IPython.display import FileLink, display files =!ls *.py for f in files: - display(FileLink(f)) \ No newline at end of file + display(FileLink(f)) diff --git a/docs/source/examples/utils/list_subdirs.ipy b/docs/source/examples/utils/list_subdirs.ipy index a1bbb74ca..b8a161245 100644 --- a/docs/source/examples/utils/list_subdirs.ipy +++ b/docs/source/examples/utils/list_subdirs.ipy @@ -4,4 +4,4 @@ from IPython.display import FileLinks, display dirs =!ls -d */ for d in dirs: if d != '__pycache__/': - display(FileLinks(d)) \ No newline at end of file + display(FileLinks(d)) diff --git a/docs/source/extending/contents.rst b/docs/source/extending/contents.rst index b37a9c99a..7e480268d 100644 --- a/docs/source/extending/contents.rst +++ b/docs/source/extending/contents.rst @@ -78,7 +78,7 @@ model. There are three model types: **notebook**, **file**, and **directory**. - ``file`` models - The ``format`` field is either ``"text"`` or ``"base64"``. - - The ``mimetype`` field can be any mimetype string, but defaults to + - The ``mimetype`` field can be any mimetype string, but defaults to ``text/plain`` for text-format models and ``application/octet-stream`` for base64-format models. For files with unknown mime types (e.g. unknown file extensions), this field may be @@ -196,7 +196,7 @@ methods: ContentsManager.is_hidden You may be required to specify a Checkpoints object, as the default one, -``FileCheckpoints``, could be incompatible with your custom +``FileCheckpoints``, could be incompatible with your custom ContentsManager. @@ -222,12 +222,12 @@ Customizing Checkpoints ----------------------- .. currentmodule:: notebook.services.contents.checkpoints -Customized Checkpoint definitions allows behavior to be +Customized Checkpoint definitions allows behavior to be altered and extended. The ``Checkpoints`` and ``GenericCheckpointsMixin`` classes (from :mod:`notebook.services.contents.checkpoints`) -have reusable code and are intended to be used together, +have reusable code and are intended to be used together, but require the following methods to be implemented. .. autosummary:: @@ -243,7 +243,7 @@ No-op example ~~~~~~~~~~~~~ Here is an example of a no-op checkpoints object - note the mixin -comes first. The docstrings indicate what each method should do or +comes first. The docstrings indicate what each method should do or return for a more complete implementation. .. code-block:: python @@ -261,7 +261,7 @@ return for a more complete implementation. def delete_checkpoint(self, checkpoint_id, path): """deletes a checkpoint for a file""" def list_checkpoints(self, path): - """returns a list of checkpoint models for a given file, + """returns a list of checkpoint models for a given file, default just does one per file """ return [] diff --git a/docs/source/extending/frontend_extensions.rst b/docs/source/extending/frontend_extensions.rst index 68603107b..3ae2df5f8 100644 --- a/docs/source/extending/frontend_extensions.rst +++ b/docs/source/extending/frontend_extensions.rst @@ -224,8 +224,8 @@ notebook interface to load it. You can do that with another command:: The argument refers to the Javascript module containing your ``load_ipython_extension`` function, which is ``my_extension/main.js`` in this -example. The ``--section='common'`` argument will affect all pages, by default -it will be loaded on the notebook view only. +example. The ``--section='common'`` argument will affect all pages, by default +it will be loaded on the notebook view only. There is a corresponding ``disable`` command to stop using an extension without uninstalling it. diff --git a/docs/source/extending/keymaps.rst b/docs/source/extending/keymaps.rst index 33953bd3c..d1e0faa04 100644 --- a/docs/source/extending/keymaps.rst +++ b/docs/source/extending/keymaps.rst @@ -8,18 +8,18 @@ Customize keymaps which is not guaranteed to be kept in future versions of the notebook, and can be removed or changed without warnings. -The notebook shortcuts that are defined by jupyter both in edit mode and +The notebook shortcuts that are defined by jupyter both in edit mode and command mode are configurable in the frontend configuration file -``~/.jupyter/nbconfig/notebook.json``. The modification of keyboard -shortcuts suffers from several limitations, mainly that your Browser and OS +``~/.jupyter/nbconfig/notebook.json``. The modification of keyboard +shortcuts suffers from several limitations, mainly that your Browser and OS might prevent certain shortcuts from working correctly. If this is the case, there is unfortunately not much that can be done. The second issue can arise -with keyboards that have a layout different than US English. Again, even if +with keyboards that have a layout different than US English. Again, even if we are aware of the issue, there is not much that can be done. -Shortcuts are also limited by the underlying library that handles code and -text editing: CodeMirror. If some keyboard shortcuts are conflicting, the -method described below might not work to create new keyboard shortcuts, +Shortcuts are also limited by the underlying library that handles code and +text editing: CodeMirror. If some keyboard shortcuts are conflicting, the +method described below might not work to create new keyboard shortcuts, especially in the ``edit`` mode of the notebook. @@ -31,9 +31,9 @@ following: - ``keys.command.bind`` - ``keys.edit.bind`` -The first two sections describe which default keyboard shortcuts not to -register at notebook startup time. These are mostly useful if you need to -``unbind`` a default keyboard shortcut before binding it to a new +The first two sections describe which default keyboard shortcuts not to +register at notebook startup time. These are mostly useful if you need to +``unbind`` a default keyboard shortcut before binding it to a new ``command``. The first two sections apply respectively to the ``command`` and ``edit`` @@ -88,5 +88,5 @@ the following: -The name of the available ``commands`` can be find by hovering over the +The name of the available ``commands`` can be find by hovering over the right end of a row in the command palette. diff --git a/docs/source/frontend_config.rst b/docs/source/frontend_config.rst index 40a7e8105..c50adbc09 100644 --- a/docs/source/frontend_config.rst +++ b/docs/source/frontend_config.rst @@ -93,7 +93,7 @@ pages. Persisting configuration settings --------------------------------- -A banner might be shown to users to inform them about news or updates. This +A banner might be shown to users to inform them about news or updates. This banner can be hidden launching the server with the show_banner trait.:: jupyter notebook --NotebookApp.show_banner=False diff --git a/docs/source/index.rst b/docs/source/index.rst index a53b0b74e..8f208e3f9 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -24,6 +24,6 @@ Find out more about configuring NbClassic. :maxdepth: 1 :titlesonly: - contribute_docs + contribute_docs -Additional information about contributing to and developing NbClassic. \ No newline at end of file +Additional information about contributing to and developing NbClassic. diff --git a/docs/source/nbclassic.rst b/docs/source/nbclassic.rst index 58d8dd1df..3143a9eaa 100644 --- a/docs/source/nbclassic.rst +++ b/docs/source/nbclassic.rst @@ -5,7 +5,7 @@ Jupyter NbClassic ================= .. toctree:: :maxdepth: 2 - + Introduction ------------ @@ -13,7 +13,7 @@ The nbclassic package is the implementation of the classic Jupyter Notebook 6 as a Jupyter Server extension. As proposed in the accepted `Jupyter Enhancement Proposal #79`_ the development of this package is due to plans being carried out to create a Notebook 7, that is based on -the modern JupyterLab code-base. +the modern JupyterLab code-base. While Notebook 7 provides a user experience equivalent to that of the classic Notebook 6, the technology stack used is incompatible with @@ -23,7 +23,7 @@ way to continue using the Jupyter Notebook 6 tech-stack as they transition to using the Jupyter Notebook 7. The NbClassic package intends to address that need. -You can read more about the migration impacts and coexistence of NbClassic and Notebook package on +You can read more about the migration impacts and coexistence of NbClassic and Notebook package on the `NbClassic and Notebook migration plan `_ page. .. _Jupyter Enhancement Proposal #79: https://jupyter.org/enhancement-proposals/79-notebook-v7/notebook-v7.html @@ -50,7 +50,7 @@ Configuration ~~~~~~~~~~~~~ To create a ``jupyter_nbclassic_config.py`` file in the ``.jupyter`` directory you can use the following command:: - + $ jupyter nbclassic --generate-config Options @@ -59,7 +59,7 @@ Options You can view a list of the available options by typing:: $ jupyter nbclassic --help - + NbClassic Development --------------------- @@ -71,7 +71,7 @@ endpoints provided by Jupyter Server. *Jupyter Server Extensions* - `Authoring a basic server extension `_ -**The jupyter/notebook Repository**: The original `jupyter/notebook`_ GitHub +**The jupyter/notebook Repository**: The original `jupyter/notebook`_ GitHub repository now holds the codebase for the new Jupyter Notebook (version 7). .. _jupyter/notebook: https://github.com/jupyter/notebook @@ -81,10 +81,10 @@ NbClassic Timeline ------------------ As proposed in the `JEP #79`_, the nbclassic package will continue to be supported with critical security fixes -in the transition period as users move to using the more modern +in the transition period as users move to using the more modern Jupyter Notebook 7. -**Porting Notebook 6 Extensions**: Work being done in parallel. +**Porting Notebook 6 Extensions**: Work being done in parallel. ou can find a helpful list of classical Notebook extensions and corresponding Jupyterlab extensions if available at the `Jupyterlab-contrib website `_. @@ -96,8 +96,8 @@ Known issues Bellow are some known bugs and issues with the NbClassic project. These are items that may be of particular interest to users migrating from notebook to nbclassic. -1. `#140 Error using jupyter_nbextensions_configurator with nbclassic `_ is a -known issue with partial fix `Support nbclassic while updating the static path `_ +1. `#140 Error using jupyter_nbextensions_configurator with nbclassic `_ is a +known issue with partial fix `Support nbclassic while updating the static path `_ pending to be merged into the `Jupyter-contrib/jupyter_nbextensions_configurator `_ repository. Once a release with this fix is available, users will be able to activate the extension with the following commands:: diff --git a/docs/source/nbclassic_dev_faq.rst b/docs/source/nbclassic_dev_faq.rst index 5cac94074..2c2850fb9 100644 --- a/docs/source/nbclassic_dev_faq.rst +++ b/docs/source/nbclassic_dev_faq.rst @@ -2,11 +2,11 @@ The Development of NbClassic ============================ -Here you will find information about some especially noteworthy updates made in NbClassic, issues that have been reported +Here you will find information about some especially noteworthy updates made in NbClassic, issues that have been reported and common questions. -Noteworthy Updates in NbClassic +Noteworthy Updates in NbClassic -------------------------------- - Entrypoints in NbClassic @@ -16,13 +16,13 @@ Noteworthy Updates in NbClassic - ``jupyter nbclassic-serverextension`` - ``jupyter-nbclassic-bundlerextension`` - - The decision to rename these entrypoints came about after some deliberation and consideration for user experience. When considering the confusion that having a more implicit handling of the entrypoints might pose, the concensus was that renaming the entrypoints would allow for more observability and it would help highlight some of the changes that are happening in the Jupyter ecosystem. + - The decision to rename these entrypoints came about after some deliberation and consideration for user experience. When considering the confusion that having a more implicit handling of the entrypoints might pose, the concensus was that renaming the entrypoints would allow for more observability and it would help highlight some of the changes that are happening in the Jupyter ecosystem. .. _`Rename duplicate entrypoints #138`: https://github.com/jupyter/nbclassic/pull/138 - Providing backwards compatibility with the `jupyter_notebook_config.py` file - - With the goal of allowing NbClassic to be installed along with Notebook 7, the release of NbClassic 0.4 included changing the project name from `notebook` to `nbclassic`. In changing the 'name' attribute to be `nbclassic`, the traitlet behavior changed and resulted in the configuration file which was previously named `jupyter_notebook_config`, to be named `jupyter_nbclassic_config`. However, this was updated to manually set the file name to `jupyter_notebook_config`. With this, the configuration file is picked up whether Notebook or NbClassic are installed. + - With the goal of allowing NbClassic to be installed along with Notebook 7, the release of NbClassic 0.4 included changing the project name from `notebook` to `nbclassic`. In changing the 'name' attribute to be `nbclassic`, the traitlet behavior changed and resulted in the configuration file which was previously named `jupyter_notebook_config`, to be named `jupyter_nbclassic_config`. However, this was updated to manually set the file name to `jupyter_notebook_config`. With this, the configuration file is picked up whether Notebook or NbClassic are installed. - Endpoints in NbClassic - NbClassic handlers have been updated to account for Notebook 7 being installed (`Handlers under nbclassic if notebook 7 is found`_). If so, the resources from nbclassic will be served under the ``/nbclassic/`` URL subpath, so as to not interfere with those resources being served by Jupyter Notebook. @@ -44,7 +44,7 @@ NbClassic Developer FAQ For Notebook 6.5.x, as it is intended to be end of life and will receive only bug and security fixes, issues of this type in the frontend should be reported in the `jupyter/nbclassic`_ repository, bug and security issues for the server can be - submitted in the `jupyter/notebook`_ repository. + submitted in the `jupyter/notebook`_ repository. Generally, user interface issues dealing with the nbclassic package can be submitted to the `jupyter/nbclassic`_ repository, while server issues can be @@ -71,4 +71,3 @@ NbClassic Developer FAQ .. _`MeeseeksDev bot`: https://github.com/MeeseeksBox/MeeseeksDev#meeseeksdev-migrate-to-target-orgrepo .. _`allowed organization list`: https://github.com/MeeseeksBox/MeeseeksDev/blob/master/meeseeksdev/__init__.py#L26 .. _`Jupyter Community`: https://jupyter.org/community - diff --git a/docs/source/notebook.rst b/docs/source/notebook.rst index e14a2cd2c..53b32f2a9 100644 --- a/docs/source/notebook.rst +++ b/docs/source/notebook.rst @@ -24,7 +24,7 @@ text, mathematics, images, and rich media representations of objects. .. seealso:: - See the :ref:`installation guide ` on how to install + See the :ref:`installation guide ` on how to install nbclassic and its dependencies. diff --git a/docs/source/public_server.rst b/docs/source/public_server.rst index c8070164e..942d48758 100644 --- a/docs/source/public_server.rst +++ b/docs/source/public_server.rst @@ -378,7 +378,7 @@ server. Known issues ------------ -Below are issues previously reported Notebook server issues and may be applicable to +Below are issues previously reported Notebook server issues and may be applicable to the Jupyter Server package that provides NbClassic's server. Proxies diff --git a/docs/source/user_docs.rst b/docs/source/user_docs.rst index 3d3612999..b1279c856 100644 --- a/docs/source/user_docs.rst +++ b/docs/source/user_docs.rst @@ -14,4 +14,3 @@ User Documentation troubleshooting changelog comms - diff --git a/git-hooks/README.md b/git-hooks/README.md index 959b75289..6a29ec196 100644 --- a/git-hooks/README.md +++ b/git-hooks/README.md @@ -6,4 +6,4 @@ For now, we just have `post-checkout` and `post-merge`, both of which attempt to rebuild javascript and css sourcemaps, so make sure that you have a fully synced repo whenever you checkout or pull. -To use these hooks, run `./install-hooks.sh`. +To use these hooks, run `./install-hooks.sh`. diff --git a/jupyter_server_config.d/nbclassic.json b/jupyter_server_config.d/nbclassic.json index dbe3f8a45..05adb2503 100644 --- a/jupyter_server_config.d/nbclassic.json +++ b/jupyter_server_config.d/nbclassic.json @@ -4,4 +4,4 @@ "nbclassic": true } } -} \ No newline at end of file +} diff --git a/nbclassic/_sysinfo.py b/nbclassic/_sysinfo.py index 2341cb767..ae1ca1b8a 100644 --- a/nbclassic/_sysinfo.py +++ b/nbclassic/_sysinfo.py @@ -94,4 +94,3 @@ def get_sys_info(): p = os.path path = p.realpath(p.dirname(p.abspath(p.join(nbclassic.__file__)))) return pkg_info(path) - diff --git a/nbclassic/bundler/__main__.py b/nbclassic/bundler/__main__.py index cde186dbb..340c5ac30 100644 --- a/nbclassic/bundler/__main__.py +++ b/nbclassic/bundler/__main__.py @@ -3,5 +3,5 @@ from .bundlerextensions import main -if __name__ == '__main__': - main() \ No newline at end of file +if __name__ == '__main__': + main() diff --git a/nbclassic/bundler/bundlerextensions.py b/nbclassic/bundler/bundlerextensions.py index d6aeb5f63..e9b18b9e2 100644 --- a/nbclassic/bundler/bundlerextensions.py +++ b/nbclassic/bundler/bundlerextensions.py @@ -17,14 +17,14 @@ def _get_bundler_metadata(module): """Gets the list of bundlers associated with a Python package. - + Returns a tuple of (the module, [{ 'name': 'unique name of the bundler', 'label': 'file menu item label for the bundler', 'module_name': 'dotted package/module name containing the bundler', 'group': 'download or deploy parent menu item' }]) - + Parameters ---------- @@ -41,9 +41,9 @@ def _get_bundler_metadata(module): def _set_bundler_state(name, label, module_name, group, state, user=True, sys_prefix=False, logger=None): """Set whether a bundler is enabled or disabled. - + Returns True if the final state is the one requested. - + Parameters ---------- name : string @@ -68,14 +68,14 @@ def _set_bundler_state(name, label, module_name, group, state, config_dir = os.path.join( _get_config_dir(user=user, sys_prefix=sys_prefix), 'nbconfig') cm = BaseJSONConfigManager(config_dir=config_dir) - + if logger: logger.info("{} {} bundler {}...".format( "Enabling" if state else "Disabling", name, module_name )) - + if state: cm.update(BUNDLER_SECTION, { BUNDLER_SUBSECTION: { @@ -96,13 +96,13 @@ def _set_bundler_state(name, label, module_name, group, state, return (cm.get(BUNDLER_SECTION) .get(BUNDLER_SUBSECTION, {}) .get(name) is not None) == state - + def _set_bundler_state_python(state, module, user, sys_prefix, logger=None): """Enables or disables bundlers defined in a Python package. - + Returns a list of whether the state was achieved for each bundler. - + Parameters ---------- state : Bool @@ -129,9 +129,9 @@ def _set_bundler_state_python(state, module, user, sys_prefix, logger=None): def enable_bundler_python(module, user=True, sys_prefix=False, logger=None): """Enables bundlers defined in a Python package. - + Returns whether each bundle defined in the packaged was enabled or not. - + Parameters ---------- module : str @@ -147,12 +147,12 @@ def enable_bundler_python(module, user=True, sys_prefix=False, logger=None): """ return _set_bundler_state_python(True, module, user, sys_prefix, logger=logger) - + def disable_bundler_python(module, user=True, sys_prefix=False, logger=None): """Disables bundlers defined in a Python package. - + Returns whether each bundle defined in the packaged was enabled or not. - + Parameters ---------- module : str @@ -176,13 +176,13 @@ class ToggleBundlerExtensionApp(BaseExtensionApp): description = "Enable/disable a bundlerextension in configuration." user = Bool(True, config=True, help="Apply the configuration only for the current user (default)") - + _toggle_value = None - + def _config_file_name_default(self): """The default config file name.""" return 'jupyter_notebook_config' - + def toggle_bundler_python(self, module): """Toggle some extensions in an importable Python module. @@ -210,25 +210,25 @@ def start(self): if self.python: self.toggle_bundler_python(self.extra_args[0]) else: - raise NotImplementedError('Cannot install bundlers from non-Python packages') + raise NotImplementedError('Cannot install bundlers from non-Python packages') class EnableBundlerExtensionApp(ToggleBundlerExtensionApp): """An App that enables bundlerextensions""" name = "jupyter nbclassic-bundlerextension enable" description = """ Enable a bundlerextension in frontend configuration. - + Usage jupyter nbclassic-bundlerextension enable [--system|--sys-prefix] """ _toggle_value = True - + class DisableBundlerExtensionApp(ToggleBundlerExtensionApp): """An App that disables bundlerextensions""" name = "jupyter nbclassic-bundlerextension disable" description = """ Disable a bundlerextension in frontend configuration. - + Usage jupyter nbclassic-bundlerextension disable [--system|--sys-prefix] """ @@ -240,13 +240,13 @@ class ListBundlerExtensionApp(BaseExtensionApp): name = "jupyter nbclassic-extension list" version = __version__ description = "List all nbextensions known by the configuration system" - + def list_nbextensions(self): """List all the nbextensions""" config_dirs = [os.path.join(p, 'nbconfig') for p in jupyter_config_path()] - + print("Known bundlerextensions:") - + for config_dir in config_dirs: head = u' config dir: {}'.format(config_dir) head_shown = False @@ -258,7 +258,7 @@ def list_nbextensions(self): # only show heading if there is an nbextension here print(head) head_shown = True - + for bundler_id, info in data['bundlerextensions'].items(): label = info.get('label') module = info.get('module_name') @@ -269,7 +269,7 @@ def list_nbextensions(self): label, module, GREEN_ENABLED ) print(msg) - + def start(self): """Perform the App's functions as configured""" self.list_nbextensions() diff --git a/nbclassic/bundler/handlers.py b/nbclassic/bundler/handlers.py index 02327aa9d..451d4e123 100644 --- a/nbclassic/bundler/handlers.py +++ b/nbclassic/bundler/handlers.py @@ -41,22 +41,22 @@ def initialize(self): """Make tools module available on the handler instance for compatibility with existing bundler API and ease of reference.""" self.tools = tools - + def get_bundler(self, bundler_id): """ Get bundler metadata from config given a bundler ID. - + Parameters ---------- bundler_id: str Unique bundler ID within the notebook/bundlerextensions config section - + Returns ------- dict Bundler metadata with label, group, and module_name attributes - - + + Raises ------ KeyError @@ -69,7 +69,7 @@ def get_bundler(self, bundler_id): @gen.coroutine def get(self, path): """Bundle the given nbclassic. - + Parameters ---------- path: str @@ -93,7 +93,7 @@ def get(self, path): except UnicodeEncodeError: # Encode unicode as utf-8 in python2 else import_item fails module_name = module_name.encode('utf-8') - + try: bundler_mod = import_item(module_name) except ImportError as e: diff --git a/nbclassic/bundler/tarball_bundler.py b/nbclassic/bundler/tarball_bundler.py index 21ac94cd6..e57f2967e 100644 --- a/nbclassic/bundler/tarball_bundler.py +++ b/nbclassic/bundler/tarball_bundler.py @@ -20,7 +20,7 @@ def _jupyter_bundlerextension_paths(): def bundle(handler, model): """Create a compressed tarball containing the notebook document. - + Parameters ---------- handler : tornado.web.RequestHandler @@ -32,7 +32,7 @@ def bundle(handler, model): notebook_content = nbformat.writes(model['content']).encode('utf-8') notebook_name = os.path.splitext(notebook_filename)[0] tar_filename = '{}.tar.gz'.format(notebook_name) - + info = tarfile.TarInfo(notebook_filename) info.size = len(notebook_content) diff --git a/nbclassic/bundler/tests/resources/another_subdir/test_file.txt b/nbclassic/bundler/tests/resources/another_subdir/test_file.txt index 597cd83d4..e07668237 100644 --- a/nbclassic/bundler/tests/resources/another_subdir/test_file.txt +++ b/nbclassic/bundler/tests/resources/another_subdir/test_file.txt @@ -1 +1 @@ -Used to test globbing. \ No newline at end of file +Used to test globbing. diff --git a/nbclassic/bundler/tests/resources/empty.ipynb b/nbclassic/bundler/tests/resources/empty.ipynb index bbdd6febf..afd318050 100644 --- a/nbclassic/bundler/tests/resources/empty.ipynb +++ b/nbclassic/bundler/tests/resources/empty.ipynb @@ -3,4 +3,4 @@ "cells": [], "nbformat": 4, "metadata": {} -} \ No newline at end of file +} diff --git a/nbclassic/bundler/tests/resources/subdir/test_file.txt b/nbclassic/bundler/tests/resources/subdir/test_file.txt index 597cd83d4..e07668237 100644 --- a/nbclassic/bundler/tests/resources/subdir/test_file.txt +++ b/nbclassic/bundler/tests/resources/subdir/test_file.txt @@ -1 +1 @@ -Used to test globbing. \ No newline at end of file +Used to test globbing. diff --git a/nbclassic/bundler/tests/test_bundler_api.py b/nbclassic/bundler/tests/test_bundler_api.py index a39eba18a..f0f2c545c 100644 --- a/nbclassic/bundler/tests/test_bundler_api.py +++ b/nbclassic/bundler/tests/test_bundler_api.py @@ -14,7 +14,7 @@ from unittest.mock import patch - + def bundle(handler, model): """Bundler test stub. Echo the notebook path.""" handler.finish(model['path']) @@ -34,7 +34,7 @@ def setup_class(cls): cc1 = new_code_cell(source=u'print(2*6)') cc1.outputs.append(new_output(output_type="stream", text=u'12')) nb.cells.append(cc1) - + with io.open(pjoin(nbdir, 'testnb.ipynb'), 'w', encoding='utf-8') as f: write(nb, f, version=4) @@ -68,7 +68,7 @@ def test_bundler_import_error(self): mock.assert_called_with('fake_bundler') self.assertEqual(resp.status_code, 500) self.assertIn('Could not import bundler fake_bundler', resp.text) - + def test_bundler_invoke(self): """Should respond with 200 and output from test bundler stub""" with patch('nbclassic.bundler.handlers.BundlerHandler.get_bundler') as mock: @@ -77,4 +77,4 @@ def test_bundler_invoke(self): params={'bundler': 'stub_bundler'}) mock.assert_called_with('stub_bundler') self.assertEqual(resp.status_code, 200) - self.assertIn('testnb.ipynb', resp.text) \ No newline at end of file + self.assertIn('testnb.ipynb', resp.text) diff --git a/nbclassic/bundler/tests/test_bundler_tools.py b/nbclassic/bundler/tests/test_bundler_tools.py index e2202a228..85c853855 100644 --- a/nbclassic/bundler/tests/test_bundler_tools.py +++ b/nbclassic/bundler/tests/test_bundler_tools.py @@ -72,7 +72,7 @@ def test_get_cell_reference_patterns_precode_mdcomment(self): self.assertEqual(len(references), 2, str(references)) def test_get_cell_reference_patterns_precode_backticks(self): - '''Should find three references in a fenced code block.''' + '''Should find three references in a fenced code block.''' cell = {'cell_type':'markdown', 'source':'''```c a b/ diff --git a/nbclassic/bundler/tests/test_bundlerextension.py b/nbclassic/bundler/tests/test_bundlerextension.py index 92f59a9b9..2ddb4f200 100644 --- a/nbclassic/bundler/tests/test_bundlerextension.py +++ b/nbclassic/bundler/tests/test_bundlerextension.py @@ -15,7 +15,7 @@ import nbclassic.nbextensions as nbextensions from nbclassic.config_manager import BaseJSONConfigManager -from ..bundlerextensions import (_get_config_dir, enable_bundler_python, +from ..bundlerextensions import (_get_config_dir, enable_bundler_python, disable_bundler_python) def test_help_output(): @@ -28,13 +28,13 @@ class TestBundlerExtensionCLI(unittest.TestCase): def setUp(self): """Build an isolated config environment.""" td = TemporaryDirectory() - + self.test_dir = py3compat.cast_unicode(td.name) self.data_dir = os.path.join(self.test_dir, 'data') self.config_dir = os.path.join(self.test_dir, 'config') self.system_data_dir = os.path.join(self.test_dir, 'system_data') self.system_path = [self.system_data_dir] - + # Use temp directory, not real user or system config paths self.patch_env = patch.dict('os.environ', { 'JUPYTER_CONFIG_DIR': self.config_dir, @@ -44,28 +44,28 @@ def setUp(self): self.patch_system_path = patch.object(nbextensions, 'SYSTEM_JUPYTER_PATH', self.system_path) self.patch_system_path.start() - + def tearDown(self): """Remove the test config environment.""" shutil.rmtree(self.test_dir, ignore_errors=True) self.patch_env.stop() self.patch_system_path.stop() - + def test_enable(self): """Should add the bundler to the notebook configuration.""" enable_bundler_python('nbclassic.bundler.zip_bundler') - + config_dir = os.path.join(_get_config_dir(user=True), 'nbconfig') cm = BaseJSONConfigManager(config_dir=config_dir) bundlers = cm.get('notebook').get('bundlerextensions', {}) self.assertEqual(len(bundlers), 1) self.assertIn('notebook_zip_download', bundlers) - + def test_disable(self): """Should remove the bundler from the notebook configuration.""" self.test_enable() disable_bundler_python('nbclassic.bundler.zip_bundler') - + config_dir = os.path.join(_get_config_dir(user=True), 'nbconfig') cm = BaseJSONConfigManager(config_dir=config_dir) bundlers = cm.get('notebook').get('bundlerextensions', {}) diff --git a/nbclassic/bundler/zip_bundler.py b/nbclassic/bundler/zip_bundler.py index e4346bf20..dbd543b56 100644 --- a/nbclassic/bundler/zip_bundler.py +++ b/nbclassic/bundler/zip_bundler.py @@ -17,10 +17,10 @@ def _jupyter_bundlerextension_paths(): def bundle(handler, model): """Create a zip file containing the original notebook and files referenced from it. Retain the referenced files in paths relative to the nbclassic. - Return the zip as a file download. - + Return the zip as a file download. + Assumes the notebook and other files are all on local disk. - + Parameters ---------- handler : tornado.web.RequestHandler @@ -31,7 +31,7 @@ def bundle(handler, model): abs_nb_path = os.path.join(handler.settings['contents_manager'].root_dir, model['path']) notebook_filename = model['name'] - notebook_name = os.path.splitext(notebook_filename)[0] + notebook_name = os.path.splitext(notebook_filename)[0] # Headers zip_filename = os.path.splitext(notebook_name)[0] + '.zip' @@ -50,10 +50,10 @@ def bundle(handler, model): for nb_relative_filename in ref_filenames: # Build absolute path to file on disk abs_fn = os.path.join(notebook_dir, nb_relative_filename) - # Store file under path relative to notebook + # Store file under path relative to notebook zipf.write(abs_fn, nb_relative_filename) zipf.close() # Return the buffer value as the response - handler.finish(zip_buffer.getvalue()) \ No newline at end of file + handler.finish(zip_buffer.getvalue()) diff --git a/nbclassic/i18n/babel_nbui.cfg b/nbclassic/i18n/babel_nbui.cfg index 271554a8a..5f05ba0d7 100644 --- a/nbclassic/i18n/babel_nbui.cfg +++ b/nbclassic/i18n/babel_nbui.cfg @@ -1,4 +1,4 @@ [jinja2: notebook/templates/**.html] encoding = utf-8 -[extractors] +[extractors] jinja2 = jinja2.ext:babel_extract diff --git a/nbclassic/i18n/fr_FR/LC_MESSAGES/nbclassic.po b/nbclassic/i18n/fr_FR/LC_MESSAGES/nbclassic.po index 5437b1b0f..a868e0ebd 100644 --- a/nbclassic/i18n/fr_FR/LC_MESSAGES/nbclassic.po +++ b/nbclassic/i18n/fr_FR/LC_MESSAGES/nbclassic.po @@ -477,4 +477,3 @@ msgstr "" #: notebook/services/contents/manager.py:68 msgid "Untitled" msgstr "" - diff --git a/nbclassic/i18n/zh_CN/LC_MESSAGES/nbclassic.po b/nbclassic/i18n/zh_CN/LC_MESSAGES/nbclassic.po index aa03cd583..b735f4270 100644 --- a/nbclassic/i18n/zh_CN/LC_MESSAGES/nbclassic.po +++ b/nbclassic/i18n/zh_CN/LC_MESSAGES/nbclassic.po @@ -483,4 +483,3 @@ msgstr "notebooks 运行所在的本地路径: %s" #: notebook/services/contents/manager.py:69 msgid "Untitled" msgstr "未命名" - diff --git a/nbclassic/i18n/zh_CN/LC_MESSAGES/nbjs.po b/nbclassic/i18n/zh_CN/LC_MESSAGES/nbjs.po index 9faed160a..708121b7a 100644 --- a/nbclassic/i18n/zh_CN/LC_MESSAGES/nbjs.po +++ b/nbclassic/i18n/zh_CN/LC_MESSAGES/nbjs.po @@ -1975,4 +1975,3 @@ msgstr "已经存在一个名为 \"%s\" 的文件,替换现有文件?" #: notebook/static/tree/js/notebooklist.js:1399 msgid "Replace file" msgstr "替换文件" - diff --git a/nbclassic/i18n/zh_CN/LC_MESSAGES/nbui.po b/nbclassic/i18n/zh_CN/LC_MESSAGES/nbui.po index 465dde76f..0c85355b3 100644 --- a/nbclassic/i18n/zh_CN/LC_MESSAGES/nbui.po +++ b/nbclassic/i18n/zh_CN/LC_MESSAGES/nbui.po @@ -730,4 +730,3 @@ msgstr "集群标签现在由IPython并行提供。" #: notebook/templates/tree.html:179 msgid "See 'IPython parallel' for installation details." msgstr "安装细节查看 'IPython parallel'。" - diff --git a/nbclassic/notebookapp.py b/nbclassic/notebookapp.py index 73a4a80c6..f6d32221e 100644 --- a/nbclassic/notebookapp.py +++ b/nbclassic/notebookapp.py @@ -267,7 +267,7 @@ def initialize_handlers(self): if len(nbclassic_path()) > 0: handlers.append( ( - rf"/nbclassic", + r"/nbclassic", RedirectHandler, {"url": self.serverapp.base_url+"nbclassic/tree"} ) @@ -331,7 +331,7 @@ def initialize_handlers(self): | |_| | '_ \/ _` / _` | _/ -_) \___/| .__/\__,_\__,_|\__\___| |_| - + Read the migration plan to Notebook 7 to learn about the new features and the actions to take if you are using extensions. https://jupyter-notebook.readthedocs.io/en/latest/migrate_to_notebook7.html diff --git a/nbclassic/shim.py b/nbclassic/shim.py index 46e6a938d..64b653689 100644 --- a/nbclassic/shim.py +++ b/nbclassic/shim.py @@ -1,4 +1,4 @@ -from notebook_shim.shim import * +from notebook_shim.shim import NotebookConfigShimMixin NBClassicConfigShimMixin = NotebookConfigShimMixin diff --git a/nbclassic/shim_notebook.py b/nbclassic/shim_notebook.py index 4f98cf876..9c6672acc 100644 --- a/nbclassic/shim_notebook.py +++ b/nbclassic/shim_notebook.py @@ -12,11 +12,11 @@ def shim_notebook(): their corresponding and backwards-compatible jupyter-server packages. TODO Can we lazy load these loadings? - - Note: We could a custom module loader to achieve similar functionality. The + + Note: We could a custom module loader to achieve similar functionality. The logic thar conditional loading seems to be more complicated than simply listing by hand the needed subpackages but could avoid latency on server start. - + https://docs.python.org/3/library/importlib.html#importlib.abc.Loader These are the notebook packages we need to shim: diff --git a/nbclassic/static/acc_overwrite.less b/nbclassic/static/acc_overwrite.less index 4209ea633..9e7e548e9 100644 --- a/nbclassic/static/acc_overwrite.less +++ b/nbclassic/static/acc_overwrite.less @@ -22,7 +22,7 @@ color: @close-color; text-shadow: @close-text-shadow; .opacity(.6); - + &:hover, &:focus { color: @close-color; @@ -43,7 +43,7 @@ > li > a { color: @navbar-default-link-color; // To make keyboard focus clearly visible on the Controls(File,Edit,View,Insert,Cell...etc)present on the menubar. - //&:hover, //To use browser's hover default value + //&:hover, //To use browser's hover default value &:focus { /* -webkit-focus-ring-color = '#5B9DD9' */ outline: -webkit-focus-ring-color auto 5px; @@ -58,4 +58,3 @@ outline: -webkit-focus-ring-color auto 5px; } } - diff --git a/nbclassic/static/auth/less/logout.less b/nbclassic/static/auth/less/logout.less index 63cd701c9..db9afca1a 100644 --- a/nbclassic/static/auth/less/logout.less +++ b/nbclassic/static/auth/less/logout.less @@ -1,2 +1 @@ // Custom styles for logout.html - diff --git a/nbclassic/static/auth/less/style.less b/nbclassic/static/auth/less/style.less index 4d1919cc0..cb83c0f2b 100644 --- a/nbclassic/static/auth/less/style.less +++ b/nbclassic/static/auth/less/style.less @@ -4,4 +4,4 @@ * */ @import "login.less"; -@import "logout.less"; \ No newline at end of file +@import "logout.less"; diff --git a/nbclassic/static/base/js/dialog.js b/nbclassic/static/base/js/dialog.js index 77d81185f..e87bb38ae 100644 --- a/nbclassic/static/base/js/dialog.js +++ b/nbclassic/static/base/js/dialog.js @@ -24,13 +24,13 @@ define(['jquery', * - notebook : notebook instance * - keyboard_manager: keyboard manager instance. * - * Unlike bootstrap modals, the backdrop options is set by default + * Unlike bootstrap modals, the backdrop options is set by default * to 'static'. * - * The rest of the options are passed as is to bootstrap modals. + * The rest of the options are passed as is to bootstrap modals. * * btn_options: dict with the following property: - * + * * - click : callback to trigger on click * - class : css classes to add to button. * @@ -77,11 +77,11 @@ define(['jquery', options.body || $("

") ) ); - + var footer = $("

").addClass("modal-footer"); - + var default_button; - + for (var label in options.buttons) { var btn_opts = options.buttons[label]; var button = $(" +
@@ -167,9 +167,9 @@ {% block headercontainer %} {% endblock %} - + {% block header_buttons %} - + {% block login_widget %} @@ -183,7 +183,7 @@ {% endblock %} {% endblock header_buttons %} - +
@@ -216,9 +216,9 @@ if (search_parameters.length) { new_search = '?' + search_parameters.join('&'); } - var new_url = window.location.origin + - window.location.pathname + - new_search + + var new_url = window.location.origin + + window.location.pathname + + new_search + window.location.hash; window.history.replaceState({}, "", new_url); return; diff --git a/nbclassic/templates/tree.html b/nbclassic/templates/tree.html index 668fa2be3..e62d43d8f 100644 --- a/nbclassic/templates/tree.html +++ b/nbclassic/templates/tree.html @@ -44,17 +44,17 @@ - + - + - + - + - + diff --git a/nbclassic/tests/README.md b/nbclassic/tests/README.md index fa6d67734..9ca708798 100644 --- a/nbclassic/tests/README.md +++ b/nbclassic/tests/README.md @@ -10,7 +10,7 @@ The JavaScript tests are organized into subdirectories that match those in To run all of the JavaScript tests do: ``` -python -m nbclassic.jstest +python -m nbclassic.jstest ``` To run the JavaScript tests for a specific file (`base/utils.js` in this case) diff --git a/nbclassic/tests/base/highlight.js b/nbclassic/tests/base/highlight.js index 155d13f3c..0260ba885 100644 --- a/nbclassic/tests/base/highlight.js +++ b/nbclassic/tests/base/highlight.js @@ -14,7 +14,7 @@ casper.notebook_test(function () { ); } }); - + var that = this; // syntax highlighting [ @@ -55,4 +55,4 @@ casper.notebook_test(function () { }); }); }); -}); \ No newline at end of file +}); diff --git a/nbclassic/tests/base/misc.js b/nbclassic/tests/base/misc.js index 373969877..6f047b60e 100644 --- a/nbclassic/tests/base/misc.js +++ b/nbclassic/tests/base/misc.js @@ -17,7 +17,7 @@ casper.notebook_test(function () { var result = this.get_output_cell(0); this.test.assertEquals(result.text.trim(), jsver, 'IPython.version in JS matches server-side.'); }); - + // verify that requirejs loads the same CodeCell prototype at runtime as build time this.thenEvaluate(function () { require(['notebook/js/codecell'], function (codecell) { diff --git a/nbclassic/tests/base/security.js b/nbclassic/tests/base/security.js index af23e6691..1a74d01bc 100644 --- a/nbclassic/tests/base/security.js +++ b/nbclassic/tests/base/security.js @@ -38,20 +38,20 @@ casper.notebook_test(function () { var sanitized = self.evaluate(function (item) { return IPython.security.sanitize_html(item); }, item); - + // string equality may be too strict, but it works for now this.test.assertEquals(sanitized, item, "Safe: '" + truncate(item, 32) + "'"); }); - + this.each(unsafe_tests, function (self, item) { var sanitized = self.evaluate(function (item) { return IPython.security.sanitize_html(item); }, item); - - this.test.assertNotEquals(sanitized, item, - "Sanitized: '" + truncate(item, 32) + + + this.test.assertNotEquals(sanitized, item, + "Sanitized: '" + truncate(item, 32) + "' => '" + truncate(sanitized, 32) + "'" ); this.test.assertEquals(sanitized.indexOf("alert"), -1, "alert removed"); }); -}); \ No newline at end of file +}); diff --git a/nbclassic/tests/base/utils.js b/nbclassic/tests/base/utils.js index 4d6428a68..524b18a66 100644 --- a/nbclassic/tests/base/utils.js +++ b/nbclassic/tests/base/utils.js @@ -58,7 +58,7 @@ casper.notebook_test(function () { 'x2\r\r', '1\r', ].join(''); - + var output = [ 'hasrn\n', 'hasn\n', @@ -66,13 +66,13 @@ casper.notebook_test(function () { 'hellof\n', '123\r' ].join(''); - + var result = this.evaluate(function (input) { return IPython.utils.fixCarriageReturn(input); }, input); this.test.assertEquals(result, output, "IPython.utils.fixCarriageReturns works"); - + // Test load_extensions this.thenEvaluate(function() { @@ -85,7 +85,7 @@ casper.notebook_test(function () { this.waitFor(function() { return this.evaluate(function() { return window.a; }); }); - + this.waitFor(function() { return this.evaluate(function() { return window.a; }); }); diff --git a/nbclassic/tests/end_to_end/conftest.py b/nbclassic/tests/end_to_end/conftest.py index 61961645c..f9f5b2d18 100644 --- a/nbclassic/tests/end_to_end/conftest.py +++ b/nbclassic/tests/end_to_end/conftest.py @@ -134,7 +134,7 @@ def inner(cells): cells = [new_code_cell(c) if isinstance(c, str) else c for c in cells] # new_notebook is an nbformat function that is imported so that it can create a - # notebook that is formatted as it needs to be + # notebook that is formatted as it needs to be nb = new_notebook(cells=cells) # Create temporary file directory and store it's reference as well as the path diff --git a/nbclassic/tests/end_to_end/test_clipboard_multiselect.py b/nbclassic/tests/end_to_end/test_clipboard_multiselect.py index a71b8e67a..f030c6cc4 100644 --- a/nbclassic/tests/end_to_end/test_clipboard_multiselect.py +++ b/nbclassic/tests/end_to_end/test_clipboard_multiselect.py @@ -11,7 +11,7 @@ def test_clipboard_multiselect(prefill_notebook): assert notebook.get_cells_contents() == ['', '1', '2', '3', '4', '5a', '6b', '7c', '8d'] # Copy the first 3 cells - # Paste the values copied from the first three cells into the last 3 cells + # Paste the values copied from the first three cells into the last 3 cells # Selecting the fist 3 cells notebook.select_cell_range(1, 3) diff --git a/nbclassic/tests/end_to_end/test_dashboard_nav.py b/nbclassic/tests/end_to_end/test_dashboard_nav.py index 32d855ca6..db65a1f23 100644 --- a/nbclassic/tests/end_to_end/test_dashboard_nav.py +++ b/nbclassic/tests/end_to_end/test_dashboard_nav.py @@ -24,10 +24,10 @@ def navigate_to_link(nb, item_text): # Define a match finder func (this is easier # to hook into for debugging than a listcomp) def get_matches(): - print(f'[Test] Attempt to find matches...') + print('[Test] Attempt to find matches...') tree_page_items = [item for item in notebook_frontend.locate_all('#notebook_list .item_link', TREE_PAGE)] if tree_page_items: - print(f'[Test] Found!') + print('[Test] Found!') return [elem for elem in tree_page_items if elem.is_visible() and elem.get_inner_text().strip() == item_text] # Get tree page item matching the item_text (the dir name/link element to navigate to) matches = notebook_frontend.wait_for_condition( @@ -42,13 +42,13 @@ def get_matches(): f'#notebook_list .item_link >> text="{item_text}"', page=EDITOR_PAGE).is_visible() ) - print(f'[Test] Check URL in tree') + print('[Test] Check URL in tree') notebook_frontend.wait_for_condition( lambda: url_in_tree(notebook_frontend), timeout=60, period=5 ) - print(f'[Test] Check URL matches link') + print('[Test] Check URL matches link') print(f'[Test] Item link: "{target_link}"') print(f'[Test] Current URL is: "{notebook_frontend.get_page_url(page=TREE_PAGE)}"') notebook_frontend.wait_for_condition( @@ -56,7 +56,7 @@ def get_matches(): timeout=60, period=5 ) - print(f'[Test] Passed!') + print('[Test] Passed!') return notebook_frontend.get_page_url(page=TREE_PAGE) @@ -73,17 +73,17 @@ def test_navigation(notebook_frontend): SUBDIR1B = 'sub ∂ir 1b' # Start at the root (tree) URL - print(f'[Test] Start at tree (root) URL') + print('[Test] Start at tree (root) URL') tree_url = notebook_frontend.get_page_url(page=TREE_PAGE) print(f'[Test] URL is now at "{tree_url}"') # Test navigation to first folder from root - print(f'[Test] Navigate to subdir1') + print('[Test] Navigate to subdir1') subdir1_url = navigate_to_link(notebook_frontend, SUBDIR1) print(f'[Test] URL is now at "{subdir1_url}"') # Test navigation to first subfolder (1a) - print(f'[Test] Navigate to subdir1a') + print('[Test] Navigate to subdir1a') subdir1a_url = navigate_to_link(notebook_frontend, SUBDIR1A) print(f'[Test] URL is now at "{subdir1a_url}"') notebook_frontend.go_back(page=TREE_PAGE) @@ -106,7 +106,7 @@ def test_navigation(notebook_frontend): ) # Test navigation to second folder from root - print(f'[Test] Navigate to subdir2') + print('[Test] Navigate to subdir2') subdir2_url = navigate_to_link(notebook_frontend, SUBDIR2) print(f'[Test] URL is now at "{subdir2_url}"') # Wait for the links to update (subdir2 link should NOT be showing anymore) @@ -117,7 +117,7 @@ def test_navigation(notebook_frontend): ) # Test navigation to second subfolder (1b) - print(f'[Test] Navigate to subdir1b') + print('[Test] Navigate to subdir1b') subdir1b_url = navigate_to_link(notebook_frontend, SUBDIR1B) print(f'[Test] URL is now at "{subdir1b_url}"') notebook_frontend.go_back(page=TREE_PAGE) diff --git a/nbclassic/tests/end_to_end/test_display_isolation.py b/nbclassic/tests/end_to_end/test_display_isolation.py index 9f1300123..e20c945c8 100644 --- a/nbclassic/tests/end_to_end/test_display_isolation.py +++ b/nbclassic/tests/end_to_end/test_display_isolation.py @@ -80,7 +80,7 @@ def isolated_svg(notebook): notebook.wait_for_frame(count=2, page=EDITOR_PAGE) isolated_svg_1 = notebook.locate_in_frame('#r1', page=EDITOR_PAGE, frame_index=2) assert isolated_svg_1.get_computed_property("fill") == yellow - + # The second rectangle will be black notebook.wait_for_frame(count=3, page=EDITOR_PAGE) isolated_svg_2 = notebook.locate_in_frame('#r2', page=EDITOR_PAGE, frame_index=3) diff --git a/nbclassic/tests/end_to_end/test_save.py b/nbclassic/tests/end_to_end/test_save.py index 0a34781fd..21be5aa86 100644 --- a/nbclassic/tests/end_to_end/test_save.py +++ b/nbclassic/tests/end_to_end/test_save.py @@ -50,7 +50,7 @@ def test_save(notebook_frontend): hrefs_nonmatch = [] all_links = notebook_frontend.locate_all('a.item_link', page=EDITOR_PAGE) - + for link in all_links: href = link.get_attribute('href') @@ -68,4 +68,3 @@ def test_save(notebook_frontend): notebook_frontend.edit_cell(index=0, content="") notebook_frontend.delete_all_cells() - \ No newline at end of file diff --git a/nbclassic/tests/end_to_end/test_save_as_notebook.py b/nbclassic/tests/end_to_end/test_save_as_notebook.py index 260bbaccb..88c9cf082 100644 --- a/nbclassic/tests/end_to_end/test_save_as_notebook.py +++ b/nbclassic/tests/end_to_end/test_save_as_notebook.py @@ -73,16 +73,16 @@ def attempt_form_fill_and_save(): # Set the notebook name field in the save dialog print('[Test] Fill the input field') - name_input_element.evaluate(f'(elem) => {{ elem.value = "new_notebook.ipynb"; return elem.value; }}') + name_input_element.evaluate('(elem) => {{ elem.value = "new_notebook.ipynb"; return elem.value; }}') notebook_frontend.wait_for_condition( lambda: name_input_element.evaluate( - f'(elem) => {{ elem.value = "new_notebook.ipynb"; return elem.value; }}') == 'new_notebook.ipynb', + '(elem) => {{ elem.value = "new_notebook.ipynb"; return elem.value; }}') == 'new_notebook.ipynb', timeout=120, period=.25 ) # Show the input field value print('[Test] Name input field contents:') - field_value = name_input_element.evaluate(f'(elem) => {{ return elem.value; }}') + field_value = name_input_element.evaluate('(elem) => {{ return elem.value; }}') print('[Test] ' + field_value) if field_value != 'new_notebook.ipynb': return False diff --git a/nbclassic/tests/end_to_end/test_save_readonly_as.py b/nbclassic/tests/end_to_end/test_save_readonly_as.py index 2da7384ae..bc1901535 100644 --- a/nbclassic/tests/end_to_end/test_save_readonly_as.py +++ b/nbclassic/tests/end_to_end/test_save_readonly_as.py @@ -100,16 +100,16 @@ def attempt_form_fill_and_save(): # Set the notebook name field in the save dialog print('[Test] Fill the input field') - name_input_element.evaluate(f'(elem) => {{ elem.value = "writable_notebook.ipynb"; return elem.value; }}') + name_input_element.evaluate('(elem) => {{ elem.value = "writable_notebook.ipynb"; return elem.value; }}') notebook_frontend.wait_for_condition( lambda: name_input_element.evaluate( - f'(elem) => {{ elem.value = "writable_notebook.ipynb"; return elem.value; }}') == 'writable_notebook.ipynb', + '(elem) => {{ elem.value = "writable_notebook.ipynb"; return elem.value; }}') == 'writable_notebook.ipynb', timeout=120, period=.25 ) # Show the input field value print('[Test] Name input field contents:') - field_value = name_input_element.evaluate(f'(elem) => {{ return elem.value; }}') + field_value = name_input_element.evaluate('(elem) => {{ return elem.value; }}') print('[Test] ' + field_value) if field_value != 'writable_notebook.ipynb': return False diff --git a/nbclassic/tests/end_to_end/test_shutdown.py b/nbclassic/tests/end_to_end/test_shutdown.py index 6c2a5010d..f29568924 100644 --- a/nbclassic/tests/end_to_end/test_shutdown.py +++ b/nbclassic/tests/end_to_end/test_shutdown.py @@ -3,11 +3,11 @@ def test_shutdown(prefill_notebook): notebook_frontend = prefill_notebook(["print(21)"]) - + notebook_frontend.try_click_selector('//a[text()="Kernel"]', page=EDITOR_PAGE) notebook_frontend.try_click_selector('#shutdown_kernel', page=EDITOR_PAGE) notebook_frontend.try_click_selector('.btn.btn-default.btn-sm.btn-danger', page=EDITOR_PAGE) - + notebook_frontend.execute_cell(0) assert not notebook_frontend.is_kernel_running() diff --git a/nbclassic/tests/notebook/attachments.js b/nbclassic/tests/notebook/attachments.js index 084fa5d8e..ce332a655 100644 --- a/nbclassic/tests/notebook/attachments.js +++ b/nbclassic/tests/notebook/attachments.js @@ -189,4 +189,3 @@ casper.notebook_test(function () { 'cell1 attachments have been garbage collected'); }); }); - diff --git a/nbclassic/tests/notebook/display_id.js b/nbclassic/tests/notebook/display_id.js index 3b062ea0c..fcfe3acfe 100644 --- a/nbclassic/tests/notebook/display_id.js +++ b/nbclassic/tests/notebook/display_id.js @@ -3,7 +3,7 @@ // casper.notebook_test(function () { - + function get_outputs(cell_idx) { var outputs_json = casper.evaluate(function (cell_idx) { var cell = Jupyter.notebook.get_cell(cell_idx); @@ -11,7 +11,7 @@ casper.notebook_test(function () { }, {cell_idx: cell_idx}); return JSON.parse(outputs_json); } - + this.thenEvaluate(function () { Jupyter.notebook.insert_cell_at_index("code", 0); var cell = Jupyter.notebook.get_cell(0); diff --git a/nbclassic/tests/notebook/dualmode.js b/nbclassic/tests/notebook/dualmode.js index ee577c7ce..60dc42e99 100644 --- a/nbclassic/tests/notebook/dualmode.js +++ b/nbclassic/tests/notebook/dualmode.js @@ -60,7 +60,7 @@ casper.notebook_test(function () { IPython.modal_shown = false; }); }); - + }); this.waitFor(function () { diff --git a/nbclassic/tests/notebook/dualmode_merge.js b/nbclassic/tests/notebook/dualmode_merge.js index 0cd15aa3c..54cc446cc 100644 --- a/nbclassic/tests/notebook/dualmode_merge.js +++ b/nbclassic/tests/notebook/dualmode_merge.js @@ -130,7 +130,7 @@ casper.notebook_test(function () { this.test.assertEquals(this.get_cell_text(0), a, 'Split cell 1: Cell 0 is unchanged'); this.test.assertEquals(this.get_cell_text(1), b, 'Split cell 1: Cell 1 is unchanged'); this.test.assertEquals(this.get_cell_text(2), c, 'Split cell 1: Cell 2 is unchanged'); - this.validate_notebook_state('ctrl-shift--', 'edit', 1); + this.validate_notebook_state('ctrl-shift--', 'edit', 1); }); // Try to merge cell 1 down, should fail, as 1 is locked diff --git a/nbclassic/tests/notebook/execute_selected_cells.js b/nbclassic/tests/notebook/execute_selected_cells.js index 5cb470ab3..871f1faa7 100644 --- a/nbclassic/tests/notebook/execute_selected_cells.js +++ b/nbclassic/tests/notebook/execute_selected_cells.js @@ -149,7 +149,7 @@ casper.notebook_test(function () { this.trigger_keydown('alt-enter'); }); - + this.wait_for_output(0); this.wait_for_output(1); this.then(function () { @@ -168,7 +168,7 @@ casper.notebook_test(function () { }); }); - + this.wait_for_output(1); this.wait_for_output(2); this.then(function () { diff --git a/nbclassic/tests/notebook/inject_js.js b/nbclassic/tests/notebook/inject_js.js index 03757aa79..af187881d 100644 --- a/nbclassic/tests/notebook/inject_js.js +++ b/nbclassic/tests/notebook/inject_js.js @@ -9,7 +9,7 @@ casper.notebook_test(function () { this.on('remote.alert', function (msg) { messages.push(msg); }); - + this.evaluate(function () { var cell = IPython.notebook.get_cell(0); var json = cell.toJSON(); diff --git a/nbclassic/tests/notebook/markdown.js b/nbclassic/tests/notebook/markdown.js index 377b26ef5..fa8f83eb6 100644 --- a/nbclassic/tests/notebook/markdown.js +++ b/nbclassic/tests/notebook/markdown.js @@ -39,7 +39,7 @@ casper.notebook_test(function () { var input_string_1 = 'x \\\\(a_{0}+ b_{T}\\\\) y \\\\(a_{0}+ b_{T}\\\\) z'; var expected_result_1 = ['x @@0@@ y @@1@@ z', ['\\\\(a_{0}+ b_{T}\\\\)','\\\\(a_{0}+ b_{T}\\\\)']]; var message_1 = "multiple inline(LaTeX style) with underscores"; - + var input_string_2 = 'x \\\\[a_{0}+ b_{T}\\\\] y \\\\[a_{0}+ b_{T}\\\\] z'; var expected_result_2 = ['x @@0@@ y @@1@@ z', ['\\\\[a_{0}+ b_{T}\\\\]','\\\\[a_{0}+ b_{T}\\\\]']]; var message_2 = "multiple equation (LaTeX style) with underscores"; @@ -47,7 +47,7 @@ casper.notebook_test(function () { var input_string_3 = 'x $a_{0}+ b_{T}$ y $a_{0}+ b_{T}$ z'; var expected_result_3 = ['x @@0@@ y @@1@@ z',['$a_{0}+ b_{T}$','$a_{0}+ b_{T}$']]; var message_3 = "multiple inline(TeX style) with underscores"; - + var input_string_4 = 'x $$a_{0}+ b_{T}$$ y $$a_{0}+ b_{T}$$ z'; var expected_result_4 = ['x @@0@@ y @@1@@ z', ['$$a_{0}+ b_{T}$$','$$a_{0}+ b_{T}$$']]; var message_4 = "multiple equation(TeX style) with underscores"; diff --git a/nbclassic/tests/notebook/output.js b/nbclassic/tests/notebook/output.js index bb4b1a962..6c0508f27 100644 --- a/nbclassic/tests/notebook/output.js +++ b/nbclassic/tests/notebook/output.js @@ -3,7 +3,7 @@ // casper.notebook_test(function () { - + this.compare_outputs = function(results, expected) { for (var i = 0; i < results.length; i++) { var r = results[i]; @@ -19,16 +19,16 @@ casper.notebook_test(function () { this.then(function () { this.echo("Test coalesced output: " + msg); }); - + this.thenEvaluate(function (code) { IPython.notebook.insert_cell_at_index("code", 0); var cell = IPython.notebook.get_cell(0); cell.set_text(code); cell.execute(); }, {code: code}); - + this.wait_for_output(0); - + this.then(function () { var results = this.evaluate(function () { var cell = IPython.notebook.get_cell(0); @@ -37,7 +37,7 @@ casper.notebook_test(function () { this.test.assertEquals(results.length, expected.length, "correct number of outputs"); this.compare_outputs(results, expected); }); - + }; this.thenEvaluate(function () { @@ -63,7 +63,7 @@ casper.notebook_test(function () { text: "1\n2\n3\n" }] ); - + this.test_coalesced_output("stdout+sdterr", [ "print(1)", "sys.stdout.flush()", @@ -111,7 +111,7 @@ casper.notebook_test(function () { 'SVG(nested_svg)' ].join("\n"), [{ output_type: "execute_result", - data: { + data: { "text/plain" : "", "image/svg+xml": [ '', @@ -167,9 +167,9 @@ casper.notebook_test(function () { }, false); kernel.output_callback_overrides_push(msg_id, callback_id); }); - + this.wait_for_idle(); - + this.then(function () { var expected_callback = [{ output_type: "stream", @@ -234,9 +234,9 @@ casper.notebook_test(function () { }, false); kernel.output_callback_overrides_push(msg_id, callback_id); }); - + this.wait_for_idle(); - + this.then(function () { var expected_callback = [{ output_type: "execute_result", diff --git a/nbclassic/tests/notebook/roundtrip.js b/nbclassic/tests/notebook/roundtrip.js index b88dae94e..3373bf191 100644 --- a/nbclassic/tests/notebook/roundtrip.js +++ b/nbclassic/tests/notebook/roundtrip.js @@ -33,7 +33,7 @@ function assert_has(short_name, json, result, result2) { this.test.assertTrue(result2.data.hasOwnProperty(long_name), 'fromJSON() embedded ' + short_name + ' gets mime key ' + long_name); } - + // helper function for checkout that the first two cells have a particular // output_type (either 'execute_result' or 'display_data'), and checks the to/fromJSON // for a set of mimetype keys, ensuring the old short names ('javascript', 'text', @@ -99,7 +99,7 @@ casper.notebook_test(function () { "var a=5;" ].join('\n')); }); - + this.then(function () { check_output_area.apply(this, ['display_data', ['javascript']]); @@ -109,7 +109,7 @@ casper.notebook_test(function () { this.then(function() { clear_and_execute(this, '%lsmagic'); }); - + this.then(function () { check_output_area.apply(this, ['execute_result', ['text', 'json']]); }); @@ -122,12 +122,12 @@ casper.notebook_test(function () { this.then(function ( ) { check_output_area.apply(this, ['display_data', ['text', 'json']]); }); - + this.then(function() { clear_and_execute(this, "from IPython.display import Latex; Latex('$X^2$')"); }); - + this.then(function ( ) { check_output_area.apply(this, ['execute_result', ['text', 'latex']]); }); @@ -136,24 +136,24 @@ casper.notebook_test(function () { clear_and_execute(this, "from IPython.display import Latex, display; display(Latex('$X^2$'))"); }); - + this.then(function ( ) { check_output_area.apply(this, ['display_data', ['text', 'latex']]); }); - + this.then(function() { clear_and_execute(this, "from IPython.display import HTML; HTML('it works!')"); }); - + this.then(function ( ) { check_output_area.apply(this, ['execute_result', ['text', 'html']]); }); this.then(function() { clear_and_execute(this, - "from base64 import b64decode;" + - "black_dot_png = b64decode(" + black_dot_png + ");" + + "from base64 import b64decode;" + + "black_dot_png = b64decode(" + black_dot_png + ");" + "black_dot_jpeg = b64decode(" + black_dot_jpeg + ")" ); }); @@ -161,7 +161,7 @@ casper.notebook_test(function () { clear_and_execute(this, "from IPython.display import HTML, display; display(HTML('it works!'))"); }); - + this.then(function ( ) { check_output_area.apply(this, ['display_data', ['text', 'html']]); }); @@ -172,16 +172,16 @@ casper.notebook_test(function () { "from IPython.display import Image; Image(black_dot_png)"); }); this.thenEvaluate(function() { IPython.notebook.save_notebook(); }); - + this.then(function ( ) { check_output_area.apply(this, ['execute_result', ['text', 'png']]); }); - + this.then(function() { clear_and_execute(this, "from IPython.display import Image, display; display(Image(black_dot_png))"); }); - + this.then(function ( ) { check_output_area.apply(this, ['display_data', ['text', 'png']]); }); @@ -191,25 +191,25 @@ casper.notebook_test(function () { clear_and_execute(this, "from IPython.display import Image; Image(black_dot_jpeg, format='jpeg')"); }); - + this.then(function ( ) { check_output_area.apply(this, ['execute_result', ['text', 'jpeg']]); }); - + this.then(function() { clear_and_execute(this, "from IPython.display import Image, display; display(Image(black_dot_jpeg, format='jpeg'))"); }); - + this.then(function ( ) { check_output_area.apply(this, ['display_data', ['text', 'jpeg']]); }); - + this.then(function() { clear_and_execute(this, "from IPython.display import SVG; SVG(" + svg + ")"); }); - + this.then(function ( ) { check_output_area.apply(this, ['execute_result', ['text', 'svg']]); }); @@ -218,11 +218,11 @@ casper.notebook_test(function () { clear_and_execute(this, "from IPython.display import SVG, display; display(SVG(" + svg + "))"); }); - + this.then(function ( ) { check_output_area.apply(this, ['display_data', ['text', 'svg']]); }); - + this.thenEvaluate(function() { IPython.notebook.save_notebook(); }); this.then(function() { @@ -235,11 +235,11 @@ casper.notebook_test(function () { 'display(HTML("yo"))', "HTML('hello')"].join('\n') ); - + }); - + this.wait_for_output(0, 1); - + this.then(function () { var long_name = 'text/superfancymimetype'; var result = this.get_output_cell(0); @@ -248,7 +248,7 @@ casper.notebook_test(function () { result = this.get_output_cell(0, 1); this.test.assertTrue(result.data.hasOwnProperty(long_name), 'execute_result custom mimetype ' + long_name); - + }); - + }); diff --git a/nbclassic/tests/notebook/safe_append_output.js b/nbclassic/tests/notebook/safe_append_output.js index d151a21c7..3a4ab5878 100644 --- a/nbclassic/tests/notebook/safe_append_output.js +++ b/nbclassic/tests/notebook/safe_append_output.js @@ -10,7 +10,7 @@ casper.notebook_test(function () { this.on('remote.message', function (msg) { messages.push(msg); }); - + this.evaluate(function () { var cell = IPython.notebook.get_cell(0); cell.set_text( "dp = get_ipython().display_pub\n" + diff --git a/nbclassic/tests/notebook/tags.js b/nbclassic/tests/notebook/tags.js index 98e0dce39..96b0d9099 100644 --- a/nbclassic/tests/notebook/tags.js +++ b/nbclassic/tests/notebook/tags.js @@ -3,13 +3,13 @@ // casper.notebook_test(function () { - + function get_tag_metadata () { return casper.evaluate(function () { return Jupyter.notebook.get_cell(0).metadata.tags; }); } - + function get_tag_elements () { return casper.evaluate(function () { var cell = Jupyter.notebook.get_cell(0); @@ -40,7 +40,7 @@ casper.notebook_test(function () { 1, "Tag cell toolbar item is present"); }) - + // activate tags toolbar via menubar this.thenEvaluate(function () { $('#menu-cell-toolbar-submenu') @@ -48,7 +48,7 @@ casper.notebook_test(function () { .find('a') .click(); }); - + // wait for one tag container this.waitForSelector('.tags_button_container'); this.then(function () { @@ -76,7 +76,7 @@ casper.notebook_test(function () { .find('.tags-input button') .click(); }); - + var all_tags = ['tag1', 'tüg2', 'tåg3', 'tag4', 'tag5']; // verify that tags are applied this.then(function () { diff --git a/nbclassic/tests/services/kernel.js b/nbclassic/tests/services/kernel.js index a7e538263..b1bfc503d 100644 --- a/nbclassic/tests/services/kernel.js +++ b/nbclassic/tests/services/kernel.js @@ -26,7 +26,7 @@ casper.notebook_test(function () { }); this.test.assertEquals(num_kernels, 1, 'one kernel running'); }); - + // test get_info var kernel_info = this.evaluate(function () { return { @@ -316,7 +316,7 @@ casper.notebook_test(function () { "os._exit(1)"); cell.execute(); }); - }, + }, // need an extra-long timeout, because it needs to try // restarting the kernel 5 times! diff --git a/nbclassic/tests/services/serialize.js b/nbclassic/tests/services/serialize.js index 36bb16565..b2616b4d0 100644 --- a/nbclassic/tests/services/serialize.js +++ b/nbclassic/tests/services/serialize.js @@ -9,7 +9,7 @@ casper.notebook_test(function () { this.then(function () { var success = this.evaluate(function () { IPython._msgs = []; - + var EchoBuffers = function(comm) { this.comm = comm; this.comm.on_msg($.proxy(this.on_msg, this)); @@ -23,7 +23,7 @@ casper.notebook_test(function () { IPython.notebook.kernel.comm_manager.register_target("echo", function (comm) { return new EchoBuffers(comm); }); - + return true; }); this.test.assertEquals(success, true, "Created echo comm target"); @@ -42,7 +42,7 @@ casper.notebook_test(function () { ].join('\n'), 'code'); this.execute_cell(index); }); - + // send a message with binary data this.then(function () { var index = this.append_cell([ @@ -53,14 +53,14 @@ casper.notebook_test(function () { ].join('\n'), 'code'); this.execute_cell(index); }); - + // wait for capture this.waitFor(function () { return this.evaluate(function () { return IPython._msgs.length >= 3; }); }); - + // validate captured buffers js-side this.then(function () { var msgs = this.evaluate(function () { @@ -77,7 +77,7 @@ casper.notebook_test(function () { this.test.assertEquals(msgs[1].buffers.length, 0, "comm message 1 has no buffers"); this.test.assertEquals(msgs[2].content.data, "message 2", "message 2 processed third"); this.test.assertEquals(msgs[2].buffers.length, 2, "comm message 2 has two buffers"); - + // extract attributes to test in evaluate, // because the raw DataViews can't be passed across var buf_info = function (message, index) { @@ -90,7 +90,7 @@ casper.notebook_test(function () { } return data; }; - + var msgs_with_buffers = [0, 2]; for (var i = 0; i < msgs_with_buffers.length; i++) { msg_index = msgs_with_buffers[i]; @@ -102,7 +102,7 @@ casper.notebook_test(function () { this.test.assertEquals(buf1.bytes, [0, 1, 2], 'buf[1] has correct bytes in message '+msg_index); } }); - + // validate captured buffers Python-side this.then(function () { var index = this.append_cell([ diff --git a/nbclassic/tests/util.js b/nbclassic/tests/util.js index 695daa048..6cc91584e 100644 --- a/nbclassic/tests/util.js +++ b/nbclassic/tests/util.js @@ -26,7 +26,7 @@ casper.open_new_notebook = function () { this.waitFor(this.page_loaded); this.waitForSelector('#kernel-python2 a, #kernel-python3 a'); this.thenClick('#kernel-python2 a, #kernel-python3 a'); - + this.waitForPopup(''); this.waitFor(this.popup_has_url); @@ -71,7 +71,7 @@ casper.open_new_notebook = function () { // track the IPython busy/idle state this.thenEvaluate(function () { require(['base/js/namespace', 'base/js/events'], function (IPython, events) { - + events.on('kernel_idle.Kernel',function () { IPython._status = 'idle'; }); @@ -200,11 +200,11 @@ casper.wait_for_widget = function (widget_info) { // Clear the results of a previous query, if they exist. Make sure a // dictionary exists to store the async results in. this.thenEvaluate(function(model_id) { - if (window.pending_msgs === undefined) { - window.pending_msgs = {}; + if (window.pending_msgs === undefined) { + window.pending_msgs = {}; } else { window.pending_msgs[model_id] = -1; - } + } }, {model_id: widget_info.model_id}); // Wait for the pending messages to be 0. @@ -214,8 +214,8 @@ casper.wait_for_widget = function (widget_info) { // Get the model. Once the model is had, store it's pending_msgs // count in the window's dictionary. IPython.notebook.kernel.widget_manager.get_model(model_id) - .then(function(model) { - window.pending_msgs[model_id] = model.pending_msgs; + .then(function(model) { + window.pending_msgs[model_id] = model.pending_msgs; }); // Return the pending_msgs result. @@ -295,7 +295,7 @@ casper.insert_cell_at_bottom = function(cell_type){ }, cell_type); }; -casper.append_cell = function(text, cell_type) { +casper.append_cell = function(text, cell_type) { // Insert a cell at the bottom of the notebook and set the cells text. // Returns the new cell's index. var index = this.insert_cell_at_bottom(cell_type); @@ -308,7 +308,7 @@ casper.append_cell = function(text, cell_type) { casper.execute_cell = function(index, expect_failure){ // Asynchronously executes a cell by index. // Returns the cell's index. - + if (expect_failure === undefined) expect_failure = false; var that = this; this.then(function(){ @@ -318,7 +318,7 @@ casper.execute_cell = function(index, expect_failure){ }, index); }); this.wait_for_idle(); - + this.then(function () { var error = that.evaluate(function (index) { var cell = IPython.notebook.get_cell(index); @@ -352,7 +352,7 @@ casper.execute_cell_then = function(index, then_callback, expect_failure) { this.wait_for_idle(); var that = this; - this.then(function(){ + this.then(function(){ if (then_callback!==undefined) { then_callback.apply(that, [index]); } @@ -375,7 +375,7 @@ casper.assert_output_equals = function(text, output_text, message) { }; casper.wait_for_element = function(index, selector){ - // Utility function that allows us to easily wait for an element + // Utility function that allows us to easily wait for an element // within a cell. Uses JQuery selector to look for the element. var that = this; this.waitFor(function() { @@ -384,7 +384,7 @@ casper.wait_for_element = function(index, selector){ }; casper.cell_element_exists = function(index, selector){ - // Utility function that allows us to easily check if an element exists + // Utility function that allows us to easily check if an element exists // within a cell. Uses JQuery selector to look for the element. return casper.evaluate(function (index, selector) { var $cell = IPython.notebook.get_cell(index).element; @@ -393,7 +393,7 @@ casper.cell_element_exists = function(index, selector){ }; casper.cell_element_function = function(index, selector, function_name, function_args){ - // Utility function that allows us to execute a jQuery function on an + // Utility function that allows us to execute a jQuery function on an // element within a cell. return casper.evaluate(function (index, selector, function_name, function_args) { var $cell = IPython.notebook.get_cell(index).element; @@ -467,8 +467,8 @@ casper.select_cells = function(index, bound, moveanchor) { casper.click_cell_editor = function(index) { // Emulate a click on a cell's editor. - - // Code Mirror does not play nicely with emulated brower events. + + // Code Mirror does not play nicely with emulated brower events. // Instead of trying to emulate a click, here we run code similar to // the code used in Code Mirror that handles the mousedown event on a // region of codemirror that the user can focus. @@ -501,7 +501,7 @@ casper.trigger_keydown = function() { var element = $(document); var event = IPython.keyboard.shortcut_to_event(k, 'keydown'); element.trigger(event); - }, {k: arguments[i]}); + }, {k: arguments[i]}); } }; @@ -544,7 +544,7 @@ casper.is_cell_editor_focused = function(index) { var cell = IPython.notebook.get_cell(i); if (cell) { return cell.code_mirror.getInputField() == focused_textarea[0]; - } + } } return false; }, {i : index}); @@ -635,14 +635,14 @@ casper.assert_colors_equal = function (hex_color, local_color, msg) { // hex_color: string // Hexadecimal color code, with or without preceding hash character. // local_color: string - // Local color representation. Can either be hexadecimal (default for + // Local color representation. Can either be hexadecimal (default for // phantom) or rgb (default for slimer). // Remove parentheses, hashes, semi-colons, and space characters. hex_color = hex_color.replace(/[\(\); #]/, ''); local_color = local_color.replace(/[\(\); #]/, ''); - // If the local color is rgb, clean it up and replace + // If the local color is rgb, clean it up and replace if (local_color.substr(0,3).toLowerCase() == 'rgb') { var components = local_color.substr(3).split(','); local_color = ''; @@ -652,7 +652,7 @@ casper.assert_colors_equal = function (hex_color, local_color, msg) { local_color += part; } } - + this.test.assertEquals(hex_color.toUpperCase(), local_color.toUpperCase(), msg); }; @@ -663,12 +663,12 @@ casper.notebook_test = function(test) { // Echo whether or not we are running this test using SlimerJS if (this.evaluate(function(){ return typeof InstallTrigger !== 'undefined'; // Firefox 1.0+ - })) { - console.log('This test is running in SlimerJS.'); + })) { + console.log('This test is running in SlimerJS.'); this.slimerjs = true; } - - // Make sure to remove the onbeforeunload callback. This callback is + + // Make sure to remove the onbeforeunload callback. This callback is // responsible for the "Are you sure you want to quit?" type messages. // PhantomJS ignores these prompts, SlimerJS does not which causes hangs. this.then(function(){ @@ -678,12 +678,12 @@ casper.notebook_test = function(test) { }); this.then(test); - + // Kill the kernel and delete the notebook. this.shutdown_current_kernel(); // This is still broken but shouldn't be a problem for now. // this.delete_current_notebook(); - + // This is required to clean up the page we just finished with. If we don't call this // casperjs will leak file descriptors of all the open WebSockets in that page. We // have to set this.page=null so that next time casper.start runs, it will create a @@ -692,7 +692,7 @@ casper.notebook_test = function(test) { this.page.close(); this.page = null; }); - + // Run the browser automation. this.run(function() { this.test.done(); @@ -735,7 +735,7 @@ casper.dashboard_test = function (test) { this.page.close(); this.page = null; }); - + // Run the browser automation. this.run(function() { this.test.done(); diff --git a/nbclassic/view/__init__.py b/nbclassic/view/__init__.py index 6e91c4e16..d0ad2546e 100644 --- a/nbclassic/view/__init__.py +++ b/nbclassic/view/__init__.py @@ -1 +1 @@ -"""Tornado handlers for viewing HTML files.""" \ No newline at end of file +"""Tornado handlers for viewing HTML files.""" diff --git a/nbclassic/view/handlers.py b/nbclassic/view/handlers.py index 46c71e51d..e0ecb790c 100644 --- a/nbclassic/view/handlers.py +++ b/nbclassic/view/handlers.py @@ -20,7 +20,7 @@ class CustomViewHandler(JupyterHandler): @gen.coroutine def get(self, path): """Get a view on a given path.""" - + path = path.strip('/') exists = yield ensure_async(self.contents_manager.file_exists(path)) if not exists: @@ -37,4 +37,4 @@ def get(self, path): default_handlers = [ (r"{}/view{}".format(nbclassic_path(), path_regex), CustomViewHandler), -] \ No newline at end of file +] diff --git a/pyproject.toml b/pyproject.toml index 66d3be86e..0a93ead7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,10 @@ optional-dependencies.docs = [ "sphinx-rtd-theme", "sphinxcontrib-github-alt", ] +optional-dependencies.dev = [ + "pre-commit", + "hatch" +] optional-dependencies.json-logging = [ "json-logging", ] @@ -216,3 +220,8 @@ src = "nbclassic/_version.py" [[tool.tbump.file]] src = "nbclassic/static/base/js/namespace.js" version_template = "Jupyter.version = \"{major}.{minor}.{patch}{channel}{release}\";" + +[tool.check-wheel-contents] +ignore = [ + "W002", # Duplicate files check +] diff --git a/tools/build-main.js b/tools/build-main.js index bcd0db1d6..4a5e89932 100644 --- a/tools/build-main.js +++ b/tools/build-main.js @@ -28,7 +28,7 @@ var rjs_config = { "xtermjs-fit": 'components/xterm.js-fit/index', "jquery-typeahead": 'components/jquery-typeahead/dist/jquery.typeahead.min', contents: 'empty:', - custom: 'empty:', + custom: 'empty:', 'custom-preload': 'empty:', }, diff --git a/tools/security_deprecated.js b/tools/security_deprecated.js index 195c0a5cb..cae855713 100644 --- a/tools/security_deprecated.js +++ b/tools/security_deprecated.js @@ -6,16 +6,16 @@ define([ 'components/google-caja/html-css-sanitizer-minified', ], function($, sanitize) { "use strict"; - + var noop = function (x) { return x; }; - + var caja; if (window && window.html) { caja = window.html; caja.html4 = window.html4; caja.sanitizeStylesheet = window.sanitizeStylesheet; } - + var sanitizeAttribs = function (tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger) { /** * add trusting data-attributes to the default sanitizeAttribs from caja @@ -39,7 +39,7 @@ define([ ATTRIBS['img::src'] = 0; return caja.sanitizeAttribs(tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger); }; - + var sanitize_css = function (css, tagPolicy) { /** * sanitize CSS @@ -58,7 +58,7 @@ define([ noop ); }; - + var sanitize_stylesheets = function (html, tagPolicy) { /** * sanitize just the css in style tags in a block of html @@ -75,7 +75,7 @@ define([ }); return h.html(); }; - + var sanitize_html = function (html, allow_css) { /** * sanitize HTML @@ -94,11 +94,11 @@ define([ html4.ELEMENTS.style |= html4.eflags.UNSAFE; html4.ATTRIBS.style = html4.atype.SCRIPT; } - + var record_messages = function (msg, opts) { console.log("HTML Sanitizer", msg, opts); }; - + var policy = function (tagName, attribs) { if (!(html4.ELEMENTS[tagName] & html4.eflags.UNSAFE)) { return { @@ -112,14 +112,14 @@ define([ }); } }; - + var sanitized = caja.sanitizeWithPolicy(html, policy); - + if (allow_css) { // sanitize style tags as stylesheets sanitized = sanitize_stylesheets(sanitized, policy); } - + return sanitized; }; @@ -141,7 +141,7 @@ define([ $.htmlPrefilter = prev_htmlPrefilter; // Set it back again } }; - + var security = { caja: caja, sanitize_html_and_parse: sanitize_html_and_parse, diff --git a/tools/tests/CSS Reference.ipynb b/tools/tests/CSS Reference.ipynb index eed2f65b1..6e91c1efd 100644 --- a/tools/tests/CSS Reference.ipynb +++ b/tools/tests/CSS Reference.ipynb @@ -8203,4 +8203,4 @@ }, "nbformat": 4, "nbformat_minor": 0 -} \ No newline at end of file +}