We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
AttributeError: module 'typing' has no attribute 'NoReturn' with Python 3.5.3
I get this error when running the tests with Python 3.5.3.

```
tests/test_py3/test_aiohttpparser_async_functions.py:6: in <module>
    from webargs.aiohttpparser import parser, use_args, use_kwargs
webargs/aiohttpparser.py:72: in <module>
    class AIOHTTPParser(AsyncParser):
webargs/aiohttpparser.py:148: in AIOHTTPParser
    ) -> typing.NoReturn:
E   AttributeError: module 'typing' has no attribute 'NoReturn'
```

The docs say [`typing.NoReturn`](https://docs.python.org/3/library/typing.html#typing.NoReturn) was added in 3.6.5. However, [the tests pass on Travis](https://travis-ci.org/marshmallow-code/webargs/jobs/486701760) with Python 3.5.6.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `webargs/aiohttpparser.py`
Content:
```
1 """aiohttp request argument parsing module.
2 
3 Example: ::
4 
5     import asyncio
6     from aiohttp import web
7 
8     from webargs import fields
9     from webargs.aiohttpparser import use_args
10 
11 
12     hello_args = {
13         'name': fields.Str(required=True)
14     }
15     @asyncio.coroutine
16     @use_args(hello_args)
17     def index(request, args):
18         return web.Response(
19             body='Hello {}'.format(args['name']).encode('utf-8')
20         )
21 
22     app = web.Application()
23     app.router.add_route('GET', '/', index)
24 """
25 import typing
26 
27 from aiohttp import web
28 from aiohttp.web import Request
29 from aiohttp import web_exceptions
30 from marshmallow import Schema, ValidationError
31 from marshmallow.fields import Field
32 
33 from webargs import core
34 from webargs.core import json
35 from webargs.asyncparser import AsyncParser
36 
37 
38 def is_json_request(req: Request) -> bool:
39     content_type = req.content_type
40     return core.is_json(content_type)
41 
42 
43 class HTTPUnprocessableEntity(web.HTTPClientError):
44     status_code = 422
45 
46 
47 # Mapping of status codes to exception classes
48 # Adapted from werkzeug
49 exception_map = {422: HTTPUnprocessableEntity}
50 
51 
52 def _find_exceptions() -> None:
53     for name in web_exceptions.__all__:
54         obj = getattr(web_exceptions, name)
55         try:
56             is_http_exception = issubclass(obj, web_exceptions.HTTPException)
57         except TypeError:
58             is_http_exception = False
59         if not is_http_exception or obj.status_code is None:
60             continue
61         old_obj = exception_map.get(obj.status_code, None)
62         if old_obj is not None and issubclass(obj, old_obj):
63             continue
64         exception_map[obj.status_code] = obj
65 
66 
67 # Collect all exceptions from aiohttp.web_exceptions
68 _find_exceptions()
69 del _find_exceptions
70 
71 
72 class AIOHTTPParser(AsyncParser):
73     """aiohttp request argument parser."""
74 
75     __location_map__ = dict(
76         match_info="parse_match_info", **core.Parser.__location_map__
77     )
78 
79     def parse_querystring(self, req: Request, name: str, field: Field) -> typing.Any:
80         """Pull a querystring value from the request."""
81         return core.get_value(req.query, name, field)
82 
83     async def parse_form(self, req: Request, name: str, field: Field) -> typing.Any:
84         """Pull a form value from the request."""
85         post_data = self._cache.get("post")
86         if post_data is None:
87             self._cache["post"] = await req.post()
88         return core.get_value(self._cache["post"], name, field)
89 
90     async def parse_json(self, req: Request, name: str, field: Field) -> typing.Any:
91         """Pull a json value from the request."""
92         json_data = self._cache.get("json")
93         if json_data is None:
94             if not (req.body_exists and is_json_request(req)):
95                 return core.missing
96             try:
97                 json_data = await req.json(loads=json.loads)
98             except json.JSONDecodeError as e:
99                 if e.doc == "":
100                     return core.missing
101                 else:
102                     return self.handle_invalid_json_error(e, req)
103             self._cache["json"] = json_data
104         return core.get_value(json_data, name, field, allow_many_nested=True)
105 
106     def parse_headers(self, req: Request, name: str, field: Field) -> typing.Any:
107         """Pull a value from the header data."""
108         return core.get_value(req.headers, name, field)
109 
110     def parse_cookies(self, req: Request, name: str, field: Field) -> typing.Any:
111         """Pull a value from the cookiejar."""
112         return core.get_value(req.cookies, name, field)
113 
114     def parse_files(self, req: Request, name: str, field: Field) -> None:
115         raise NotImplementedError(
116             "parse_files is not implemented. You may be able to use parse_form for "
117             "parsing upload data."
118         )
119 
120     def parse_match_info(self, req: Request, name: str, field: Field) -> typing.Any:
121         """Pull a value from the request's ``match_info``."""
122         return core.get_value(req.match_info, name, field)
123 
124     def get_request_from_view_args(
125         self, view: typing.Callable, args: typing.Iterable, kwargs: typing.Mapping
126     ) -> Request:
127         """Get request object from a handler function or method. Used internally by
128         ``use_args`` and ``use_kwargs``.
129         """
130         req = None
131         for arg in args:
132             if isinstance(arg, web.Request):
133                 req = arg
134                 break
135             elif isinstance(arg, web.View):
136                 req = arg.request
137                 break
138         assert isinstance(req, web.Request), "Request argument not found for handler"
139         return req
140 
141     def handle_error(
142         self,
143         error: ValidationError,
144         req: Request,
145         schema: Schema,
146         error_status_code: typing.Union[int, None] = None,
147         error_headers: typing.Union[typing.Mapping[str, str], None] = None,
148     ) -> typing.NoReturn:
149         """Handle ValidationErrors and return a JSON response of error messages
150         to the client.
151         """
152         error_class = exception_map.get(
153             error_status_code or self.DEFAULT_VALIDATION_STATUS
154         )
155         if not error_class:
156             raise LookupError("No exception for {0}".format(error_status_code))
157         headers = error_headers
158         raise error_class(
159             body=json.dumps(error.messages).encode("utf-8"),
160             headers=headers,
161             content_type="application/json",
162         )
163 
164     def handle_invalid_json_error(
165         self, error: json.JSONDecodeError, req: Request, *args, **kwargs
166     ) -> typing.NoReturn:
167         error_class = exception_map[400]
168         messages = {"json": ["Invalid JSON body."]}
169         raise error_class(
170             body=json.dumps(messages).encode("utf-8"), content_type="application/json"
171         )
172 
173 
174 parser = AIOHTTPParser()
175 use_args = parser.use_args  # type: typing.Callable
176 use_kwargs = parser.use_kwargs  # type: typing.Callable
177
```
--- 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/webargs/aiohttpparser.py b/webargs/aiohttpparser.py
--- a/webargs/aiohttpparser.py
+++ b/webargs/aiohttpparser.py
@@ -145,7 +145,7 @@
         schema: Schema,
         error_status_code: typing.Union[int, None] = None,
         error_headers: typing.Union[typing.Mapping[str, str], None] = None,
-    ) -> typing.NoReturn:
+    ) -> "typing.NoReturn":
         """Handle ValidationErrors and return a JSON response of error messages
         to the client.
         """
