prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Mitmweb fails with addons/options-configure.py example.
  I am new to learn it, but i follow official [demo][1], it can't working?
  ```python
  Proxy server listening at http://*:8888
  ERROR:tornado.application:Uncaught exception GET /options.json (127.0.0.1)
  HTTPServerRequest(protocol='http', host='127.0.0.1:8081', method='GET', uri='/options.json', version='HTTP/1.1', remote_ip='127.0.0.1')
  Traceback (most recent call last):
    File "c:\users\jekoie\appdata\local\programs\python\python37-32\lib\site-packages\tornado\web.py", line 1697, in _execute
      result = method(*self.path_args, **self.path_kwargs)
    File "c:\users\jekoie\appdata\local\programs\python\python37-32\lib\site-packages\mitmproxy\tools\web\app.py", line 453, in get
      self.write(optmanager.dump_dicts(self.master.options))
    File "c:\users\jekoie\appdata\local\programs\python\python37-32\lib\site-packages\mitmproxy\optmanager.py", line 469, in dump_dicts
      t = typecheck.typespec_to_str(o.typespec)
    File "c:\users\jekoie\appdata\local\programs\python\python37-32\lib\site-packages\mitmproxy\utils\typecheck.py", line 85, in typespec_to_str
      raise NotImplementedError
  NotImplementedError
  ERROR:tornado.access:500 GET /options.json (127.0.0.1) 3.91ms
  ````
  
  [1]: https://docs.mitmproxy.org/stable/addons-options/#handling-configuration-updates
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mitmproxy/utils/typecheck.py`
  Content:
  ```
  1 import typing
  2 
  3 Type = typing.Union[
  4     typing.Any  # anything more elaborate really fails with mypy at the moment.
  5 ]
  6 
  7 
  8 def sequence_type(typeinfo: typing.Type[typing.List]) -> Type:
  9     """Return the type of a sequence, e.g. typing.List"""
  10     return typeinfo.__args__[0]  # type: ignore
  11 
  12 
  13 def tuple_types(typeinfo: typing.Type[typing.Tuple]) -> typing.Sequence[Type]:
  14     """Return the types of a typing.Tuple"""
  15     return typeinfo.__args__  # type: ignore
  16 
  17 
  18 def union_types(typeinfo: typing.Type[typing.Tuple]) -> typing.Sequence[Type]:
  19     """return the types of a typing.Union"""
  20     return typeinfo.__args__  # type: ignore
  21 
  22 
  23 def mapping_types(typeinfo: typing.Type[typing.Mapping]) -> typing.Tuple[Type, Type]:
  24     """return the types of a mapping, e.g. typing.Dict"""
  25     return typeinfo.__args__  # type: ignore
  26 
  27 
  28 def check_option_type(name: str, value: typing.Any, typeinfo: Type) -> None:
  29     """
  30     Check if the provided value is an instance of typeinfo and raises a
  31     TypeError otherwise. This function supports only those types required for
  32     options.
  33     """
  34     e = TypeError("Expected {} for {}, but got {}.".format(
  35         typeinfo,
  36         name,
  37         type(value)
  38     ))
  39 
  40     typename = str(typeinfo)
  41 
  42     if typename.startswith("typing.Union"):
  43         for T in union_types(typeinfo):
  44             try:
  45                 check_option_type(name, value, T)
  46             except TypeError:
  47                 pass
  48             else:
  49                 return
  50         raise e
  51     elif typename.startswith("typing.Tuple"):
  52         types = tuple_types(typeinfo)
  53         if not isinstance(value, (tuple, list)):
  54             raise e
  55         if len(types) != len(value):
  56             raise e
  57         for i, (x, T) in enumerate(zip(value, types)):
  58             check_option_type("{}[{}]".format(name, i), x, T)
  59         return
  60     elif typename.startswith("typing.Sequence"):
  61         T = sequence_type(typeinfo)
  62         if not isinstance(value, (tuple, list)):
  63             raise e
  64         for v in value:
  65             check_option_type(name, v, T)
  66     elif typename.startswith("typing.IO"):
  67         if hasattr(value, "read"):
  68             return
  69         else:
  70             raise e
  71     elif typename.startswith("typing.Any"):
  72         return
  73     elif not isinstance(value, typeinfo):
  74         raise e
  75 
  76 
  77 def typespec_to_str(typespec: typing.Any) -> str:
  78     if typespec in (str, int, bool):
  79         t = typespec.__name__
  80     elif typespec == typing.Optional[str]:
  81         t = 'optional str'
  82     elif typespec == typing.Sequence[str]:
  83         t = 'sequence of str'
  84     else:
  85         raise NotImplementedError
  86     return t
  87
  ```
  --- 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/mitmproxy/utils/typecheck.py b/mitmproxy/utils/typecheck.py
  --- a/mitmproxy/utils/typecheck.py
  +++ b/mitmproxy/utils/typecheck.py
  @@ -81,6 +81,8 @@
           t = 'optional str'
       elif typespec == typing.Sequence[str]:
           t = 'sequence of str'
  +    elif typespec == typing.Optional[int]:
  +        t = 'optional int'
       else:
           raise NotImplementedError
       return t
  
