Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-jupyterlab-server for openSUSE:Factory checked in at 2023-04-24 22:31:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-jupyterlab-server (Old) and /work/SRC/openSUSE:Factory/.python-jupyterlab-server.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jupyterlab-server" Mon Apr 24 22:31:14 2023 rev:4 rq:1082331 version:2.22.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-jupyterlab-server/python-jupyterlab-server.changes 2023-01-16 18:01:44.523772042 +0100 +++ /work/SRC/openSUSE:Factory/.python-jupyterlab-server.new.1533/python-jupyterlab-server.changes 2023-04-24 22:31:26.607592744 +0200 @@ -1,0 +2,20 @@ +Sun Apr 23 20:59:17 UTC 2023 - Ben Greiner <c...@bnavigator.de> + +- Update to 2.22.1 + * Fix coverage handling (#392 #392 (@blink1073) +- Release 2.22.0 + * Optional argument to get only the schema names #385 (@brichet) +- Release 2.21.0 + * Add json5 support for page_config.json #388 (@peytondmurray) + * Ignore warning from bind_sockets #383 (@blink1073) + +------------------------------------------------------------------- +Sun Mar 19 16:52:56 UTC 2023 - Ben Greiner <c...@bnavigator.de> + +- Update to 2.20.0 + * Change periodic callback time from tuple to int #376 (@rmoe) + * Pin openapi deps #381 (@blink1073) + * Add more linting #369 (@blink1073) + * Clean up openapi compat and warnings #368 (@blink1073) + +------------------------------------------------------------------- Old: ---- jupyterlab_server-2.19.0.tar.gz New: ---- jupyterlab_server-2.22.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-jupyterlab-server.spec ++++++ --- /var/tmp/diff_new_pack.x8aV34/_old 2023-04-24 22:31:27.143595931 +0200 +++ /var/tmp/diff_new_pack.x8aV34/_new 2023-04-24 22:31:27.151595978 +0200 @@ -26,7 +26,7 @@ %endif Name: python-jupyterlab-server%{psuffix} -Version: 2.19.0 +Version: 2.22.1 Release: 0 Summary: Server components for JupyterLab and JupyterLab-like applications License: BSD-3-Clause @@ -84,12 +84,12 @@ Requires: python-Werkzeug Requires: python-ipykernel Requires: python-jupyterlab-server-openapi = %{version} -Requires: python-openapi-spec-validator >= 0.5.1 Requires: python-pytest >= 7 Requires: python-pytest-console-scripts Requires: python-pytest-jupyter-server >= 0.6.2 Requires: python-pytest-timeout Requires: python-requests-mock +Requires: (python-openapi-spec-validator >= 0.5.1 with python-openapi-spec-validator < 0.6) #Requires: python-sphinxcontrib-spelling Requires: python-strict-rfc3339 @@ -100,8 +100,8 @@ %package openapi Summary: The jupyterlab_server[openapi]] extra Requires: python-jupyterlab-server = %{version} -Requires: python-openapi-core >= 0.16.1 Requires: python-ruamel.yaml +Requires: (python-openapi-core >= 0.16.1 with python-openapi-core < 0.17) %description openapi Metapackage for the jupyterlab_server[openapi] extra ++++++ jupyterlab_server-2.19.0.tar.gz -> jupyterlab_server-2.22.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/.github/workflows/tests.yml new/jupyterlab_server-2.22.1/.github/workflows/tests.yml --- old/jupyterlab_server-2.19.0/.github/workflows/tests.yml 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/.github/workflows/tests.yml 2020-02-02 01:00:00.000000000 +0100 @@ -40,10 +40,17 @@ - name: Run the tests on pypy if: ${{ startsWith(matrix.python-version, 'pypy') || startsWith(matrix.python-version, '3.7') }} run: hatch run cov:nowarn - - name: Upload coverage - run: | - pip install codecov coverage[toml] - codecov + - uses: jupyterlab/maintainer-tools/.github/actions/upload-coverage@v1 + + coverage_report: + name: Combine & check coverage + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: jupyterlab/maintainer-tools/.github/actions/report-coverage@v1 + with: + fail_under: 80 test_lint: name: Test Lint @@ -111,7 +118,7 @@ runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/make-sdist@v1 @@ -140,7 +147,7 @@ tests_check: # This job does nothing and is only used for the branch protection if: always() needs: - - test + - coverage_report - test_lint - check_links - docs diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/.pre-commit-config.yaml new/jupyterlab_server-2.22.1/.pre-commit-config.yaml --- old/jupyterlab_server-2.19.0/.pre-commit-config.yaml 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/.pre-commit-config.yaml 2020-02-02 01:00:00.000000000 +0100 @@ -19,7 +19,7 @@ - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.19.2 + rev: 0.22.0 hooks: - id: check-github-workflows @@ -31,12 +31,12 @@ [mdformat-gfm, mdformat-frontmatter, mdformat-footnote] - repo: https://github.com/psf/black - rev: 22.12.0 + rev: 23.3.0 hooks: - id: black - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.206 + rev: v0.0.260 hooks: - id: ruff args: ["--fix"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/CHANGELOG.md new/jupyterlab_server-2.22.1/CHANGELOG.md --- old/jupyterlab_server-2.19.0/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100 @@ -2,6 +2,78 @@ <!-- <START NEW CHANGELOG ENTRY> --> +## 2.22.1 + +([Full Changelog](https://github.com/jupyterlab/jupyterlab_server/compare/v2.22.0...584d2f0138697f8972402e72a744e84ac3d26137)) + +### Maintenance and upkeep improvements + +- Fix coverage handling (#392 [#392](https://github.com/jupyterlab/jupyterlab_server/pull/392) ([@blink1073](https://github.com/blink1073)) + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterlab/jupyterlab_server/graphs/contributors?from=2023-03-31&to=2023-04-13&type=c)) + +[@blink1073](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Ablink1073+updated%3A2023-03-31..2023-04-13&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Apre-commit-ci+updated%3A2023-03-31..2023-04-13&type=Issues) + +<!-- <END NEW CHANGELOG ENTRY> --> + +## 2.22.0 + +([Full Changelog](https://github.com/jupyterlab/jupyterlab_server/compare/v2.21.0...cd829a8f5ca1c941cddd08dfcdbf1d8b13a7d433)) + +### Enhancements made + +- Optional argument to get only the schema names [#385](https://github.com/jupyterlab/jupyterlab_server/pull/385) ([@brichet](https://github.com/brichet)) + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterlab/jupyterlab_server/graphs/contributors?from=2023-03-22&to=2023-03-31&type=c)) + +[@brichet](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Abrichet+updated%3A2023-03-22..2023-03-31&type=Issues) + +## 2.21.0 + +([Full Changelog](https://github.com/jupyterlab/jupyterlab_server/compare/v2.20.0...48be03a73c11b2f800ad768aed30d417b248d98e)) + +### Enhancements made + +- Add json5 support for page_config.json [#388](https://github.com/jupyterlab/jupyterlab_server/pull/388) ([@peytondmurray](https://github.com/peytondmurray)) + +### Maintenance and upkeep improvements + +- Updates test dependencies [#387](https://github.com/jupyterlab/jupyterlab_server/pull/387) ([@brichet](https://github.com/brichet)) +- Ignore warning from bind_sockets [#383](https://github.com/jupyterlab/jupyterlab_server/pull/383) ([@blink1073](https://github.com/blink1073)) +- Bump actions/checkout from 2 to 3 [#379](https://github.com/jupyterlab/jupyterlab_server/pull/379) ([@dependabot](https://github.com/dependabot)) + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterlab/jupyterlab_server/graphs/contributors?from=2023-03-06&to=2023-03-22&type=c)) + +[@blink1073](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Ablink1073+updated%3A2023-03-06..2023-03-22&type=Issues) | [@brichet](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Abrichet+updated%3A2023-03-06..2023-03-22&type=Issues) | [@codecov-commenter](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Acodecov-commenter+updated%3A2023-03-06..2023-03-22&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Adependabot+updated%3A2023-03-06..2023-03-22&type=Issues) | [@peytondmurray](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Apeytondmurray+updated%3A2023-03-06..2023-03-22&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Apre-commit-ci+updated%3A2023-03-06..2023-03-22&type=Issues) | [@welcome](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+in volves%3Awelcome+updated%3A2023-03-06..2023-03-22&type=Issues) + +## 2.20.0 + +([Full Changelog](https://github.com/jupyterlab/jupyterlab_server/compare/v2.19.0...4a08b8418248f4068a3ae0bdf4aa93c524130421)) + +### Bugs fixed + +- Change periodic callback time from tuple to int (#376 [#376](https://github.com/jupyterlab/jupyterlab_server/pull/376) ([@rmoe](https://github.com/rmoe)) + +### Maintenance and upkeep improvements + +- Pin openapi deps [#381](https://github.com/jupyterlab/jupyterlab_server/pull/381) ([@blink1073](https://github.com/blink1073)) +- Revert "Fix some CodeQL notices" [#372](https://github.com/jupyterlab/jupyterlab_server/pull/372) ([@fcollonval](https://github.com/fcollonval)) +- Fix some CodeQL notices [#371](https://github.com/jupyterlab/jupyterlab_server/pull/371) ([@fcollonval](https://github.com/fcollonval)) +- Add more linting [#369](https://github.com/jupyterlab/jupyterlab_server/pull/369) ([@blink1073](https://github.com/blink1073)) +- Clean up openapi compat and warnings [#368](https://github.com/jupyterlab/jupyterlab_server/pull/368) ([@blink1073](https://github.com/blink1073)) + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterlab/jupyterlab_server/graphs/contributors?from=2023-01-16&to=2023-03-06&type=c)) + +[@blink1073](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Ablink1073+updated%3A2023-01-16..2023-03-06&type=Issues) | [@codecov-commenter](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Acodecov-commenter+updated%3A2023-01-16..2023-03-06&type=Issues) | [@fcollonval](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Afcollonval+updated%3A2023-01-16..2023-03-06&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Apre-commit-ci+updated%3A2023-01-16..2023-03-06&type=Issues) | [@rmoe](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Armoe+updated%3A2023-01-16..2023-03-06&type=Issues) | [@welcome](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Awelcome+updated%3A2023-01-16..2023-03-06&type=Issues) + ## 2.19.0 ([Full Changelog](https://github.com/jupyterlab/jupyterlab_server/compare/v2.18.0...a226eaa4e0a55a167ef7ab6ef7da53a2013a3fb1)) @@ -21,8 +93,6 @@ [@blink1073](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Ablink1073+updated%3A2023-01-03..2023-01-16&type=Issues) | [@codecov-commenter](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Acodecov-commenter+updated%3A2023-01-03..2023-01-16&type=Issues) | [@fcollonval](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyterlab_server+involves%3Afcollonval+updated%3A2023-01-03..2023-01-16&type=Issues) -<!-- <END NEW CHANGELOG ENTRY> --> - ## 2.18.0 ([Full Changelog](https://github.com/jupyterlab/jupyterlab_server/compare/v2.17.0...a2528876192e34fa2856b8fb3941148c6447d591)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/CONTRIBUTING.md new/jupyterlab_server-2.22.1/CONTRIBUTING.md --- old/jupyterlab_server-2.19.0/CONTRIBUTING.md 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/CONTRIBUTING.md 2020-02-02 01:00:00.000000000 +0100 @@ -28,7 +28,7 @@ git clone https://github.com/jupyterlab/jupyterlab_server.git cd jupyterlab_server pip install -e .[test] # install test dependencies -pytest --pyargs jupyterlab_server +hatch run cov:test # optionally, arguments of the pytest CLI can be added ``` ## Code Styling diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/PKG-INFO new/jupyterlab_server-2.22.1/PKG-INFO --- old/jupyterlab_server-2.19.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: jupyterlab_server -Version: 2.19.0 +Version: 2.22.1 Summary: A set of server components for JupyterLab and JupyterLab like applications. Project-URL: Homepage, https://jupyterlab-server.readthedocs.io Project-URL: Documentation, https://jupyterlab-server.readthedocs.io @@ -71,13 +71,13 @@ Requires-Dist: sphinx-copybutton; extra == 'docs' Requires-Dist: sphinxcontrib-openapi; extra == 'docs' Provides-Extra: openapi -Requires-Dist: openapi-core>=0.16.1; extra == 'openapi' +Requires-Dist: openapi-core~=0.16.1; extra == 'openapi' Requires-Dist: ruamel-yaml; extra == 'openapi' Provides-Extra: test -Requires-Dist: codecov; extra == 'test' +Requires-Dist: hatch; extra == 'test' Requires-Dist: ipykernel; extra == 'test' Requires-Dist: jupyterlab-server[openapi]; extra == 'test' -Requires-Dist: openapi-spec-validator>=0.5.1; extra == 'test' +Requires-Dist: openapi-spec-validator~=0.5.1; extra == 'test' Requires-Dist: pytest-console-scripts; extra == 'test' Requires-Dist: pytest-cov; extra == 'test' Requires-Dist: pytest-jupyter[server]>=0.6.2; extra == 'test' @@ -91,7 +91,6 @@ # jupyterlab server -[](https://codecov.io/gh/jupyterlab/jupyterlab_server) [](https://github.com/jupyterlab/jupyterlab_server/actions?query=branch%3Amaster+workflow%3A%22Tests%22) [](http://jupyterlab_server.readthedocs.io/en/stable/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/README.md new/jupyterlab_server-2.22.1/README.md --- old/jupyterlab_server-2.19.0/README.md 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/README.md 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,5 @@ # jupyterlab server -[](https://codecov.io/gh/jupyterlab/jupyterlab_server) [](https://github.com/jupyterlab/jupyterlab_server/actions?query=branch%3Amaster+workflow%3A%22Tests%22) [](http://jupyterlab_server.readthedocs.io/en/stable/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/codecov.yml new/jupyterlab_server-2.22.1/codecov.yml --- old/jupyterlab_server-2.19.0/codecov.yml 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/codecov.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -coverage: - status: - project: - default: - target: auto - threshold: 1 - patch: - default: - target: 0% diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/_version.py new/jupyterlab_server-2.22.1/jupyterlab_server/_version.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/_version.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/_version.py 2020-02-02 01:00:00.000000000 +0100 @@ -7,7 +7,7 @@ """ import re -__version__ = "2.19.0" +__version__ = "2.22.1" # Build up version_info tuple for backwards compatibility pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/config.py new/jupyterlab_server-2.22.1/jupyterlab_server/config.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/config.py 2020-02-02 01:00:00.000000000 +0100 @@ -9,12 +9,12 @@ from itertools import chain from os.path import join as pjoin +import json5 # type:ignore from jupyter_core.paths import SYSTEM_CONFIG_PATH, jupyter_config_dir, jupyter_path from jupyter_server.services.config.manager import ConfigManager, recursive_update +from jupyter_server.utils import url_path_join as ujoin from traitlets import Bool, HasTraits, List, Unicode, default -from .server import url_path_join as ujoin - # ----------------------------------------------------------------------------- # Module globals # ----------------------------------------------------------------------------- @@ -79,7 +79,27 @@ return cm.get("page_config") -def get_page_config(labextensions_path, app_settings_dir=None, logger=None): +def load_config(path): + """Load either a json5 or a json config file. + + Parameters + ---------- + path : str + Path to the file to be loaded + + Returns + ------- + Dict[Any, Any] + Dictionary of json or json5 data + """ + with open(path, encoding="utf-8") as fid: + if path.endswith('.json5'): + return json5.load(fid) + else: + return json.load(fid) + + +def get_page_config(labextensions_path, app_settings_dir=None, logger=None): # noqa """Get the page config for the application handler""" # Build up the full page config page_config: dict = {} @@ -88,17 +108,20 @@ # Start with the app_settings_dir as lowest priority if app_settings_dir: - app_page_config = pjoin(app_settings_dir, "page_config.json") - if osp.exists(app_page_config): - with open(app_page_config, encoding="utf-8") as fid: - data = json.load(fid) - - # Convert lists to dicts - for key in [disabled_key, "deferredExtensions"]: - if key in data: - data[key] = {key: True for key in data[key]} + config_paths = [ + pjoin(app_settings_dir, "page_config.json5"), + pjoin(app_settings_dir, "page_config.json"), + ] + for path in config_paths: + if osp.exists(path): + data = load_config(path) + # Convert lists to dicts + for key in [disabled_key, "deferredExtensions"]: + if key in data: + data[key] = {key: True for key in data[key]} - recursive_update(page_config, data) + recursive_update(page_config, data) + break # Get the traitlets config static_page_config = get_static_page_config(logger=logger, level="all") @@ -113,7 +136,7 @@ # Ensure there is a disabled key page_config.setdefault(disabled_key, {}) - for (_, ext_data) in federated_exts.items(): + for _, ext_data in federated_exts.items(): if "_build" not in ext_data["jupyterlab"]: logger.warning("%s is not a valid extension" % ext_data["name"]) continue @@ -143,7 +166,7 @@ with open(package_data_file, encoding="utf-8") as fid: app_data = json.load(fid) all_ext_data = app_data["jupyterlab"].get("extensionMetadata", {}) - for (ext, ext_data) in all_ext_data.items(): + for ext, ext_data in all_ext_data.items(): if ext in disabled_by_extensions_all: continue if ext_data.get(disabled_key): @@ -164,8 +187,7 @@ page_config[disabled_key] = rollup_disabled # Convert dictionaries to lists to give to the front end - for (key, value) in page_config.items(): - + for key, value in page_config.items(): if isinstance(value, dict): page_config[key] = [subkey for subkey in value if value[subkey]] @@ -321,7 +343,8 @@ """ allowed = ["all", "user", "sys_prefix", "system", "app", "extension"] if level not in allowed: - raise ValueError(f"Page config level must be one of: {allowed}") + msg = f"Page config level must be one of: {allowed}" + raise ValueError(msg) config_name = "labconfig" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/handlers.py new/jupyterlab_server-2.22.1/jupyterlab_server/handlers.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/handlers.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/handlers.py 2020-02-02 01:00:00.000000000 +0100 @@ -8,14 +8,14 @@ from functools import lru_cache from urllib.parse import urlparse +from jupyter_server.base.handlers import FileFindHandler, JupyterHandler from jupyter_server.extension.handler import ExtensionHandlerJinjaMixin, ExtensionHandlerMixin +from jupyter_server.utils import url_path_join as ujoin from tornado import template, web from .config import LabConfig, get_page_config, recursive_update from .licenses_handler import LicensesHandler, LicensesManager from .listings_handler import ListingsHandler, fetch_listings -from .server import FileFindHandler, JupyterHandler -from .server import url_path_join as ujoin from .settings_handler import SettingsHandler from .themes_handler import ThemesHandler from .translations_handler import TranslationsHandler @@ -98,8 +98,8 @@ .relative_to(server_root) .as_posix() ) - except Exception: - pass # we do not require the preferred_dir trait to be present + except Exception: # noqa S110 + pass # JupyterLab relies on an unset/default path being "/" page_config["preferredPath"] = preferred_path or "/" @@ -175,7 +175,7 @@ return page_config -def add_handlers(handlers, extension_app): +def add_handlers(handlers, extension_app): # noqa """Add the appropriate handlers to the web app.""" # Normalize directories. for name in LabConfig.class_trait_names(): @@ -246,7 +246,6 @@ # Handle saved workspaces. if extension_app.workspaces_dir: - workspaces_config = {"manager": WorkspacesManager(extension_app.workspaces_dir)} # Handle requests for the list of workspaces. Make slash optional. @@ -264,14 +263,14 @@ allowed_extensions_uris = settings_config.get("allowed_extensions_uris", "") if (blocked_extensions_uris) and (allowed_extensions_uris): - warnings.warn( + warnings.warn( # noqa B028 "Simultaneous blocked_extensions_uris and allowed_extensions_uris is not supported. Please define only one of those." ) import sys sys.exit(-1) - ListingsHandler.listings_refresh_seconds = settings_config.get( # type:ignore + ListingsHandler.listings_refresh_seconds = settings_config.get( "listings_refresh_seconds", 60 * 60 ) ListingsHandler.listings_request_opts = settings_config.get("listings_request_options", {}) @@ -291,10 +290,10 @@ ): from tornado import ioloop - callback_time = (ListingsHandler.listings_refresh_seconds * 1000,) # type:ignore + callback_time = ListingsHandler.listings_refresh_seconds * 1000 ListingsHandler.pc = ioloop.PeriodicCallback( lambda: fetch_listings(None), # type:ignore - callback_time=callback_time, # type:ignore + callback_time=callback_time, jitter=0.1, ) ListingsHandler.pc.start() # type:ignore diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/licenses_app.py new/jupyterlab_server-2.22.1/jupyterlab_server/licenses_app.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/licenses_app.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/licenses_app.py 2020-02-02 01:00:00.000000000 +0100 @@ -93,5 +93,5 @@ full_text=self.full_text, bundles_pattern=self.bundles_pattern, )[0] - print(report) # noqa + print(report) self.exit(0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/licenses_handler.py new/jupyterlab_server-2.22.1/jupyterlab_server/licenses_handler.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/licenses_handler.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/licenses_handler.py 2020-02-02 01:00:00.000000000 +0100 @@ -11,12 +11,12 @@ from concurrent.futures import ThreadPoolExecutor from pathlib import Path +from jupyter_server.base.handlers import APIHandler from tornado import gen, web from traitlets import List, Unicode from traitlets.config import LoggingConfigurable from .config import get_federated_extensions -from .server import APIHandler # this is duplicated in @juptyerlab/builder DEFAULT_THIRD_PARTY_LICENSE_FILE = "third-party-licenses.json" @@ -85,7 +85,8 @@ "text/markdown", ) - raise ValueError(f"Unsupported report format {report_format}.") + msg = f"Unsupported report format {report_format}." + raise ValueError(msg) def report_json(self, bundles): """create a JSON report @@ -97,7 +98,7 @@ """create a CSV report""" outfile = io.StringIO() fieldnames = ["name", "versionInfo", "licenseId", "extractedText"] - writer = csv.DictWriter(outfile, fieldnames=["bundle"] + fieldnames) + writer = csv.DictWriter(outfile, fieldnames=["bundle", *fieldnames]) writer.writeheader() for bundle_name, bundle in bundles.items(): for package in bundle["packages"]: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/listings_handler.py new/jupyterlab_server-2.22.1/jupyterlab_server/listings_handler.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/listings_handler.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/listings_handler.py 2020-02-02 01:00:00.000000000 +0100 @@ -7,8 +7,7 @@ import requests import tornado - -from .server import APIHandler +from jupyter_server.base.handlers import APIHandler LISTINGS_URL_SUFFIX = "@jupyterlab/extensionmanager-extension/listings.json" @@ -79,6 +78,8 @@ allowed_extensions: list = [] # The provider request options to be used for the request library. listings_request_opts: dict = {} + # The callback time for the periodic callback in seconds. + listings_refresh_seconds: int # The PeriodicCallback that schedule the call to fetch_listings method. pc = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/process.py new/jupyterlab_server-2.22.1/jupyterlab_server/process.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/process.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/process.py 2020-02-02 01:00:00.000000000 +0100 @@ -85,10 +85,12 @@ Whether to suppress output. """ if not isinstance(cmd, (list, tuple)): - raise ValueError("Command must be given as a list") + msg = "Command must be given as a list" + raise ValueError(msg) if kill_event and kill_event.is_set(): - raise ValueError("Process aborted") + msg = "Process aborted" + raise ValueError(msg) self.logger = logger or self.get_log() self._last_line = "" @@ -117,7 +119,7 @@ try: proc.wait(timeout=2.0) except subprocess.TimeoutExpired: - if os.name == "nt": + if os.name == "nt": # noqa sig = signal.SIGBREAK # type:ignore else: sig = signal.SIGKILL @@ -143,7 +145,8 @@ while proc.poll() is None: if kill_event.is_set(): self.terminate() - raise ValueError("Process was aborted") + msg = "Process was aborted" + raise ValueError(msg) time.sleep(1.0) return self.terminate() @@ -155,7 +158,8 @@ while proc.poll() is None: if kill_event.is_set(): self.terminate() - raise ValueError("Process was aborted") + msg = "Process was aborted" + raise ValueError(msg) yield gen.sleep(1.0) raise gen.Return(self.terminate()) @@ -218,8 +222,9 @@ while 1: line = self._stdout.readline().decode("utf-8") if not line: - raise RuntimeError("Process ended improperly") - print(line.rstrip()) # noqa + msg = "Process ended improperly" + raise RuntimeError(msg) + print(line.rstrip()) if re.match(startup_regex, line): break @@ -259,7 +264,7 @@ if not buf: return - print(buf.decode("utf-8"), end="") # noqa + print(buf.decode("utf-8"), end="") def _create_process(self, **kwargs): """Create the watcher helper process.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/server.py new/jupyterlab_server-2.22.1/jupyterlab_server/server.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/server.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/server.py 2020-02-02 01:00:00.000000000 +0100 @@ -2,7 +2,9 @@ # Distributed under the terms of the Modified BSD License. """Server api.""" -from jupyter_server import _tz as tz # noqa +# FIXME TODO Deprecated remove this file for the next major version +# Downstream package must import those items from `jupyter_server` directly +from jupyter_server import _tz as tz from jupyter_server.base.handlers import ( APIHandler, FileFindHandler, @@ -15,5 +17,5 @@ RED_DISABLED, RED_X, ) -from jupyter_server.serverapp import ServerApp, aliases, flags # noqa -from jupyter_server.utils import url_escape, url_path_join # noqa +from jupyter_server.serverapp import ServerApp, aliases, flags +from jupyter_server.utils import url_escape, url_path_join diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/settings_handler.py new/jupyterlab_server-2.22.1/jupyterlab_server/settings_handler.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/settings_handler.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/settings_handler.py 2020-02-02 01:00:00.000000000 +0100 @@ -26,12 +26,25 @@ @web.authenticated def get(self, schema_name=""): - """Get setting(s)""" + """ + Get setting(s) + + Parameters + ---------- + schema_name: str + The id of a unique schema to send, added to the URL + + ## NOTES: + An optional argument `ids_only=true` can be provided in the URL to get only the + ids of the schemas instead of the content. + """ # Need to be update here as translator locale is not change when a new locale is put # from frontend locale = self.get_current_locale() translator.set_locale(locale) + ids_only = self.get_argument('ids_only', '') == 'true' + result, warnings = get_settings( self.app_settings_dir, self.schemas_dir, @@ -40,6 +53,7 @@ schema_name=schema_name, overrides=self.overrides, translator=translator.translate_schema, + ids_only=ids_only, ) # Print all warnings. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/settings_utils.py new/jupyterlab_server-2.22.1/jupyterlab_server/settings_utils.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/settings_utils.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/settings_utils.py 2020-02-02 01:00:00.000000000 +0100 @@ -9,10 +9,11 @@ import json5 # type:ignore from jsonschema import Draft4Validator as Validator from jsonschema import ValidationError +from jupyter_server import _tz as tz +from jupyter_server.base.handlers import APIHandler from jupyter_server.services.config.manager import ConfigManager, recursive_update from tornado import web -from .server import APIHandler, tz from .translation_utils import DEFAULT_LOCALE, L10N_SCHEMA_NAME, SYS_LOCALE, is_valid_locale # The JupyterLab settings file extension. @@ -128,11 +129,13 @@ extension=".json", labextensions_path=None, translator=None, + ids_only=False, ): """ Returns a tuple containing: - the list of plugins, schemas, and their settings, - respecting any defaults that may have been overridden. + respecting any defaults that may have been overridden if `ids_only=False`, + otherwise a list of dict containing only the ids of plugins. - the list of warnings that were generated when validating the user overrides against the schemas. """ @@ -158,16 +161,20 @@ ).replace( "\\", "/" ) # Normalize slashes. - schema, version = _get_schema(schemas_dir, schema_name, overrides, None) - if translator is not None: - schema = translator(schema) - user_settings = _get_user_settings(settings_dir, schema_name, schema) - if user_settings["warning"]: - warnings.append(user_settings.pop("warning")) + if ids_only: + settings[_id] = dict(id=_id) + else: + schema, version = _get_schema(schemas_dir, schema_name, overrides, None) + if translator is not None: + schema = translator(schema) + user_settings = _get_user_settings(settings_dir, schema_name, schema) + + if user_settings["warning"]: + warnings.append(user_settings.pop("warning")) - # Add the plugin to the list of settings. - settings[_id] = dict(id=_id, schema=schema, version=version, **user_settings) + # Add the plugin to the list of settings. + settings[_id] = dict(id=_id, schema=schema, version=version, **user_settings) if labextensions_path is not None: schema_paths = [] @@ -177,8 +184,8 @@ schema_paths.sort() - for schema_path in schema_paths: - schema_path = schema_path.replace(os.sep, "/") + for schema_path_ in schema_paths: + schema_path = schema_path_.replace(os.sep, "/") base_dir, rel_path = schema_path.split("schemas/") @@ -194,16 +201,21 @@ if _id in federated_settings: continue - schema, version = _get_schema( - schemas_dir, schema_name, overrides, labextensions_path=labextensions_path - ) - user_settings = _get_user_settings(settings_dir, schema_name, schema) - - if user_settings["warning"]: - warnings.append(user_settings.pop("warning")) - - # Add the plugin to the list of settings. - federated_settings[_id] = dict(id=_id, schema=schema, version=version, **user_settings) + if ids_only: + federated_settings[_id] = dict(id=_id) + else: + schema, version = _get_schema( + schemas_dir, schema_name, overrides, labextensions_path=labextensions_path + ) + user_settings = _get_user_settings(settings_dir, schema_name, schema) + + if user_settings["warning"]: + warnings.append(user_settings.pop("warning")) + + # Add the plugin to the list of settings. + federated_settings[_id] = dict( + id=_id, schema=schema, version=version, **user_settings + ) settings.update(federated_settings) settings_list = [settings[key] for key in sorted(settings.keys(), reverse=True)] @@ -316,6 +328,7 @@ overrides=None, labextensions_path=None, translator=None, + ids_only=False, ): """ Get settings. @@ -342,9 +355,10 @@ ------- tuple The first item is a dictionary with a list of setting if no `schema_name` - was provided, otherwise it is a dictionary with id, raw, scheme, settings - and version keys. The second item is a list of warnings. Warnings will - either be a list of i) strings with the warning messages or ii) `None`. + was provided (only the ids if `ids_only=True`), otherwise it is a dictionary + with id, raw, scheme, settings and version keys. + The second item is a list of warnings. Warnings will either be a list of + i) strings with the warning messages or ii) `None`. """ result = {} warnings = [] @@ -366,6 +380,7 @@ overrides, labextensions_path=labextensions_path, translator=translator, + ids_only=ids_only, ) result = { "settings": settings_list, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/spec.py new/jupyterlab_server-2.22.1/jupyterlab_server/spec.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/spec.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/spec.py 2020-02-02 01:00:00.000000000 +0100 @@ -14,10 +14,10 @@ def get_openapi_spec() -> "Spec": """Get the OpenAPI spec object.""" - from openapi_core.spec.shortcuts import create_spec + from openapi_core.spec.paths import Spec openapi_spec_dict = get_openapi_spec_dict() - return create_spec(openapi_spec_dict) + return Spec.from_dict(openapi_spec_dict) def get_openapi_spec_dict(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/test_utils.py new/jupyterlab_server-2.22.1/jupyterlab_server/test_utils.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/test_utils.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/test_utils.py 2020-02-02 01:00:00.000000000 +0100 @@ -12,10 +12,15 @@ import tornado.httpclient import tornado.web + +try: + from openapi_core import V30RequestValidator, V30ResponseValidator # type:ignore[attr-defined] +except ImportError: + V30RequestValidator = None + V30ResponseValidator = None + from openapi_core import openapi_request_validator, openapi_response_validator from openapi_core.spec.paths import Spec -from openapi_core.validation.request import openapi_request_validator from openapi_core.validation.request.datatypes import RequestParameters -from openapi_core.validation.response import openapi_response_validator from tornado.httpclient import HTTPRequest, HTTPResponse from werkzeug.datastructures import Headers, ImmutableMultiDict @@ -37,7 +42,8 @@ self.request = request self.spec = spec if request.url is None: - raise RuntimeError("Request URL is missing") + msg = "Request URL is missing" + raise RuntimeError(msg) self._url_parsed = urlparse(request.url) cookie: SimpleCookie = SimpleCookie() @@ -71,12 +77,11 @@ # https://github.com/OAI/OpenAPI-Specification/issues/892 url = None o = urlparse(self.request.url) - for path in self.spec["paths"]: + for path_ in self.spec["paths"]: if url: continue - has_arg = "{" in path - if has_arg: - path = path[: path.index("{")] + has_arg = "{" in path_ + path = path_[: path_.index("{")] if has_arg else path_ if path in o.path: u = o.path[o.path.index(path) :] if not has_arg and len(u) == len(path): @@ -85,7 +90,8 @@ url = u[: len(path)] + r"foo" if url is None: - raise ValueError(f"Could not find matching pattern for {o.path}") + msg = f"Could not find matching pattern for {o.path}" + raise ValueError(msg) return url @property @@ -95,8 +101,11 @@ @property def body(self) -> Optional[str]: + if self.request.body is None: + return None if not isinstance(self.request.body, bytes): - raise AssertionError('Request body is invalid') + msg = 'Request body is invalid' + raise AssertionError(msg) return self.request.body.decode("utf-8") @property @@ -121,7 +130,8 @@ @property def data(self) -> str: if not isinstance(self.response.body, bytes): - raise AssertionError('Response body is invalid') + msg = 'Response body is invalid' + raise AssertionError(msg) return self.response.body.decode("utf-8") @property @@ -142,34 +152,42 @@ openapi_spec = get_openapi_spec() request = TornadoOpenAPIRequest(response.request, openapi_spec) - result = openapi_request_validator.validate(openapi_spec, request) + if V30RequestValidator: + result = V30RequestValidator(openapi_spec).validate(request) + else: + result = openapi_request_validator.validate(openapi_spec, request) result.raise_for_errors() response = TornadoOpenAPIResponse(response) - result2 = openapi_response_validator.validate(openapi_spec, request, response) + if V30ResponseValidator: + result2 = V30ResponseValidator(openapi_spec).validate(request, response) + else: + result2 = openapi_response_validator.validate(openapi_spec, request, response) result2.raise_for_errors() def maybe_patch_ioloop(): """a windows 3.8+ patch for the asyncio loop""" - if sys.platform.startswith("win") and tornado.version_info < (6, 1): - if sys.version_info >= (3, 8): - - try: - from asyncio import WindowsProactorEventLoopPolicy, WindowsSelectorEventLoopPolicy - except ImportError: - pass - # not affected - else: - from asyncio import get_event_loop_policy, set_event_loop_policy - - if type(get_event_loop_policy()) is WindowsProactorEventLoopPolicy: - # WindowsProactorEventLoopPolicy is not compatible with tornado 6 - # fallback to the pre-3.8 default of Selector - set_event_loop_policy(WindowsSelectorEventLoopPolicy()) + if ( + sys.platform.startswith("win") + and tornado.version_info < (6, 1) + and sys.version_info >= (3, 8) + ): + try: + from asyncio import WindowsProactorEventLoopPolicy, WindowsSelectorEventLoopPolicy + except ImportError: + pass + # not affected + else: + from asyncio import get_event_loop_policy, set_event_loop_policy + + if type(get_event_loop_policy()) is WindowsProactorEventLoopPolicy: + # WindowsProactorEventLoopPolicy is not compatible with tornado 6 + # fallback to the pre-3.8 default of Selector + set_event_loop_policy(WindowsSelectorEventLoopPolicy()) -def expected_http_error(error, expected_code, expected_message=None): +def expected_http_error(error, expected_code, expected_message=None): # noqa """Check that the error matches the expected output error.""" e = error.value if isinstance(e, tornado.web.HTTPError): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/themes_handler.py new/jupyterlab_server-2.22.1/jupyterlab_server/themes_handler.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/themes_handler.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/themes_handler.py 2020-02-02 01:00:00.000000000 +0100 @@ -6,11 +6,10 @@ import os import re from glob import glob -from os import path as osp from urllib.parse import urlparse -from .server import FileFindHandler -from .server import url_path_join as ujoin +from jupyter_server.base.handlers import FileFindHandler +from jupyter_server.utils import url_path_join as ujoin class ThemesHandler(FileFindHandler): @@ -50,7 +49,7 @@ This method should either return a byte string or an iterator of byte strings. """ - base, ext = osp.splitext(abspath) + base, ext = os.path.splitext(abspath) if ext != ".css": return FileFindHandler.get_content(abspath, start, end) @@ -59,7 +58,7 @@ def get_content_size(self): """Retrieve the total size of the resource at the given path.""" assert self.absolute_path is not None # noqa - base, ext = osp.splitext(self.absolute_path) + base, ext = os.path.splitext(self.absolute_path) if ext != ".css": return FileFindHandler.get_content_size(self) else: @@ -71,7 +70,7 @@ with open(self.absolute_path, "rb") as fid: data = fid.read().decode("utf-8") - basedir = osp.dirname(self.path).replace(os.sep, "/") + basedir = os.path.dirname(self.path).replace(os.sep, "/") basepath = ujoin(self.themes_url, basedir) # Replace local paths with mangled paths. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/translation_utils.py new/jupyterlab_server-2.22.1/jupyterlab_server/translation_utils.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/translation_utils.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/translation_utils.py 2020-02-02 01:00:00.000000000 +0100 @@ -348,31 +348,30 @@ found_packages_locales, message = get_installed_packages_locale(locale_) locale_data = {} messages = message.split("\n") - if not message and is_valid_locale(locale_): - if locale_ in found_locales: - path = found_locales[locale_] - for root, __, files in os.walk(path, topdown=False): - for name in files: - if name.endswith(".json"): - pkg_name = name.replace(".json", "") - json_path = os.path.join(root, name) - try: - with open(json_path, encoding="utf-8") as fh: - merged_data = json.load(fh) - except Exception: - messages.append(traceback.format_exc()) - - # Load packages with locale data and merge them - if pkg_name in found_packages_locales: - pkg_data = found_packages_locales[pkg_name] - merged_data = merge_locale_data(merged_data, pkg_data) - - locale_data[pkg_name] = merged_data - - # Check if package locales exist that do not exists in language pack - for pkg_name, data in found_packages_locales.items(): - if pkg_name not in locale_data: - locale_data[pkg_name] = data + if not message and is_valid_locale(locale_) and locale_ in found_locales: + path = found_locales[locale_] + for root, __, files in os.walk(path, topdown=False): + for name in files: + if name.endswith(".json"): + pkg_name = name.replace(".json", "") + json_path = os.path.join(root, name) + try: + with open(json_path, encoding="utf-8") as fh: + merged_data = json.load(fh) + except Exception: + messages.append(traceback.format_exc()) + + # Load packages with locale data and merge them + if pkg_name in found_packages_locales: + pkg_data = found_packages_locales[pkg_name] + merged_data = merge_locale_data(merged_data, pkg_data) + + locale_data[pkg_name] = merged_data + + # Check if package locales exist that do not exists in language pack + for pkg_name, data in found_packages_locales.items(): + if pkg_name not in locale_data: + locale_data[pkg_name] = data return locale_data, "\n".join(messages) @@ -410,7 +409,7 @@ mod = importlib.import_module(language_pack_module) assert mod.__file__ is not None # noqa localedir = os.path.join(os.path.dirname(mod.__file__), LOCALE_DIR) - except Exception: + except Exception: # noqa S110 # no-op pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/translations_handler.py new/jupyterlab_server-2.22.1/jupyterlab_server/translations_handler.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/translations_handler.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/translations_handler.py 2020-02-02 01:00:00.000000000 +0100 @@ -52,15 +52,14 @@ data, message = await current_loop.run_in_executor( None, partial(get_language_pack, locale) ) - if data == {} and message == "": + if data == {} and not message: if is_valid_locale(locale): message = f"Language pack '{locale}' not installed!" else: message = f"Language pack '{locale}' not valid!" - else: + elif is_valid_locale(locale): # only change locale if the language pack is installed and valid - if is_valid_locale(locale): - translator.set_locale(locale) + translator.set_locale(locale) except Exception: message = traceback.format_exc() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/workspaces_app.py new/jupyterlab_server-2.22.1/jupyterlab_server/workspaces_app.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/workspaces_app.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/workspaces_app.py 2020-02-02 01:00:00.000000000 +0100 @@ -68,12 +68,12 @@ workspaces = self.manager.list_workspaces() if self.jsonlines: for workspace in workspaces: - print(json.dumps(workspace)) # noqa + print(json.dumps(workspace)) elif self.json: - print(json.dumps(workspaces)) # noqa + print(json.dumps(workspaces)) else: for workspace in workspaces: - print(workspace["metadata"]["id"]) # noqa + print(workspace["metadata"]["id"]) class WorkspaceExportApp(JupyterApp, LabConfig): @@ -103,7 +103,7 @@ raw = DEFAULT_WORKSPACE if not self.extra_args else self.extra_args[0] try: workspace = self.manager.load(raw) - print(json.dumps(workspace)) # noqa + print(json.dumps(workspace)) except Exception: # pragma: no cover self.log.error(json.dumps(dict(data=dict(), metadata=dict(id=raw)))) @@ -175,14 +175,15 @@ workspace = json.load(data) if "data" not in workspace: - raise Exception("The `data` field is missing.") + msg = "The `data` field is missing." + raise Exception(msg) # If workspace_name is set in config, inject the # name into the workspace metadata. - if self.workspace_name is not None and self.workspace_name != "": + if self.workspace_name is not None and self.workspace_name: workspace["metadata"] = {"id": self.workspace_name} - else: - if "id" not in workspace["metadata"]: - raise Exception("The `id` field is missing in `metadata`.") + elif "id" not in workspace["metadata"]: + msg = "The `id` field is missing in `metadata`." + raise Exception(msg) return workspace diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/jupyterlab_server/workspaces_handler.py new/jupyterlab_server-2.22.1/jupyterlab_server/workspaces_handler.py --- old/jupyterlab_server-2.19.0/jupyterlab_server/workspaces_handler.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/jupyterlab_server/workspaces_handler.py 2020-02-02 01:00:00.000000000 +0100 @@ -9,13 +9,13 @@ import urllib from pathlib import Path +from jupyter_server import _tz as tz +from jupyter_server.base.handlers import APIHandler from jupyter_server.extension.handler import ExtensionHandlerJinjaMixin, ExtensionHandlerMixin +from jupyter_server.utils import url_path_join as ujoin from tornado import web from traitlets.config import LoggingConfigurable -from .server import APIHandler, tz -from .server import url_path_join as ujoin - # The JupyterLab workspace file extension. WORKSPACE_EXTENSION = ".jupyterlab-workspace" @@ -97,7 +97,8 @@ """Initialize a workspaces manager with content in ``path``.""" super() if not path: - raise ValueError("Workspaces directory is not set") + msg = "Workspaces directory is not set" + raise ValueError(msg) self.workspaces_dir = Path(path) def delete(self, space_name): @@ -106,7 +107,8 @@ workspace_path = self.workspaces_dir / (slug + WORKSPACE_EXTENSION) if not workspace_path.exists(): - raise FileNotFoundError(f"Workspace {space_name!r} ({slug!r}) not found") + msg = f"Workspace {space_name!r} ({slug!r}) not found" + raise FileNotFoundError(msg) # to delete the workspace file. workspace_path.unlink() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/pyproject.toml new/jupyterlab_server-2.22.1/pyproject.toml --- old/jupyterlab_server-2.19.0/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 @@ -66,15 +66,15 @@ "jinja2<3.2.0" ] openapi = [ - "openapi_core>=0.16.1", + "openapi_core~=0.16.1", "ruamel.yaml", ] test = [ - "codecov", + "hatch", "ipykernel", "pytest-jupyter[server]>=0.6.2", "jupyterlab_server[openapi]", - "openapi-spec-validator>=0.5.1", + "openapi-spec-validator~=0.5.1", "sphinxcontrib_spelling", "requests_mock", "pytest>=7.0", @@ -115,10 +115,10 @@ [tool.hatch.envs.lint] dependencies = [ - "black[jupyter]==22.12.0", + "black[jupyter]==23.3.0", "mdformat>0.7", "mdformat-gfm>=0.3.5", - "ruff==0.0.206" + "ruff==0.0.260" ] detatched = true [tool.hatch.envs.lint.scripts] @@ -143,12 +143,12 @@ # timeout_method = "thread" filterwarnings = [ "error", - "module:make_current is deprecated:DeprecationWarning", - "module:clear_current is deprecated:DeprecationWarning", - "module:There is no current event loop:DeprecationWarning", "ignore:ServerApp.preferred_dir config is deprecated:FutureWarning", - "ignore:Passing a schema to Validator.iter_errors:DeprecationWarning", - "module:Subclassing validator classes is not intended to be part of their public API:DeprecationWarning" + # From openapi_schema_validator + "module:write property is deprecated:DeprecationWarning", + "module:read property is deprecated:DeprecationWarning", + # From tornado.netutil.bind_sockets + "module:unclosed <socket.socket:ResourceWarning", ] [tool.coverage.report] @@ -196,8 +196,31 @@ target-version = "py37" line-length = 100 select = [ - "A", "B", "C", "E", "F", "FBT", "I", "N", "Q", "RUF", "S", "T", - "UP", "W", "YTT", + "A", + "B", + "C", + "DTZ", + "E", + "EM", + "F", + "FBT", + "I", + "ICN", + "ISC", + "N", + "PLC", + "PLE", + "PLR", + "PLW", + "Q", + "RUF", + "S", + "SIM", + "T", + "TID", + "UP", + "W", + "YTT", ] ignore = [ # Q000 Single quotes found but double quotes preferred @@ -210,15 +233,31 @@ "C408", "C416", # E501 Line too long (108 > 100 characters) "E501", +# SIM105 Use `contextlib.suppress(...)` +"SIM105", +# PLR0912 Too many branches +"PLR0912", +# PLR0913 Too many arguments to function call +"PLR0913", ] [tool.ruff.per-file-ignores] # S101 Use of `assert` detected # A001 Variable `id` is shadowing a python builtin +# PLR2004 Magic value used in comparison # F841 Local variable `list_data` is assigned to but never used -"tests/*" = ["S101", "A001", "F841"] +# EM101 Exception must not use a string literal +"tests/*" = ["S101", "A001", "F841", "EM101", "EM102", "EM103", "PLR2004"] +# T201 `print` found +"jupyterlab_server/licenses_app.py" = ["T201"] +# T201 `print` found +"jupyterlab_server/process.py" = ["T201"] # F401 `foo` imported but unused "jupyterlab_server/server.py" = ["F401"] +# T201 `print` found +"jupyterlab_server/workspaces_app.py" = ["B028", "T201"] +# Invalid module name +"tests/translations/jupyterlab-language-pack-es_CO/jupyterlab_language_pack_es_CO/__init__.py" = ["N999"] [tool.interrogate] ignore-init-module=true @@ -229,3 +268,7 @@ ignore-nested-classes=true fail-under=100 exclude = ["tests", "docs"] + +[tool.coverage.run] +relative_files = true +source = ["jupyterlab_server"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/tests/test_config.py new/jupyterlab_server-2.22.1/tests/test_config.py --- old/jupyterlab_server-2.19.0/tests/test_config.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/tests/test_config.py 2020-02-02 01:00:00.000000000 +0100 @@ -4,17 +4,27 @@ import json import os +import json5 # type:ignore +import pytest + from jupyterlab_server.config import get_page_config -def test_get_page_config(tmp_path): +@pytest.mark.parametrize( + "lib,extension", + ( + (json, "json"), + (json5, "json5"), + ), +) +def test_get_page_config(tmp_path, lib, extension): labext_path = [os.path.join(tmp_path, "ext")] settings_path = os.path.join(tmp_path, "settings") os.mkdir(settings_path) - with open(os.path.join(settings_path, "page_config.json"), "w") as fid: + with open(os.path.join(settings_path, f"page_config.{extension}"), "w") as fid: data = dict(deferredExtensions=["foo"]) - json.dump(data, fid) + lib.dump(data, fid) static_dir = os.path.join(tmp_path, "static") os.mkdir(static_dir) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/tests/test_labapp.py new/jupyterlab_server-2.22.1/tests/test_labapp.py --- old/jupyterlab_server-2.19.0/tests/test_labapp.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/tests/test_labapp.py 2020-02-02 01:00:00.000000000 +0100 @@ -52,7 +52,7 @@ # Check that the lab template is loaded html = r.body.decode() page_config = extract_page_config(html) - assert page_config['treePath'] == "" + assert not page_config['treePath'] assert page_config['preferredPath'] == "/" def ispath(p): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/tests/test_licenses_api.py new/jupyterlab_server-2.22.1/tests/test_licenses_api.py --- old/jupyterlab_server-2.19.0/tests/test_licenses_api.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/tests/test_licenses_api.py 2020-02-02 01:00:00.000000000 +0100 @@ -192,4 +192,4 @@ def test_labextension_bundle(a_fake_labextension, a_licenses_manager): ext_path, ext_name = a_fake_labextension bundle = a_licenses_manager.license_bundle(ext_path, ext_name) - assert bundle["packages"][0]["name"] == dict(FULL_ENTRY)["name"] # noqa + assert bundle["packages"][0]["name"] == dict(FULL_ENTRY)["name"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/tests/test_process.py new/jupyterlab_server-2.22.1/tests/test_process.py --- old/jupyterlab_server-2.19.0/tests/test_process.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/tests/test_process.py 2020-02-02 01:00:00.000000000 +0100 @@ -33,7 +33,7 @@ helper.wait() -async def test_process_app(): +def test_process_app(): class TestApp(ProcessApp): name = "tests" @@ -46,4 +46,4 @@ # Kandle exception on older versions of server. except Exception as e: # Convert to warning so the test will pass on min version test. - warnings.warn(str(e)) + warnings.warn(str(e)) # noqa B028 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/tests/test_settings_api.py new/jupyterlab_server-2.22.1/tests/test_settings_api.py --- old/jupyterlab_server-2.19.0/tests/test_settings_api.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/tests/test_settings_api.py 2020-02-02 01:00:00.000000000 +0100 @@ -104,6 +104,30 @@ assert {None} == set(last_modifieds + createds) +async def test_listing_ids(jp_fetch, labserverapp): + ids = [ + "@jupyterlab/apputils-extension:themes", + "@jupyterlab/apputils-extension-federated:themes", + "@jupyterlab/codemirror-extension:commands", + "@jupyterlab/codemirror-extension-federated:commands", + "@jupyterlab/shortcuts-extension:plugin", + "@jupyterlab/translation-extension:plugin", + "@jupyterlab/unicode-extension:plugin", + ] + r = await jp_fetch("lab", "api", "settings/", params={"ids_only": "true"}) + validate_request(r) + res = r.body.decode() + response = json.loads(res) + response_ids = [item["id"] for item in response["settings"]] + # Checks the IDs list is correct + assert set(response_ids) == set(ids) + + # Checks there is only the 'id' key in each item + assert all( + [(len(item.keys()) == 1 and list(item.keys())[0] == 'id') for item in response["settings"]] + ) + + async def test_patch(jp_fetch, labserverapp): id = "@jupyterlab/shortcuts-extension:plugin" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/tests/test_translation_api.py new/jupyterlab_server-2.22.1/tests/test_translation_api.py --- old/jupyterlab_server-2.19.0/tests/test_translation_api.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/tests/test_translation_api.py 2020-02-02 01:00:00.000000000 +0100 @@ -48,7 +48,6 @@ @pytest.fixture(autouse=True) def before_after_test(schemas_dir, user_settings_dir, labserverapp): - # Code that will run before any test. # Copy the schema files. @@ -144,28 +143,28 @@ def test_get_installed_language_pack_locales_passes(): data, message = _get_installed_language_pack_locales() assert "es_CO" in data - assert message == "" + assert not message def test_get_installed_package_locales(): data, message = _get_installed_package_locales() assert "jupyterlab_some_package" in data assert os.path.isdir(data["jupyterlab_some_package"]) - assert message == "" + assert not message def test_get_installed_packages_locale(): data, message = get_installed_packages_locale("es_CO") assert "jupyterlab_some_package" in data assert "" in data["jupyterlab_some_package"] - assert message == "" + assert not message def test_get_language_packs(): data, message = get_language_packs("en") assert "en" in data assert "es_CO" in data - assert message == "" + assert not message def test_get_language_pack(): @@ -174,7 +173,7 @@ assert "jupyterlab_some_package" in data assert "" in data["jupyterlab"] assert "" in data["jupyterlab_some_package"] - assert message == "" + assert not message # --- Utils diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jupyterlab_server-2.19.0/tests/test_workspaces_app.py new/jupyterlab_server-2.22.1/tests/test_workspaces_app.py --- old/jupyterlab_server-2.19.0/tests/test_workspaces_app.py 2020-02-02 01:00:00.000000000 +0100 +++ new/jupyterlab_server-2.22.1/tests/test_workspaces_app.py 2020-02-02 01:00:00.000000000 +0100 @@ -13,7 +13,6 @@ def test_workspace_apps(jp_environ, tmp_path): - sys.argv = [sys.argv[0]] data = {