prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Fix JUPYTERHUB_SINGLEUSER_APP after Notebook 7 release
  ### Bug description
  
  With `notebook 6.5.4` it was possible to specify JUPYTERHUB_SINGLEUSER_APP='notebook' to run `Jupyter Notebook` instead of `JupyterLab`.
  
  #### Expected behaviour
  
  Jupyter Notebook is run in singleuser
  
  #### Actual behaviour
  
  `jupyterhub-singleuser` fails
  
  ### How to reproduce
  
  Working image: `jupyter/base-notebook:notebook-6.5.4`
  Failing image: `jupyter/base-notebook:notebook-7.0.0`
  
  1. Run image: `docker run -it --rm jupyter/base-notebook:notebook-7.0.0 bash`
  2. Run: `JUPYTERHUB_SINGLEUSER_APP='notebook' JUPYTERHUB_SERVICE_URL="127.0.0.1" jupyterhub-singleuser`
  
  JupyterHub is not running inside the image, but I don't think that's the problem.
  
  Output with Jupyter Notebook 7:
  ```
  Traceback (most recent call last):
    File "/opt/conda/bin/jupyterhub-singleuser", line 6, in <module>
      from jupyterhub.singleuser import main
    File "/opt/conda/lib/python3.11/site-packages/jupyterhub/singleuser/__init__.py", line 67, in <module>
      from .app import SingleUserNotebookApp, main
    File "/opt/conda/lib/python3.11/site-packages/jupyterhub/singleuser/app.py", line 31, in <module>
      App = import_item(JUPYTERHUB_SINGLEUSER_APP)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/opt/conda/lib/python3.11/site-packages/traitlets/utils/importstring.py", line 30, in import_item
      module = __import__(package, fromlist=[obj])
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ModuleNotFoundError: No module named 'notebook.notebookapp'
  ```
  
  Output with Jupyter Notebook 6:
  ```
  [I 2023-07-25 20:59:48.574 SingleUserNotebookApp mixins:547] Starting jupyterhub single-user server version 4.0.1
  [I 2023-07-25 20:59:48.574 SingleUserNotebookApp mixins:561] Extending notebook.notebookapp.NotebookApp from notebook 6.5.4
  [W 2023-07-25 20:59:48.578 SingleUserNotebookApp configurable:200] Config option `open_browser` not recognized by `SingleUserNotebookApp`.  Did you mean `browser`?
  JUPYTERHUB_API_TOKEN env is required to run jupyterhub-singleuser. Did you launch it manually?
  ```
  
  ### Your personal set up
  
  
  
   - OS:
   <!-- [e.g. ubuntu 20.04, macOS 11.0] -->
   - Version(s):
   <!-- e.g. jupyterhub --version, python --version --->
  
  <details><summary>Full environment</summary>
  <!-- For reproduction, it's useful to have the full environment. For example, the output of `pip freeze` or `conda list` --->
  
  ```
  # paste output of `pip freeze` or `conda list` here
  ```
  </details>
  
  <details><summary>Configuration</summary>
  <!--
  For JupyterHub, especially include information such as what Spawner and Authenticator are being used.
  Be careful not to share any sensitive information.
  You can paste jupyterhub_config.py below.
  To exclude lots of comments and empty lines from auto-generated jupyterhub_config.py, you can do:
      grep -v '\(^#\|^[[:space:]]*$\)' jupyterhub_config.py
  -->
  
  ```python
  # jupyterhub_config.py
  ```
  </details>
  
  <details><summary>Logs</summary>
  <!--
  Errors are often logged by jupytehub. How you get logs depends on your deployment.
  With kubernetes it might be:
  
      kubectl get pod # hub pod name starts with hub...
      kubectl logs hub-...
      # or for a single-user server
      kubectl logs jupyter-username
  
  Or the-littlest-jupyterhub:
  
      journalctl -u jupyterhub
      # or for a single-user server
      journalctl -u jupyter-username
  -->
  
  ```
  # paste relevant logs here, if any
  ```
  </details>
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `jupyterhub/singleuser/app.py`
  Content:
  ```
  1 """Make a single-user app based on the environment:
  2 
  3 - $JUPYTERHUB_SINGLEUSER_APP, the base Application class, to be wrapped in JupyterHub authentication.
  4   default: jupyter_server.serverapp.ServerApp
  5 
  6 .. versionchanged:: 2.0
  7 
  8     Default app changed to launch `jupyter labhub`.
  9     Use JUPYTERHUB_SINGLEUSER_APP=notebook.notebookapp.NotebookApp for the legacy 'classic' notebook server.
  10 """
  11 import os
  12 
  13 from traitlets import import_item
  14 
  15 from .mixins import make_singleuser_app
  16 
  17 JUPYTERHUB_SINGLEUSER_APP = os.environ.get("JUPYTERHUB_SINGLEUSER_APP", "")
  18 
  19 # allow shortcut references
  20 _app_shortcuts = {
  21     "notebook": "notebook.notebookapp.NotebookApp",
  22     "jupyter-server": "jupyter_server.serverapp.ServerApp",
  23     "extension": "jupyter_server.serverapp.ServerApp",
  24 }
  25 
  26 JUPYTERHUB_SINGLEUSER_APP = _app_shortcuts.get(
  27     JUPYTERHUB_SINGLEUSER_APP.replace("_", "-"), JUPYTERHUB_SINGLEUSER_APP
  28 )
  29 
  30 if JUPYTERHUB_SINGLEUSER_APP:
  31     App = import_item(JUPYTERHUB_SINGLEUSER_APP)
  32 else:
  33     App = None
  34     _import_error = None
  35     for JUPYTERHUB_SINGLEUSER_APP in (
  36         "jupyter_server.serverapp.ServerApp",
  37         "notebook.notebookapp.NotebookApp",
  38     ):
  39         try:
  40             App = import_item(JUPYTERHUB_SINGLEUSER_APP)
  41         except ImportError as e:
  42             if _import_error is None:
  43                 _import_error = e
  44             continue
  45         else:
  46             break
  47     if App is None:
  48         raise _import_error
  49 
  50 
  51 SingleUserNotebookApp = make_singleuser_app(App)
  52 
  53 
  54 def main():
  55     """Launch a jupyterhub single-user server"""
  56     if not os.environ.get("JUPYTERHUB_SINGLEUSER_APP"):
  57         # app not specified, launch jupyter-labhub by default,
  58         # if jupyterlab is recent enough (3.1).
  59         # This is a minimally extended ServerApp that does:
  60         # 1. ensure lab extension is enabled, and
  61         # 2. set default URL to `/lab`
  62         import re
  63 
  64         _version_pat = re.compile(r"(\d+)\.(\d+)")
  65         try:
  66             import jupyterlab
  67             from jupyterlab.labhubapp import SingleUserLabApp
  68 
  69             m = _version_pat.match(jupyterlab.__version__)
  70         except Exception:
  71             m = None
  72 
  73         if m is not None:
  74             version_tuple = tuple(int(v) for v in m.groups())
  75             if version_tuple >= (3, 1):
  76                 return SingleUserLabApp.launch_instance()
  77 
  78     return SingleUserNotebookApp.launch_instance()
  79
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/jupyterhub/singleuser/app.py b/jupyterhub/singleuser/app.py
  --- a/jupyterhub/singleuser/app.py
  +++ b/jupyterhub/singleuser/app.py
  @@ -6,7 +6,7 @@
   .. versionchanged:: 2.0
   
       Default app changed to launch `jupyter labhub`.
  -    Use JUPYTERHUB_SINGLEUSER_APP=notebook.notebookapp.NotebookApp for the legacy 'classic' notebook server.
  +    Use JUPYTERHUB_SINGLEUSER_APP='notebook' for the legacy 'classic' notebook server (requires notebook<7).
   """
   import os
   
  @@ -27,7 +27,25 @@
       JUPYTERHUB_SINGLEUSER_APP.replace("_", "-"), JUPYTERHUB_SINGLEUSER_APP
   )
   
  +
   if JUPYTERHUB_SINGLEUSER_APP:
  +    if JUPYTERHUB_SINGLEUSER_APP in {"notebook", _app_shortcuts["notebook"]}:
  +        # better error for notebook v7, which uses jupyter-server
  +        # when the legacy notebook server is requested
  +        try:
  +            from notebook import __version__
  +        except ImportError:
  +            # will raise later
  +            pass
  +        else:
  +            # check if this failed because of notebook v7
  +            _notebook_major_version = int(__version__.split(".", 1)[0])
  +            if _notebook_major_version >= 7:
  +                raise ImportError(
  +                    f"JUPYTERHUB_SINGLEUSER_APP={JUPYTERHUB_SINGLEUSER_APP} is not valid with notebook>=7 (have notebook=={__version__}).\n"
  +                    f"Leave $JUPYTERHUB_SINGLEUSER_APP unspecified (or use the default JUPYTERHUB_SINGLEUSER_APP=jupyter-server), "
  +                    'and set `c.Spawner.default_url = "/tree"` to make notebook v7 the default UI.'
  +                )
       App = import_item(JUPYTERHUB_SINGLEUSER_APP)
   else:
       App = None
  
verification_info: {"golden_diff": "diff --git a/jupyterhub/singleuser/app.py b/jupyterhub/singleuser/app.py\n--- a/jupyterhub/singleuser/app.py\n+++ b/jupyterhub/singleuser/app.py\n@@ -6,7 +6,7 @@\n .. versionchanged:: 2.0\n \n     Default app changed to launch `jupyter labhub`.\n-    Use JUPYTERHUB_SINGLEUSER_APP=notebook.notebookapp.NotebookApp for the legacy 'classic' notebook server.\n+    Use JUPYTERHUB_SINGLEUSER_APP='notebook' for the legacy 'classic' notebook server (requires notebook<7).\n \"\"\"\n import os\n \n@@ -27,7 +27,25 @@\n     JUPYTERHUB_SINGLEUSER_APP.replace(\"_\", \"-\"), JUPYTERHUB_SINGLEUSER_APP\n )\n \n+\n if JUPYTERHUB_SINGLEUSER_APP:\n+    if JUPYTERHUB_SINGLEUSER_APP in {\"notebook\", _app_shortcuts[\"notebook\"]}:\n+        # better error for notebook v7, which uses jupyter-server\n+        # when the legacy notebook server is requested\n+        try:\n+            from notebook import __version__\n+        except ImportError:\n+            # will raise later\n+            pass\n+        else:\n+            # check if this failed because of notebook v7\n+            _notebook_major_version = int(__version__.split(\".\", 1)[0])\n+            if _notebook_major_version >= 7:\n+                raise ImportError(\n+                    f\"JUPYTERHUB_SINGLEUSER_APP={JUPYTERHUB_SINGLEUSER_APP} is not valid with notebook>=7 (have notebook=={__version__}).\\n\"\n+                    f\"Leave $JUPYTERHUB_SINGLEUSER_APP unspecified (or use the default JUPYTERHUB_SINGLEUSER_APP=jupyter-server), \"\n+                    'and set `c.Spawner.default_url = \"/tree\"` to make notebook v7 the default UI.'\n+                )\n     App = import_item(JUPYTERHUB_SINGLEUSER_APP)\n else:\n     App = None\n", "issue": "Fix JUPYTERHUB_SINGLEUSER_APP after Notebook 7 release\n### Bug description\r\n\r\nWith `notebook 6.5.4` it was possible to specify JUPYTERHUB_SINGLEUSER_APP='notebook' to run `Jupyter Notebook` instead of `JupyterLab`.\r\n\r\n#### Expected behaviour\r\n\r\nJupyter Notebook is run in singleuser\r\n\r\n#### Actual behaviour\r\n\r\n`jupyterhub-singleuser` fails\r\n\r\n### How to reproduce\r\n\r\nWorking image: `jupyter/base-notebook:notebook-6.5.4`\r\nFailing image: `jupyter/base-notebook:notebook-7.0.0`\r\n\r\n1. Run image: `docker run -it --rm jupyter/base-notebook:notebook-7.0.0 bash`\r\n2. Run: `JUPYTERHUB_SINGLEUSER_APP='notebook' JUPYTERHUB_SERVICE_URL=\"127.0.0.1\" jupyterhub-singleuser`\r\n\r\nJupyterHub is not running inside the image, but I don't think that's the problem.\r\n\r\nOutput with Jupyter Notebook 7:\r\n```\r\nTraceback (most recent call last):\r\n  File \"/opt/conda/bin/jupyterhub-singleuser\", line 6, in <module>\r\n    from jupyterhub.singleuser import main\r\n  File \"/opt/conda/lib/python3.11/site-packages/jupyterhub/singleuser/__init__.py\", line 67, in <module>\r\n    from .app import SingleUserNotebookApp, main\r\n  File \"/opt/conda/lib/python3.11/site-packages/jupyterhub/singleuser/app.py\", line 31, in <module>\r\n    App = import_item(JUPYTERHUB_SINGLEUSER_APP)\r\n          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n  File \"/opt/conda/lib/python3.11/site-packages/traitlets/utils/importstring.py\", line 30, in import_item\r\n    module = __import__(package, fromlist=[obj])\r\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\nModuleNotFoundError: No module named 'notebook.notebookapp'\r\n```\r\n\r\nOutput with Jupyter Notebook 6:\r\n```\r\n[I 2023-07-25 20:59:48.574 SingleUserNotebookApp mixins:547] Starting jupyterhub single-user server version 4.0.1\r\n[I 2023-07-25 20:59:48.574 SingleUserNotebookApp mixins:561] Extending notebook.notebookapp.NotebookApp from notebook 6.5.4\r\n[W 2023-07-25 20:59:48.578 SingleUserNotebookApp configurable:200] Config option `open_browser` not recognized by `SingleUserNotebookApp`.  Did you mean `browser`?\r\nJUPYTERHUB_API_TOKEN env is required to run jupyterhub-singleuser. Did you launch it manually?\r\n```\r\n\r\n### Your personal set up\r\n\r\n\r\n\r\n - OS:\r\n <!-- [e.g. ubuntu 20.04, macOS 11.0] -->\r\n - Version(s):\r\n <!-- e.g. jupyterhub --version, python --version --->\r\n\r\n<details><summary>Full environment</summary>\r\n<!-- For reproduction, it's useful to have the full environment. For example, the output of `pip freeze` or `conda list` --->\r\n\r\n```\r\n# paste output of `pip freeze` or `conda list` here\r\n```\r\n</details>\r\n\r\n<details><summary>Configuration</summary>\r\n<!--\r\nFor JupyterHub, especially include information such as what Spawner and Authenticator are being used.\r\nBe careful not to share any sensitive information.\r\nYou can paste jupyterhub_config.py below.\r\nTo exclude lots of comments and empty lines from auto-generated jupyterhub_config.py, you can do:\r\n    grep -v '\\(^#\\|^[[:space:]]*$\\)' jupyterhub_config.py\r\n-->\r\n\r\n```python\r\n# jupyterhub_config.py\r\n```\r\n</details>\r\n\r\n<details><summary>Logs</summary>\r\n<!--\r\nErrors are often logged by jupytehub. How you get logs depends on your deployment.\r\nWith kubernetes it might be:\r\n\r\n    kubectl get pod # hub pod name starts with hub...\r\n    kubectl logs hub-...\r\n    # or for a single-user server\r\n    kubectl logs jupyter-username\r\n\r\nOr the-littlest-jupyterhub:\r\n\r\n    journalctl -u jupyterhub\r\n    # or for a single-user server\r\n    journalctl -u jupyter-username\r\n-->\r\n\r\n```\r\n# paste relevant logs here, if any\r\n```\r\n</details>\r\n\n", "before_files": [{"content": "\"\"\"Make a single-user app based on the environment:\n\n- $JUPYTERHUB_SINGLEUSER_APP, the base Application class, to be wrapped in JupyterHub authentication.\n  default: jupyter_server.serverapp.ServerApp\n\n.. versionchanged:: 2.0\n\n    Default app changed to launch `jupyter labhub`.\n    Use JUPYTERHUB_SINGLEUSER_APP=notebook.notebookapp.NotebookApp for the legacy 'classic' notebook server.\n\"\"\"\nimport os\n\nfrom traitlets import import_item\n\nfrom .mixins import make_singleuser_app\n\nJUPYTERHUB_SINGLEUSER_APP = os.environ.get(\"JUPYTERHUB_SINGLEUSER_APP\", \"\")\n\n# allow shortcut references\n_app_shortcuts = {\n    \"notebook\": \"notebook.notebookapp.NotebookApp\",\n    \"jupyter-server\": \"jupyter_server.serverapp.ServerApp\",\n    \"extension\": \"jupyter_server.serverapp.ServerApp\",\n}\n\nJUPYTERHUB_SINGLEUSER_APP = _app_shortcuts.get(\n    JUPYTERHUB_SINGLEUSER_APP.replace(\"_\", \"-\"), JUPYTERHUB_SINGLEUSER_APP\n)\n\nif JUPYTERHUB_SINGLEUSER_APP:\n    App = import_item(JUPYTERHUB_SINGLEUSER_APP)\nelse:\n    App = None\n    _import_error = None\n    for JUPYTERHUB_SINGLEUSER_APP in (\n        \"jupyter_server.serverapp.ServerApp\",\n        \"notebook.notebookapp.NotebookApp\",\n    ):\n        try:\n            App = import_item(JUPYTERHUB_SINGLEUSER_APP)\n        except ImportError as e:\n            if _import_error is None:\n                _import_error = e\n            continue\n        else:\n            break\n    if App is None:\n        raise _import_error\n\n\nSingleUserNotebookApp = make_singleuser_app(App)\n\n\ndef main():\n    \"\"\"Launch a jupyterhub single-user server\"\"\"\n    if not os.environ.get(\"JUPYTERHUB_SINGLEUSER_APP\"):\n        # app not specified, launch jupyter-labhub by default,\n        # if jupyterlab is recent enough (3.1).\n        # This is a minimally extended ServerApp that does:\n        # 1. ensure lab extension is enabled, and\n        # 2. set default URL to `/lab`\n        import re\n\n        _version_pat = re.compile(r\"(\\d+)\\.(\\d+)\")\n        try:\n            import jupyterlab\n            from jupyterlab.labhubapp import SingleUserLabApp\n\n            m = _version_pat.match(jupyterlab.__version__)\n        except Exception:\n            m = None\n\n        if m is not None:\n            version_tuple = tuple(int(v) for v in m.groups())\n            if version_tuple >= (3, 1):\n                return SingleUserLabApp.launch_instance()\n\n    return SingleUserNotebookApp.launch_instance()\n", "path": "jupyterhub/singleuser/app.py"}], "after_files": [{"content": "\"\"\"Make a single-user app based on the environment:\n\n- $JUPYTERHUB_SINGLEUSER_APP, the base Application class, to be wrapped in JupyterHub authentication.\n  default: jupyter_server.serverapp.ServerApp\n\n.. versionchanged:: 2.0\n\n    Default app changed to launch `jupyter labhub`.\n    Use JUPYTERHUB_SINGLEUSER_APP='notebook' for the legacy 'classic' notebook server (requires notebook<7).\n\"\"\"\nimport os\n\nfrom traitlets import import_item\n\nfrom .mixins import make_singleuser_app\n\nJUPYTERHUB_SINGLEUSER_APP = os.environ.get(\"JUPYTERHUB_SINGLEUSER_APP\", \"\")\n\n# allow shortcut references\n_app_shortcuts = {\n    \"notebook\": \"notebook.notebookapp.NotebookApp\",\n    \"jupyter-server\": \"jupyter_server.serverapp.ServerApp\",\n    \"extension\": \"jupyter_server.serverapp.ServerApp\",\n}\n\nJUPYTERHUB_SINGLEUSER_APP = _app_shortcuts.get(\n    JUPYTERHUB_SINGLEUSER_APP.replace(\"_\", \"-\"), JUPYTERHUB_SINGLEUSER_APP\n)\n\n\nif JUPYTERHUB_SINGLEUSER_APP:\n    if JUPYTERHUB_SINGLEUSER_APP in {\"notebook\", _app_shortcuts[\"notebook\"]}:\n        # better error for notebook v7, which uses jupyter-server\n        # when the legacy notebook server is requested\n        try:\n            from notebook import __version__\n        except ImportError:\n            # will raise later\n            pass\n        else:\n            # check if this failed because of notebook v7\n            _notebook_major_version = int(__version__.split(\".\", 1)[0])\n            if _notebook_major_version >= 7:\n                raise ImportError(\n                    f\"JUPYTERHUB_SINGLEUSER_APP={JUPYTERHUB_SINGLEUSER_APP} is not valid with notebook>=7 (have notebook=={__version__}).\\n\"\n                    f\"Leave $JUPYTERHUB_SINGLEUSER_APP unspecified (or use the default JUPYTERHUB_SINGLEUSER_APP=jupyter-server), \"\n                    'and set `c.Spawner.default_url = \"/tree\"` to make notebook v7 the default UI.'\n                )\n    App = import_item(JUPYTERHUB_SINGLEUSER_APP)\nelse:\n    App = None\n    _import_error = None\n    for JUPYTERHUB_SINGLEUSER_APP in (\n        \"jupyter_server.serverapp.ServerApp\",\n        \"notebook.notebookapp.NotebookApp\",\n    ):\n        try:\n            App = import_item(JUPYTERHUB_SINGLEUSER_APP)\n        except ImportError as e:\n            if _import_error is None:\n                _import_error = e\n            continue\n        else:\n            break\n    if App is None:\n        raise _import_error\n\n\nSingleUserNotebookApp = make_singleuser_app(App)\n\n\ndef main():\n    \"\"\"Launch a jupyterhub single-user server\"\"\"\n    if not os.environ.get(\"JUPYTERHUB_SINGLEUSER_APP\"):\n        # app not specified, launch jupyter-labhub by default,\n        # if jupyterlab is recent enough (3.1).\n        # This is a minimally extended ServerApp that does:\n        # 1. ensure lab extension is enabled, and\n        # 2. set default URL to `/lab`\n        import re\n\n        _version_pat = re.compile(r\"(\\d+)\\.(\\d+)\")\n        try:\n            import jupyterlab\n            from jupyterlab.labhubapp import SingleUserLabApp\n\n            m = _version_pat.match(jupyterlab.__version__)\n        except Exception:\n            m = None\n\n        if m is not None:\n            version_tuple = tuple(int(v) for v in m.groups())\n            if version_tuple >= (3, 1):\n                return SingleUserLabApp.launch_instance()\n\n    return SingleUserNotebookApp.launch_instance()\n", "path": "jupyterhub/singleuser/app.py"}]}