prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Remove or edit unreachable code block
  @minrk It looks like `_check_user_model` has a few code lines that don't seem to be reachable. Should we remove the lines after the return statement? https://github.com/jupyterhub/jupyterhub/blob/master/jupyterhub/apihandlers/base.py#L144
  
  
  --- 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/apihandlers/base.py`
  Content:
  ```
  1 """Base API handlers"""
  2 # Copyright (c) Jupyter Development Team.
  3 # Distributed under the terms of the Modified BSD License.
  4 
  5 import json
  6 
  7 from http.client import responses
  8 
  9 from tornado import web
  10 
  11 from ..handlers import BaseHandler
  12 from ..utils import url_path_join
  13 
  14 class APIHandler(BaseHandler):
  15 
  16     def check_referer(self):
  17         """Check Origin for cross-site API requests.
  18         
  19         Copied from WebSocket with changes:
  20         
  21         - allow unspecified host/referer (e.g. scripts)
  22         """
  23         host = self.request.headers.get("Host")
  24         referer = self.request.headers.get("Referer")
  25 
  26         # If no header is provided, assume it comes from a script/curl.
  27         # We are only concerned with cross-site browser stuff here.
  28         if not host:
  29             self.log.warning("Blocking API request with no host")
  30             return False
  31         if not referer:
  32             self.log.warning("Blocking API request with no referer")
  33             return False
  34         
  35         host_path = url_path_join(host, self.hub.server.base_url)
  36         referer_path = referer.split('://', 1)[-1]
  37         if not (referer_path + '/').startswith(host_path):
  38             self.log.warning("Blocking Cross Origin API request.  Referer: %s, Host: %s",
  39                 referer, host_path)
  40             return False
  41         return True
  42     
  43     def get_current_user_cookie(self):
  44         """Override get_user_cookie to check Referer header"""
  45         cookie_user = super().get_current_user_cookie()
  46         # check referer only if there is a cookie user,
  47         # avoiding misleading "Blocking Cross Origin" messages
  48         # when there's no cookie set anyway.
  49         if cookie_user and not self.check_referer():
  50             return None
  51         return cookie_user
  52 
  53     def get_json_body(self):
  54         """Return the body of the request as JSON data."""
  55         if not self.request.body:
  56             return None
  57         body = self.request.body.strip().decode('utf-8')
  58         try:
  59             model = json.loads(body)
  60         except Exception:
  61             self.log.debug("Bad JSON: %r", body)
  62             self.log.error("Couldn't parse JSON", exc_info=True)
  63             raise web.HTTPError(400, 'Invalid JSON in body of request')
  64         return model
  65     
  66     def write_error(self, status_code, **kwargs):
  67         """Write JSON errors instead of HTML"""
  68         exc_info = kwargs.get('exc_info')
  69         message = ''
  70         status_message = responses.get(status_code, 'Unknown Error')
  71         if exc_info:
  72             exception = exc_info[1]
  73             # get the custom message, if defined
  74             try:
  75                 message = exception.log_message % exception.args
  76             except Exception:
  77                 pass
  78 
  79             # construct the custom reason, if defined
  80             reason = getattr(exception, 'reason', '')
  81             if reason:
  82                 status_message = reason
  83         self.set_header('Content-Type', 'application/json')
  84         self.write(json.dumps({
  85             'status': status_code,
  86             'message': message or status_message,
  87         }))
  88 
  89     def user_model(self, user):
  90         """Get the JSON model for a User object"""
  91         model = {
  92             'name': user.name,
  93             'admin': user.admin,
  94             'groups': [ g.name for g in user.groups ],
  95             'server': user.url if user.running else None,
  96             'pending': None,
  97             'last_activity': user.last_activity.isoformat(),
  98         }
  99         if user.spawn_pending:
  100             model['pending'] = 'spawn'
  101         elif user.stop_pending:
  102             model['pending'] = 'stop'
  103         return model
  104 
  105     def group_model(self, group):
  106         """Get the JSON model for a Group object"""
  107         return {
  108             'name': group.name,
  109             'users': [ u.name for u in group.users ]
  110         }
  111 
  112     _user_model_types = {
  113         'name': str,
  114         'admin': bool,
  115         'groups': list,
  116     }
  117 
  118     _group_model_types = {
  119         'name': str,
  120         'users': list,
  121     }
  122 
  123     def _check_model(self, model, model_types, name):
  124         """Check a model provided by a REST API request
  125         
  126         Args:
  127             model (dict): user-provided model
  128             model_types (dict): dict of key:type used to validate types and keys
  129             name (str): name of the model, used in error messages
  130         """
  131         if not isinstance(model, dict):
  132             raise web.HTTPError(400, "Invalid JSON data: %r" % model)
  133         if not set(model).issubset(set(model_types)):
  134             raise web.HTTPError(400, "Invalid JSON keys: %r" % model)
  135         for key, value in model.items():
  136             if not isinstance(value, model_types[key]):
  137                 raise web.HTTPError(400, "%s.%s must be %s, not: %r" % (
  138                     name, key, model_types[key], type(value)
  139                 ))
  140 
  141     def _check_user_model(self, model):
  142         """Check a request-provided user model from a REST API"""
  143         return self._check_model(model, self._user_model_types, 'user')
  144         for groupname in model.get('groups', []):
  145             if not isinstance(groupname, str):
  146                 raise web.HTTPError(400, "group names must be str, not %r" % type(groupname))
  147 
  148     def _check_group_model(self, model):
  149         """Check a request-provided user model from a REST API"""
  150         self._check_model(model, self._group_model_types, 'group')
  151         for username in model.get('users', []):
  152             if not isinstance(username, str):
  153                 raise web.HTTPError(400, "usernames must be str, not %r" % type(groupname))
  154 
  155     def options(self, *args, **kwargs):
  156         self.set_header('Access-Control-Allow-Headers', 'accept, content-type')
  157         self.finish()
  158
  ```
  --- 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/apihandlers/base.py b/jupyterhub/apihandlers/base.py
  --- a/jupyterhub/apihandlers/base.py
  +++ b/jupyterhub/apihandlers/base.py
  @@ -140,19 +140,18 @@
   
       def _check_user_model(self, model):
           """Check a request-provided user model from a REST API"""
  -        return self._check_model(model, self._user_model_types, 'user')
  -        for groupname in model.get('groups', []):
  -            if not isinstance(groupname, str):
  -                raise web.HTTPError(400, "group names must be str, not %r" % type(groupname))
  +        self._check_model(model, self._user_model_types, 'user')
  +        for username in model.get('users', []):
  +            if not isinstance(username, str):
  +                raise web.HTTPError(400, ("usernames must be str, not %r", type(username)))
   
       def _check_group_model(self, model):
  -        """Check a request-provided user model from a REST API"""
  +        """Check a request-provided group model from a REST API"""
           self._check_model(model, self._group_model_types, 'group')
  -        for username in model.get('users', []):
  -            if not isinstance(username, str):
  -                raise web.HTTPError(400, "usernames must be str, not %r" % type(groupname))
  +        for groupname in model.get('groups', []):
  +            if not isinstance(groupname, str):
  +                raise web.HTTPError(400, ("group names must be str, not %r", type(groupname)))
   
       def options(self, *args, **kwargs):
           self.set_header('Access-Control-Allow-Headers', 'accept, content-type')
           self.finish()
  -    
  \ No newline at end of file
  
verification_info: {"golden_diff": "diff --git a/jupyterhub/apihandlers/base.py b/jupyterhub/apihandlers/base.py\n--- a/jupyterhub/apihandlers/base.py\n+++ b/jupyterhub/apihandlers/base.py\n@@ -140,19 +140,18 @@\n \n     def _check_user_model(self, model):\n         \"\"\"Check a request-provided user model from a REST API\"\"\"\n-        return self._check_model(model, self._user_model_types, 'user')\n-        for groupname in model.get('groups', []):\n-            if not isinstance(groupname, str):\n-                raise web.HTTPError(400, \"group names must be str, not %r\" % type(groupname))\n+        self._check_model(model, self._user_model_types, 'user')\n+        for username in model.get('users', []):\n+            if not isinstance(username, str):\n+                raise web.HTTPError(400, (\"usernames must be str, not %r\", type(username)))\n \n     def _check_group_model(self, model):\n-        \"\"\"Check a request-provided user model from a REST API\"\"\"\n+        \"\"\"Check a request-provided group model from a REST API\"\"\"\n         self._check_model(model, self._group_model_types, 'group')\n-        for username in model.get('users', []):\n-            if not isinstance(username, str):\n-                raise web.HTTPError(400, \"usernames must be str, not %r\" % type(groupname))\n+        for groupname in model.get('groups', []):\n+            if not isinstance(groupname, str):\n+                raise web.HTTPError(400, (\"group names must be str, not %r\", type(groupname)))\n \n     def options(self, *args, **kwargs):\n         self.set_header('Access-Control-Allow-Headers', 'accept, content-type')\n         self.finish()\n-    \n\\ No newline at end of file\n", "issue": "Remove or edit unreachable code block\n@minrk It looks like `_check_user_model` has a few code lines that don't seem to be reachable. Should we remove the lines after the return statement? https://github.com/jupyterhub/jupyterhub/blob/master/jupyterhub/apihandlers/base.py#L144\n\n", "before_files": [{"content": "\"\"\"Base API handlers\"\"\"\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport json\n\nfrom http.client import responses\n\nfrom tornado import web\n\nfrom ..handlers import BaseHandler\nfrom ..utils import url_path_join\n\nclass APIHandler(BaseHandler):\n\n    def check_referer(self):\n        \"\"\"Check Origin for cross-site API requests.\n        \n        Copied from WebSocket with changes:\n        \n        - allow unspecified host/referer (e.g. scripts)\n        \"\"\"\n        host = self.request.headers.get(\"Host\")\n        referer = self.request.headers.get(\"Referer\")\n\n        # If no header is provided, assume it comes from a script/curl.\n        # We are only concerned with cross-site browser stuff here.\n        if not host:\n            self.log.warning(\"Blocking API request with no host\")\n            return False\n        if not referer:\n            self.log.warning(\"Blocking API request with no referer\")\n            return False\n        \n        host_path = url_path_join(host, self.hub.server.base_url)\n        referer_path = referer.split('://', 1)[-1]\n        if not (referer_path + '/').startswith(host_path):\n            self.log.warning(\"Blocking Cross Origin API request.  Referer: %s, Host: %s\",\n                referer, host_path)\n            return False\n        return True\n    \n    def get_current_user_cookie(self):\n        \"\"\"Override get_user_cookie to check Referer header\"\"\"\n        cookie_user = super().get_current_user_cookie()\n        # check referer only if there is a cookie user,\n        # avoiding misleading \"Blocking Cross Origin\" messages\n        # when there's no cookie set anyway.\n        if cookie_user and not self.check_referer():\n            return None\n        return cookie_user\n\n    def get_json_body(self):\n        \"\"\"Return the body of the request as JSON data.\"\"\"\n        if not self.request.body:\n            return None\n        body = self.request.body.strip().decode('utf-8')\n        try:\n            model = json.loads(body)\n        except Exception:\n            self.log.debug(\"Bad JSON: %r\", body)\n            self.log.error(\"Couldn't parse JSON\", exc_info=True)\n            raise web.HTTPError(400, 'Invalid JSON in body of request')\n        return model\n    \n    def write_error(self, status_code, **kwargs):\n        \"\"\"Write JSON errors instead of HTML\"\"\"\n        exc_info = kwargs.get('exc_info')\n        message = ''\n        status_message = responses.get(status_code, 'Unknown Error')\n        if exc_info:\n            exception = exc_info[1]\n            # get the custom message, if defined\n            try:\n                message = exception.log_message % exception.args\n            except Exception:\n                pass\n\n            # construct the custom reason, if defined\n            reason = getattr(exception, 'reason', '')\n            if reason:\n                status_message = reason\n        self.set_header('Content-Type', 'application/json')\n        self.write(json.dumps({\n            'status': status_code,\n            'message': message or status_message,\n        }))\n\n    def user_model(self, user):\n        \"\"\"Get the JSON model for a User object\"\"\"\n        model = {\n            'name': user.name,\n            'admin': user.admin,\n            'groups': [ g.name for g in user.groups ],\n            'server': user.url if user.running else None,\n            'pending': None,\n            'last_activity': user.last_activity.isoformat(),\n        }\n        if user.spawn_pending:\n            model['pending'] = 'spawn'\n        elif user.stop_pending:\n            model['pending'] = 'stop'\n        return model\n\n    def group_model(self, group):\n        \"\"\"Get the JSON model for a Group object\"\"\"\n        return {\n            'name': group.name,\n            'users': [ u.name for u in group.users ]\n        }\n\n    _user_model_types = {\n        'name': str,\n        'admin': bool,\n        'groups': list,\n    }\n\n    _group_model_types = {\n        'name': str,\n        'users': list,\n    }\n\n    def _check_model(self, model, model_types, name):\n        \"\"\"Check a model provided by a REST API request\n        \n        Args:\n            model (dict): user-provided model\n            model_types (dict): dict of key:type used to validate types and keys\n            name (str): name of the model, used in error messages\n        \"\"\"\n        if not isinstance(model, dict):\n            raise web.HTTPError(400, \"Invalid JSON data: %r\" % model)\n        if not set(model).issubset(set(model_types)):\n            raise web.HTTPError(400, \"Invalid JSON keys: %r\" % model)\n        for key, value in model.items():\n            if not isinstance(value, model_types[key]):\n                raise web.HTTPError(400, \"%s.%s must be %s, not: %r\" % (\n                    name, key, model_types[key], type(value)\n                ))\n\n    def _check_user_model(self, model):\n        \"\"\"Check a request-provided user model from a REST API\"\"\"\n        return self._check_model(model, self._user_model_types, 'user')\n        for groupname in model.get('groups', []):\n            if not isinstance(groupname, str):\n                raise web.HTTPError(400, \"group names must be str, not %r\" % type(groupname))\n\n    def _check_group_model(self, model):\n        \"\"\"Check a request-provided user model from a REST API\"\"\"\n        self._check_model(model, self._group_model_types, 'group')\n        for username in model.get('users', []):\n            if not isinstance(username, str):\n                raise web.HTTPError(400, \"usernames must be str, not %r\" % type(groupname))\n\n    def options(self, *args, **kwargs):\n        self.set_header('Access-Control-Allow-Headers', 'accept, content-type')\n        self.finish()\n    ", "path": "jupyterhub/apihandlers/base.py"}], "after_files": [{"content": "\"\"\"Base API handlers\"\"\"\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport json\n\nfrom http.client import responses\n\nfrom tornado import web\n\nfrom ..handlers import BaseHandler\nfrom ..utils import url_path_join\n\nclass APIHandler(BaseHandler):\n\n    def check_referer(self):\n        \"\"\"Check Origin for cross-site API requests.\n        \n        Copied from WebSocket with changes:\n        \n        - allow unspecified host/referer (e.g. scripts)\n        \"\"\"\n        host = self.request.headers.get(\"Host\")\n        referer = self.request.headers.get(\"Referer\")\n\n        # If no header is provided, assume it comes from a script/curl.\n        # We are only concerned with cross-site browser stuff here.\n        if not host:\n            self.log.warning(\"Blocking API request with no host\")\n            return False\n        if not referer:\n            self.log.warning(\"Blocking API request with no referer\")\n            return False\n        \n        host_path = url_path_join(host, self.hub.server.base_url)\n        referer_path = referer.split('://', 1)[-1]\n        if not (referer_path + '/').startswith(host_path):\n            self.log.warning(\"Blocking Cross Origin API request.  Referer: %s, Host: %s\",\n                referer, host_path)\n            return False\n        return True\n    \n    def get_current_user_cookie(self):\n        \"\"\"Override get_user_cookie to check Referer header\"\"\"\n        cookie_user = super().get_current_user_cookie()\n        # check referer only if there is a cookie user,\n        # avoiding misleading \"Blocking Cross Origin\" messages\n        # when there's no cookie set anyway.\n        if cookie_user and not self.check_referer():\n            return None\n        return cookie_user\n\n    def get_json_body(self):\n        \"\"\"Return the body of the request as JSON data.\"\"\"\n        if not self.request.body:\n            return None\n        body = self.request.body.strip().decode('utf-8')\n        try:\n            model = json.loads(body)\n        except Exception:\n            self.log.debug(\"Bad JSON: %r\", body)\n            self.log.error(\"Couldn't parse JSON\", exc_info=True)\n            raise web.HTTPError(400, 'Invalid JSON in body of request')\n        return model\n    \n    def write_error(self, status_code, **kwargs):\n        \"\"\"Write JSON errors instead of HTML\"\"\"\n        exc_info = kwargs.get('exc_info')\n        message = ''\n        status_message = responses.get(status_code, 'Unknown Error')\n        if exc_info:\n            exception = exc_info[1]\n            # get the custom message, if defined\n            try:\n                message = exception.log_message % exception.args\n            except Exception:\n                pass\n\n            # construct the custom reason, if defined\n            reason = getattr(exception, 'reason', '')\n            if reason:\n                status_message = reason\n        self.set_header('Content-Type', 'application/json')\n        self.write(json.dumps({\n            'status': status_code,\n            'message': message or status_message,\n        }))\n\n    def user_model(self, user):\n        \"\"\"Get the JSON model for a User object\"\"\"\n        model = {\n            'name': user.name,\n            'admin': user.admin,\n            'groups': [ g.name for g in user.groups ],\n            'server': user.url if user.running else None,\n            'pending': None,\n            'last_activity': user.last_activity.isoformat(),\n        }\n        if user.spawn_pending:\n            model['pending'] = 'spawn'\n        elif user.stop_pending:\n            model['pending'] = 'stop'\n        return model\n\n    def group_model(self, group):\n        \"\"\"Get the JSON model for a Group object\"\"\"\n        return {\n            'name': group.name,\n            'users': [ u.name for u in group.users ]\n        }\n\n    _user_model_types = {\n        'name': str,\n        'admin': bool,\n        'groups': list,\n    }\n\n    _group_model_types = {\n        'name': str,\n        'users': list,\n    }\n\n    def _check_model(self, model, model_types, name):\n        \"\"\"Check a model provided by a REST API request\n        \n        Args:\n            model (dict): user-provided model\n            model_types (dict): dict of key:type used to validate types and keys\n            name (str): name of the model, used in error messages\n        \"\"\"\n        if not isinstance(model, dict):\n            raise web.HTTPError(400, \"Invalid JSON data: %r\" % model)\n        if not set(model).issubset(set(model_types)):\n            raise web.HTTPError(400, \"Invalid JSON keys: %r\" % model)\n        for key, value in model.items():\n            if not isinstance(value, model_types[key]):\n                raise web.HTTPError(400, \"%s.%s must be %s, not: %r\" % (\n                    name, key, model_types[key], type(value)\n                ))\n\n    def _check_user_model(self, model):\n        \"\"\"Check a request-provided user model from a REST API\"\"\"\n        self._check_model(model, self._user_model_types, 'user')\n        for username in model.get('users', []):\n            if not isinstance(username, str):\n                raise web.HTTPError(400, (\"usernames must be str, not %r\", type(username)))\n\n    def _check_group_model(self, model):\n        \"\"\"Check a request-provided group model from a REST API\"\"\"\n        self._check_model(model, self._group_model_types, 'group')\n        for groupname in model.get('groups', []):\n            if not isinstance(groupname, str):\n                raise web.HTTPError(400, (\"group names must be str, not %r\", type(groupname)))\n\n    def options(self, *args, **kwargs):\n        self.set_header('Access-Control-Allow-Headers', 'accept, content-type')\n        self.finish()\n", "path": "jupyterhub/apihandlers/base.py"}]}