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
 
-[![codecov](https://codecov.io/gh/jupyterlab/jupyterlab_server/branch/main/graph/badge.svg?token=4fjcFj91Le)](https://codecov.io/gh/jupyterlab/jupyterlab_server)
 [![Build 
Status](https://github.com/jupyterlab/jupyterlab_server/workflows/Tests/badge.svg?branch=master)](https://github.com/jupyterlab/jupyterlab_server/actions?query=branch%3Amaster+workflow%3A%22Tests%22)
 [![Documentation 
Status](https://readthedocs.org/projects/jupyterlab_server/badge/?version=stable)](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
 
-[![codecov](https://codecov.io/gh/jupyterlab/jupyterlab_server/branch/main/graph/badge.svg?token=4fjcFj91Le)](https://codecov.io/gh/jupyterlab/jupyterlab_server)
 [![Build 
Status](https://github.com/jupyterlab/jupyterlab_server/workflows/Tests/badge.svg?branch=master)](https://github.com/jupyterlab/jupyterlab_server/actions?query=branch%3Amaster+workflow%3A%22Tests%22)
 [![Documentation 
Status](https://readthedocs.org/projects/jupyterlab_server/badge/?version=stable)](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 = {

Reply via email to