@@ -163,7 +163,7 @@
 
     def handle_invalid_json_error(
         self, error: json.JSONDecodeError, req: Request, *args, **kwargs
-    ) -> typing.NoReturn:
+    ) -> "typing.NoReturn":
         error_class = exception_map[400]
         messages = {"json": ["Invalid JSON body."]}
         raise error_class(

{"golden_diff": "diff --git a/webargs/aiohttpparser.py b/webargs/aiohttpparser.py\n--- a/webargs/aiohttpparser.py\n+++ b/webargs/aiohttpparser.py\n@@ -145,7 +145,7 @@\n         schema: Schema,\n         error_status_code: typing.Union[int, None] = None,\n         error_headers: typing.Union[typing.Mapping[str, str], None] = None,\n-    ) -> typing.NoReturn:\n+    ) -> \"typing.NoReturn\":\n         \"\"\"Handle ValidationErrors and return a JSON response of error messages\n         to the client.\n         \"\"\"\n@@ -163,7 +163,7 @@\n \n     def handle_invalid_json_error(\n         self, error: json.JSONDecodeError, req: Request, *args, **kwargs\n-    ) -> typing.NoReturn:\n+    ) -> \"typing.NoReturn\":\n         error_class = exception_map[400]\n         messages = {\"json\": [\"Invalid JSON body.\"]}\n         raise error_class(\n", "issue": "AttributeError: module 'typing' has no attribute 'NoReturn' with Python 3.5.3\nI get this error when running the tests with Python 3.5.3.\r\n\r\n```\r\ntests/test_py3/test_aiohttpparser_async_functions.py:6: in <module>\r\n    from webargs.aiohttpparser import parser, use_args, use_kwargs\r\nwebargs/aiohttpparser.py:72: in <module>\r\n    class AIOHTTPParser(AsyncParser):\r\nwebargs/aiohttpparser.py:148: in AIOHTTPParser\r\n    ) -> typing.NoReturn:\r\nE   AttributeError: module 'typing' has no attribute 'NoReturn'\r\n```\r\n\r\nThe docs say [`typing.NoReturn`](https://docs.python.org/3/library/typing.html#typing.NoReturn) was added in 3.6.5. However, [the tests pass on Travis](https://travis-ci.org/marshmallow-code/webargs/jobs/486701760) with Python 3.5.6.\n", "before_files": [{"content": "\"\"\"aiohttp request argument parsing module.\n\nExample: ::\n\n    import asyncio\n    from aiohttp import web\n\n    from webargs import fields\n    from webargs.aiohttpparser import use_args\n\n\n    hello_args = {\n        'name': fields.Str(required=True)\n    }\n    @asyncio.coroutine\n    @use_args(hello_args)\n    def index(request, args):\n        return web.Response(\n            body='Hello {}'.format(args['name']).encode('utf-8')\n        )\n\n    app = web.Application()\n    app.router.add_route('GET', '/', index)\n\"\"\"\nimport typing\n\nfrom aiohttp import web\nfrom aiohttp.web import Request\nfrom aiohttp import web_exceptions\nfrom marshmallow import Schema, ValidationError\nfrom marshmallow.fields import Field\n\nfrom webargs import core\nfrom webargs.core import json\nfrom webargs.asyncparser import AsyncParser\n\n\ndef is_json_request(req: Request) -> bool:\n    content_type = req.content_type\n    return core.is_json(content_type)\n\n\nclass HTTPUnprocessableEntity(web.HTTPClientError):\n    status_code = 422\n\n\n# Mapping of status codes to exception classes\n# Adapted from werkzeug\nexception_map = {422: HTTPUnprocessableEntity}\n\n\ndef _find_exceptions() -> None:\n    for name in web_exceptions.__all__:\n        obj = getattr(web_exceptions, name)\n        try:\n            is_http_exception = issubclass(obj, web_exceptions.HTTPException)\n        except TypeError:\n            is_http_exception = False\n        if not is_http_exception or obj.status_code is None:\n            continue\n        old_obj = exception_map.get(obj.status_code, None)\n        if old_obj is not None and issubclass(obj, old_obj):\n            continue\n        exception_map[obj.status_code] = obj\n\n\n# Collect all exceptions from aiohttp.web_exceptions\n_find_exceptions()\ndel _find_exceptions\n\n\nclass AIOHTTPParser(AsyncParser):\n    \"\"\"aiohttp request argument parser.\"\"\"\n\n    __location_map__ = dict(\n        match_info=\"parse_match_info\", **core.Parser.__location_map__\n    )\n\n    def parse_querystring(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a querystring value from the request.\"\"\"\n        return core.get_value(req.query, name, field)\n\n    async def parse_form(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a form value from the request.\"\"\"\n        post_data = self._cache.get(\"post\")\n        if post_data is None:\n            self._cache[\"post\"] = await req.post()\n        return core.get_value(self._cache[\"post\"], name, field)\n\n    async def parse_json(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a json value from the request.\"\"\"\n        json_data = self._cache.get(\"json\")\n        if json_data is None:\n            if not (req.body_exists and is_json_request(req)):\n                return core.missing\n            try:\n                json_data = await req.json(loads=json.loads)\n            except json.JSONDecodeError as e:\n                if e.doc == \"\":\n                    return core.missing\n                else:\n                    return self.handle_invalid_json_error(e, req)\n            self._cache[\"json\"] = json_data\n        return core.get_value(json_data, name, field, allow_many_nested=True)\n\n    def parse_headers(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a value from the header data.\"\"\"\n        return core.get_value(req.headers, name, field)\n\n    def parse_cookies(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a value from the cookiejar.\"\"\"\n        return core.get_value(req.cookies, name, field)\n\n    def parse_files(self, req: Request, name: str, field: Field) -> None:\n        raise NotImplementedError(\n            \"parse_files is not implemented. You may be able to use parse_form for \"\n            \"parsing upload data.\"\n        )\n\n    def parse_match_info(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a value from the request's ``match_info``.\"\"\"\n        return core.get_value(req.match_info, name, field)\n\n    def get_request_from_view_args(\n        self, view: typing.Callable, args: typing.Iterable, kwargs: typing.Mapping\n    ) -> Request:\n        \"\"\"Get request object from a handler function or method. Used internally by\n        ``use_args`` and ``use_kwargs``.\n        \"\"\"\n        req = None\n        for arg in args:\n            if isinstance(arg, web.Request):\n                req = arg\n                break\n            elif isinstance(arg, web.View):\n                req = arg.request\n                break\n        assert isinstance(req, web.Request), \"Request argument not found for handler\"\n        return req\n\n    def handle_error(\n        self,\n        error: ValidationError,\n        req: Request,\n        schema: Schema,\n        error_status_code: typing.Union[int, None] = None,\n        error_headers: typing.Union[typing.Mapping[str, str], None] = None,\n    ) -> typing.NoReturn:\n        \"\"\"Handle ValidationErrors and return a JSON response of error messages\n        to the client.\n        \"\"\"\n        error_class = exception_map.get(\n            error_status_code or self.DEFAULT_VALIDATION_STATUS\n        )\n        if not error_class:\n            raise LookupError(\"No exception for {0}\".format(error_status_code))\n        headers = error_headers\n        raise error_class(\n            body=json.dumps(error.messages).encode(\"utf-8\"),\n            headers=headers,\n            content_type=\"application/json\",\n        )\n\n    def handle_invalid_json_error(\n        self, error: json.JSONDecodeError, req: Request, *args, **kwargs\n    ) -> typing.NoReturn:\n        error_class = exception_map[400]\n        messages = {\"json\": [\"Invalid JSON body.\"]}\n        raise error_class(\n            body=json.dumps(messages).encode(\"utf-8\"), content_type=\"application/json\"\n        )\n\n\nparser = AIOHTTPParser()\nuse_args = parser.use_args  # type: typing.Callable\nuse_kwargs = parser.use_kwargs  # type: typing.Callable\n", "path": "webargs/aiohttpparser.py"}], "after_files": [{"content": "\"\"\"aiohttp request argument parsing module.\n\nExample: ::\n\n    import asyncio\n    from aiohttp import web\n\n    from webargs import fields\n    from webargs.aiohttpparser import use_args\n\n\n    hello_args = {\n        'name': fields.Str(required=True)\n    }\n    @asyncio.coroutine\n    @use_args(hello_args)\n    def index(request, args):\n        return web.Response(\n            body='Hello {}'.format(args['name']).encode('utf-8')\n        )\n\n    app = web.Application()\n    app.router.add_route('GET', '/', index)\n\"\"\"\nimport typing\n\nfrom aiohttp import web\nfrom aiohttp.web import Request\nfrom aiohttp import web_exceptions\nfrom marshmallow import Schema, ValidationError\nfrom marshmallow.fields import Field\n\nfrom webargs import core\nfrom webargs.core import json\nfrom webargs.asyncparser import AsyncParser\n\n\ndef is_json_request(req: Request) -> bool:\n    content_type = req.content_type\n    return core.is_json(content_type)\n\n\nclass HTTPUnprocessableEntity(web.HTTPClientError):\n    status_code = 422\n\n\n# Mapping of status codes to exception classes\n# Adapted from werkzeug\nexception_map = {422: HTTPUnprocessableEntity}\n\n\ndef _find_exceptions() -> None:\n    for name in web_exceptions.__all__:\n        obj = getattr(web_exceptions, name)\n        try:\n            is_http_exception = issubclass(obj, web_exceptions.HTTPException)\n        except TypeError:\n            is_http_exception = False\n        if not is_http_exception or obj.status_code is None:\n            continue\n        old_obj = exception_map.get(obj.status_code, None)\n        if old_obj is not None and issubclass(obj, old_obj):\n            continue\n        exception_map[obj.status_code] = obj\n\n\n# Collect all exceptions from aiohttp.web_exceptions\n_find_exceptions()\ndel _find_exceptions\n\n\nclass AIOHTTPParser(AsyncParser):\n    \"\"\"aiohttp request argument parser.\"\"\"\n\n    __location_map__ = dict(\n        match_info=\"parse_match_info\", **core.Parser.__location_map__\n    )\n\n    def parse_querystring(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a querystring value from the request.\"\"\"\n        return core.get_value(req.query, name, field)\n\n    async def parse_form(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a form value from the request.\"\"\"\n        post_data = self._cache.get(\"post\")\n        if post_data is None:\n            self._cache[\"post\"] = await req.post()\n        return core.get_value(self._cache[\"post\"], name, field)\n\n    async def parse_json(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a json value from the request.\"\"\"\n        json_data = self._cache.get(\"json\")\n        if json_data is None:\n            if not (req.body_exists and is_json_request(req)):\n                return core.missing\n            try:\n                json_data = await req.json(loads=json.loads)\n            except json.JSONDecodeError as e:\n                if e.doc == \"\":\n                    return core.missing\n                else:\n                    return self.handle_invalid_json_error(e, req)\n            self._cache[\"json\"] = json_data\n        return core.get_value(json_data, name, field, allow_many_nested=True)\n\n    def parse_headers(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a value from the header data.\"\"\"\n        return core.get_value(req.headers, name, field)\n\n    def parse_cookies(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a value from the cookiejar.\"\"\"\n        return core.get_value(req.cookies, name, field)\n\n    def parse_files(self, req: Request, name: str, field: Field) -> None:\n        raise NotImplementedError(\n            \"parse_files is not implemented. You may be able to use parse_form for \"\n            \"parsing upload data.\"\n        )\n\n    def parse_match_info(self, req: Request, name: str, field: Field) -> typing.Any:\n        \"\"\"Pull a value from the request's ``match_info``.\"\"\"\n        return core.get_value(req.match_info, name, field)\n\n    def get_request_from_view_args(\n        self, view: typing.Callable, args: typing.Iterable, kwargs: typing.Mapping\n    ) -> Request:\n        \"\"\"Get request object from a handler function or method. Used internally by\n        ``use_args`` and ``use_kwargs``.\n        \"\"\"\n        req = None\n        for arg in args:\n            if isinstance(arg, web.Request):\n                req = arg\n                break\n            elif isinstance(arg, web.View):\n                req = arg.request\n                break\n        assert isinstance(req, web.Request), \"Request argument not found for handler\"\n        return req\n\n    def handle_error(\n        self,\n        error: ValidationError,\n        req: Request,\n        schema: Schema,\n        error_status_code: typing.Union[int, None] = None,\n        error_headers: typing.Union[typing.Mapping[str, str], None] = None,\n    ) -> \"typing.NoReturn\":\n        \"\"\"Handle ValidationErrors and return a JSON response of error messages\n        to the client.\n        \"\"\"\n        error_class = exception_map.get(\n            error_status_code or self.DEFAULT_VALIDATION_STATUS\n        )\n        if not error_class:\n            raise LookupError(\"No exception for {0}\".format(error_status_code))\n        headers = error_headers\n        raise error_class(\n            body=json.dumps(error.messages).encode(\"utf-8\"),\n            headers=headers,\n            content_type=\"application/json\",\n        )\n\n    def handle_invalid_json_error(\n        self, error: json.JSONDecodeError, req: Request, *args, **kwargs\n    ) -> \"typing.NoReturn\":\n        error_class = exception_map[400]\n        messages = {\"json\": [\"Invalid JSON body.\"]}\n        raise error_class(\n            body=json.dumps(messages).encode(\"utf-8\"), content_type=\"application/json\"\n        )\n\n\nparser = AIOHTTPParser()\nuse_args = parser.use_args  # type: typing.Callable\nuse_kwargs = parser.use_kwargs  # type: typing.Callable\n", "path": "webargs/aiohttpparser.py"}]}