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()

```

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

{"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"}]}