verification_info: {"golden_diff": "diff --git a/mitmproxy/utils/typecheck.py b/mitmproxy/utils/typecheck.py\n--- a/mitmproxy/utils/typecheck.py\n+++ b/mitmproxy/utils/typecheck.py\n@@ -81,6 +81,8 @@\n         t = 'optional str'\n     elif typespec == typing.Sequence[str]:\n         t = 'sequence of str'\n+    elif typespec == typing.Optional[int]:\n+        t = 'optional int'\n     else:\n         raise NotImplementedError\n     return t\n", "issue": "Mitmweb fails with addons/options-configure.py example.\nI am new to learn it, but i follow official [demo][1], it can't working?\r\n```python\r\nProxy server listening at http://*:8888\r\nERROR:tornado.application:Uncaught exception GET /options.json (127.0.0.1)\r\nHTTPServerRequest(protocol='http', host='127.0.0.1:8081', method='GET', uri='/options.json', version='HTTP/1.1', remote_ip='127.0.0.1')\r\nTraceback (most recent call last):\r\n  File \"c:\\users\\jekoie\\appdata\\local\\programs\\python\\python37-32\\lib\\site-packages\\tornado\\web.py\", line 1697, in _execute\r\n    result = method(*self.path_args, **self.path_kwargs)\r\n  File \"c:\\users\\jekoie\\appdata\\local\\programs\\python\\python37-32\\lib\\site-packages\\mitmproxy\\tools\\web\\app.py\", line 453, in get\r\n    self.write(optmanager.dump_dicts(self.master.options))\r\n  File \"c:\\users\\jekoie\\appdata\\local\\programs\\python\\python37-32\\lib\\site-packages\\mitmproxy\\optmanager.py\", line 469, in dump_dicts\r\n    t = typecheck.typespec_to_str(o.typespec)\r\n  File \"c:\\users\\jekoie\\appdata\\local\\programs\\python\\python37-32\\lib\\site-packages\\mitmproxy\\utils\\typecheck.py\", line 85, in typespec_to_str\r\n    raise NotImplementedError\r\nNotImplementedError\r\nERROR:tornado.access:500 GET /options.json (127.0.0.1) 3.91ms\r\n````\r\n\r\n[1]: https://docs.mitmproxy.org/stable/addons-options/#handling-configuration-updates\n", "before_files": [{"content": "import typing\n\nType = typing.Union[\n    typing.Any  # anything more elaborate really fails with mypy at the moment.\n]\n\n\ndef sequence_type(typeinfo: typing.Type[typing.List]) -> Type:\n    \"\"\"Return the type of a sequence, e.g. typing.List\"\"\"\n    return typeinfo.__args__[0]  # type: ignore\n\n\ndef tuple_types(typeinfo: typing.Type[typing.Tuple]) -> typing.Sequence[Type]:\n    \"\"\"Return the types of a typing.Tuple\"\"\"\n    return typeinfo.__args__  # type: ignore\n\n\ndef union_types(typeinfo: typing.Type[typing.Tuple]) -> typing.Sequence[Type]:\n    \"\"\"return the types of a typing.Union\"\"\"\n    return typeinfo.__args__  # type: ignore\n\n\ndef mapping_types(typeinfo: typing.Type[typing.Mapping]) -> typing.Tuple[Type, Type]:\n    \"\"\"return the types of a mapping, e.g. typing.Dict\"\"\"\n    return typeinfo.__args__  # type: ignore\n\n\ndef check_option_type(name: str, value: typing.Any, typeinfo: Type) -> None:\n    \"\"\"\n    Check if the provided value is an instance of typeinfo and raises a\n    TypeError otherwise. This function supports only those types required for\n    options.\n    \"\"\"\n    e = TypeError(\"Expected {} for {}, but got {}.\".format(\n        typeinfo,\n        name,\n        type(value)\n    ))\n\n    typename = str(typeinfo)\n\n    if typename.startswith(\"typing.Union\"):\n        for T in union_types(typeinfo):\n            try:\n                check_option_type(name, value, T)\n            except TypeError:\n                pass\n            else:\n                return\n        raise e\n    elif typename.startswith(\"typing.Tuple\"):\n        types = tuple_types(typeinfo)\n        if not isinstance(value, (tuple, list)):\n            raise e\n        if len(types) != len(value):\n            raise e\n        for i, (x, T) in enumerate(zip(value, types)):\n            check_option_type(\"{}[{}]\".format(name, i), x, T)\n        return\n    elif typename.startswith(\"typing.Sequence\"):\n        T = sequence_type(typeinfo)\n        if not isinstance(value, (tuple, list)):\n            raise e\n        for v in value:\n            check_option_type(name, v, T)\n    elif typename.startswith(\"typing.IO\"):\n        if hasattr(value, \"read\"):\n            return\n        else:\n            raise e\n    elif typename.startswith(\"typing.Any\"):\n        return\n    elif not isinstance(value, typeinfo):\n        raise e\n\n\ndef typespec_to_str(typespec: typing.Any) -> str:\n    if typespec in (str, int, bool):\n        t = typespec.__name__\n    elif typespec == typing.Optional[str]:\n        t = 'optional str'\n    elif typespec == typing.Sequence[str]:\n        t = 'sequence of str'\n    else:\n        raise NotImplementedError\n    return t\n", "path": "mitmproxy/utils/typecheck.py"}], "after_files": [{"content": "import typing\n\nType = typing.Union[\n    typing.Any  # anything more elaborate really fails with mypy at the moment.\n]\n\n\ndef sequence_type(typeinfo: typing.Type[typing.List]) -> Type:\n    \"\"\"Return the type of a sequence, e.g. typing.List\"\"\"\n    return typeinfo.__args__[0]  # type: ignore\n\n\ndef tuple_types(typeinfo: typing.Type[typing.Tuple]) -> typing.Sequence[Type]:\n    \"\"\"Return the types of a typing.Tuple\"\"\"\n    return typeinfo.__args__  # type: ignore\n\n\ndef union_types(typeinfo: typing.Type[typing.Tuple]) -> typing.Sequence[Type]:\n    \"\"\"return the types of a typing.Union\"\"\"\n    return typeinfo.__args__  # type: ignore\n\n\ndef mapping_types(typeinfo: typing.Type[typing.Mapping]) -> typing.Tuple[Type, Type]:\n    \"\"\"return the types of a mapping, e.g. typing.Dict\"\"\"\n    return typeinfo.__args__  # type: ignore\n\n\ndef check_option_type(name: str, value: typing.Any, typeinfo: Type) -> None:\n    \"\"\"\n    Check if the provided value is an instance of typeinfo and raises a\n    TypeError otherwise. This function supports only those types required for\n    options.\n    \"\"\"\n    e = TypeError(\"Expected {} for {}, but got {}.\".format(\n        typeinfo,\n        name,\n        type(value)\n    ))\n\n    typename = str(typeinfo)\n\n    if typename.startswith(\"typing.Union\"):\n        for T in union_types(typeinfo):\n            try:\n                check_option_type(name, value, T)\n            except TypeError:\n                pass\n            else:\n                return\n        raise e\n    elif typename.startswith(\"typing.Tuple\"):\n        types = tuple_types(typeinfo)\n        if not isinstance(value, (tuple, list)):\n            raise e\n        if len(types) != len(value):\n            raise e\n        for i, (x, T) in enumerate(zip(value, types)):\n            check_option_type(\"{}[{}]\".format(name, i), x, T)\n        return\n    elif typename.startswith(\"typing.Sequence\"):\n        T = sequence_type(typeinfo)\n        if not isinstance(value, (tuple, list)):\n            raise e\n        for v in value:\n            check_option_type(name, v, T)\n    elif typename.startswith(\"typing.IO\"):\n        if hasattr(value, \"read\"):\n            return\n        else:\n            raise e\n    elif typename.startswith(\"typing.Any\"):\n        return\n    elif not isinstance(value, typeinfo):\n        raise e\n\n\ndef typespec_to_str(typespec: typing.Any) -> str:\n    if typespec in (str, int, bool):\n        t = typespec.__name__\n    elif typespec == typing.Optional[str]:\n        t = 'optional str'\n    elif typespec == typing.Sequence[str]:\n        t = 'sequence of str'\n    elif typespec == typing.Optional[int]:\n        t = 'optional int'\n    else:\n        raise NotImplementedError\n    return t\n", "path": "mitmproxy/utils/typecheck.py"}]}