We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Example not working
I followed the example from the documentation
```python
from ariadne import QueryType, gql, make_executable_schema
from ariadne.asgi import GraphQL

type_defs = gql("""
    type Query {
        hello: String!
    }
""")

# Create type instance for Query type defined in our schema...
query = QueryType()

# ...and assign our resolver function to its "hello" field.
@query.field("hello")
def resolve_hello(_, info):
    request = info.context["request"]
    user_agent = request.headers.get("user-agent", "guest")
    return "Hello, %s!" % user_agent

schema = make_executable_schema(type_defs, query)
app = GraphQL(schema, debug=True)
```
I started the app with `uvicorn test:app`, which starts just fine.
But when I browse to http://localhost:8000/ it errors:
```ERROR: Exception in ASGI application
Traceback (most recent call last):
  File "/home/jonas/.local/share/virtualenvs/api-ariadne-WWJK7Q5Z/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 372, in run_asgi
    result = await asgi(self.receive, self.send)
  File "/home/jonas/.local/share/virtualenvs/api-ariadne-WWJK7Q5Z/lib/python3.7/site-packages/ariadne/asgi.py", line 71, in handle_http
    await response(receive, send)
TypeError: __call__() missing 1 required positional argument: 'send'
INFO: ('127.0.0.1', 42908) - "GET / HTTP/1.1" 500
``` 
I'm using ariadne 0.3.0 and tried with uvicorn version 0.7.1, 0.7.0 and 0.6.1

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setup.py`
Content:
```
1 #! /usr/bin/env python
2 import os
3 from setuptools import setup
4 
5 CLASSIFIERS = [
6     "Development Status :: 4 - Beta",
7     "Intended Audience :: Developers",
8     "License :: OSI Approved :: BSD License",
9     "Operating System :: OS Independent",
10     "Programming Language :: Python",
11     "Programming Language :: Python :: 3.6",
12     "Programming Language :: Python :: 3.7",
13     "Topic :: Software Development :: Libraries :: Python Modules",
14 ]
15 
16 README_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "README.md")
17 with open(README_PATH, "r") as f:
18     README = f.read()
19 
20 setup(
21     name="ariadne",
22     author="Mirumee Software",
23     author_email="hello@mirumee.com",
24     description="Ariadne is a Python library for implementing GraphQL servers.",
25     long_description=README,
26     long_description_content_type="text/markdown",
27     license="BSD",
28     version="0.4.0",
29     url="https://github.com/mirumee/ariadne",
30     packages=["ariadne"],
31     package_data={"ariadne": ["py.typed"]},
32     install_requires=[
33         "graphql-core-next>=1.0.3",
34         "starlette>=0.12.0b3",
35         "typing_extensions>=3.6.0",
36     ],
37     classifiers=CLASSIFIERS,
38     platforms=["any"],
39     zip_safe=False,
40 )
41
```

Path: `ariadne/asgi.py`
Content:
```
1 import asyncio
2 from typing import Any, AsyncGenerator, Dict, List, Optional, Tuple, cast
3 
4 from graphql import GraphQLError, GraphQLSchema
5 from starlette.requests import Request
6 from starlette.responses import HTMLResponse, JSONResponse, Response
7 from starlette.types import Receive, Scope, Send
8 from starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect
9 
10 from .constants import DATA_TYPE_JSON, PLAYGROUND_HTML
11 from .exceptions import HttpBadRequestError, HttpError
12 from .format_error import format_error
13 from .graphql import graphql, subscribe
14 from .logger import log_error
15 from .types import ContextValue, ErrorFormatter, RootValue
16 
17 GQL_CONNECTION_INIT = "connection_init"  # Client -> Server
18 GQL_CONNECTION_ACK = "connection_ack"  # Server -> Client
19 GQL_CONNECTION_ERROR = "connection_error"  # Server -> Client
20 
21 # NOTE: The keep alive message type does not follow the standard due to connection optimizations
22 GQL_CONNECTION_KEEP_ALIVE = "ka"  # Server -> Client
23 
24 GQL_CONNECTION_TERMINATE = "connection_terminate"  # Client -> Server
25 GQL_START = "start"  # Client -> Server
26 GQL_DATA = "data"  # Server -> Client
27 GQL_ERROR = "error"  # Server -> Client
28 GQL_COMPLETE = "complete"  # Server -> Client
29 GQL_STOP = "stop"  # Client -> Server
30 
31 
32 class GraphQL:
33     def __init__(
34         self,
35         schema: GraphQLSchema,
36         *,
37         context_value: Optional[ContextValue] = None,
38         root_value: Optional[RootValue] = None,
39         debug: bool = False,
40         logger: Optional[str] = None,
41         error_formatter: ErrorFormatter = format_error,
42         keepalive: float = None,
43     ):
44         self.context_value = context_value
45         self.root_value = root_value
46         self.debug = debug
47         self.logger = logger
48         self.error_formatter = error_formatter
49         self.keepalive = keepalive
50         self.schema = schema
51 
52     async def __call__(self, scope: Scope, receive: Receive, send: Send):
53         if scope["type"] == "http":
54             await self.handle_http(scope=scope, receive=receive, send=send)
55         elif scope["type"] == "websocket":
56             await self.handle_websocket(scope=scope, receive=receive, send=send)
57         else:
58             raise ValueError("Unknown scope type: %r" % (scope["type"],))
59 
60     async def get_context_for_request(self, request: Any) -> Any:
61         if callable(self.context_value):
62             return self.context_value(request)
63         return self.context_value or {"request": request}
64 
65     async def handle_http(self, scope: Scope, receive: Receive, send: Send):
66         request = Request(scope=scope, receive=receive)
67         if request.method == "GET":
68             response = await self.render_playground(request)
69         elif request.method == "POST":
70             response = await self.graphql_http_server(request)
71         else:
72             response = Response(status_code=405)
73         await response(scope, receive, send)
74 
75     async def handle_websocket(self, scope: Scope, receive: Receive, send: Send):
76         websocket = WebSocket(scope=scope, receive=receive, send=send)
77         await self.websocket_server(websocket)
78 
79     async def extract_data_from_request(
80         self, request: Request
81     ) -> Tuple[str, Optional[dict], Optional[str]]:
82         if request.headers.get("Content-Type") != DATA_TYPE_JSON:
83             raise HttpBadRequestError(
84                 "Posted content must be of type {}".format(DATA_TYPE_JSON)
85             )
86         try:
87             return await request.json()
88         except ValueError:
89             raise HttpBadRequestError("Request body is not a valid JSON")
90 
91     async def render_playground(  # pylint: disable=unused-argument
92         self, request: Request
93     ) -> HTMLResponse:
94         return HTMLResponse(PLAYGROUND_HTML)
95 
96     async def graphql_http_server(self, request: Request) -> Response:
97         try:
98             data = await self.extract_data_from_request(request)
99         except HttpError as error:
100             return Response(error.message or error.status, status_code=400)
101 
102         context_value = await self.get_context_for_request(request)
103         success, response = await graphql(
104             self.schema,
105             data,
106             context_value=context_value,
107             root_value=self.root_value,
108             debug=self.debug,
109             logger=self.logger,
110             error_formatter=self.error_formatter,
111         )
112         status_code = 200 if success else 400
113         return JSONResponse(response, status_code=status_code)
114 
115     async def websocket_server(self, websocket: WebSocket) -> None:
116         subscriptions: Dict[str, AsyncGenerator] = {}
117         await websocket.accept("graphql-ws")
118         try:
119             while websocket.application_state != WebSocketState.DISCONNECTED:
120                 message = await websocket.receive_json()
121                 await self.handle_websocket_message(message, websocket, subscriptions)
122         except WebSocketDisconnect:
123             pass
124         finally:
125             for operation_id in subscriptions:
126                 await subscriptions[operation_id].aclose()
127 
128     async def handle_websocket_message(  # pylint: disable=too-complex
129         self,
130         message: dict,
131         websocket: WebSocket,
132         subscriptions: Dict[str, AsyncGenerator],
133     ):
134         operation_id = cast(str, message.get("id"))
135         message_type = cast(str, message.get("type"))
136 
137         if message_type == GQL_CONNECTION_INIT:
138             await websocket.send_json({"type": GQL_CONNECTION_ACK})
139             asyncio.ensure_future(self.keep_websocket_alive(websocket))
140         elif message_type == GQL_CONNECTION_TERMINATE:
141             await websocket.close()
142         elif message_type == GQL_START:
143             await self.start_websocket_subscription(
144                 message.get("payload"), operation_id, websocket, subscriptions
145             )
146         elif message_type == GQL_STOP:
147             if operation_id in subscriptions:
148                 await subscriptions[operation_id].aclose()
149                 del subscriptions[operation_id]
150 
151     async def keep_websocket_alive(self, websocket: WebSocket):
152         if not self.keepalive:
153             return
154         while websocket.application_state != WebSocketState.DISCONNECTED:
155             try:
156                 await websocket.send_json({"type": GQL_CONNECTION_KEEP_ALIVE})
157             except WebSocketDisconnect:
158                 return
159             await asyncio.sleep(self.keepalive)
160 
161     async def start_websocket_subscription(
162         self,
163         data: Any,
164         operation_id: str,
165         websocket: WebSocket,
166         subscriptions: Dict[str, AsyncGenerator],
167     ):
168         context_value = await self.get_context_for_request(websocket)
169         success, results = await subscribe(
170             self.schema,
171             data,
172             context_value=context_value,
173             root_value=self.root_value,
174             debug=self.debug,
175             logger=self.logger,
176             error_formatter=self.error_formatter,
177         )
178         if not success:
179             results = cast(List[dict], results)
180             await websocket.send_json(
181                 {"type": GQL_ERROR, "id": operation_id, "payload": results[0]}
182             )
183         else:
184             results = cast(AsyncGenerator, results)
185             subscriptions[operation_id] = results
186             asyncio.ensure_future(
187                 self.observe_async_results(results, operation_id, websocket)
188             )
189 
190     async def observe_async_results(  # pylint: disable=too-complex
191         self, results: AsyncGenerator, operation_id: str, websocket: WebSocket
192     ) -> None:
193         try:
194             async for result in results:
195                 payload = {}
196                 if result.data:
197                     payload["data"] = result.data
198                 if result.errors:
199                     for error in result.errors:
200                         log_error(error, self.logger)
201                     payload["errors"] = [
202                         self.error_formatter(error, self.debug)
203                         for error in result.errors
204                     ]
205                 await websocket.send_json(
206                     {"type": GQL_DATA, "id": operation_id, "payload": payload}
207                 )
208         except Exception as error:  # pylint: disable=broad-except
209             if not isinstance(error, GraphQLError):
210                 error = GraphQLError(str(error), original_error=error)
211             log_error(error, self.logger)
212             payload = {"errors": [self.error_formatter(error, self.debug)]}
213             await websocket.send_json(
214                 {"type": GQL_DATA, "id": operation_id, "payload": payload}
215             )
216 
217         if websocket.application_state != WebSocketState.DISCONNECTED:
218             await websocket.send_json({"type": GQL_COMPLETE, "id": operation_id})
219
```
--- 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/ariadne/asgi.py b/ariadne/asgi.py
--- a/ariadne/asgi.py
+++ b/ariadne/asgi.py
@@ -3,7 +3,7 @@
 
 from graphql import GraphQLError, GraphQLSchema
 from starlette.requests import Request
-from starlette.responses import HTMLResponse, JSONResponse, Response
+from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response
 from starlette.types import Receive, Scope, Send
 from starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect
 
@@ -90,14 +90,14 @@
 
     async def render_playground(  # pylint: disable=unused-argument
         self, request: Request
-    ) -> HTMLResponse:
+    ) -> Response:
         return HTMLResponse(PLAYGROUND_HTML)
 
     async def graphql_http_server(self, request: Request) -> Response:
         try:
             data = await self.extract_data_from_request(request)
         except HttpError as error:
-            return Response(error.message or error.status, status_code=400)
+            return PlainTextResponse(error.message or error.status, status_code=400)
 
         context_value = await self.get_context_for_request(request)
         success, response = await graphql(
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -31,7 +31,7 @@
     package_data={"ariadne": ["py.typed"]},
     install_requires=[
         "graphql-core-next>=1.0.3",
-        "starlette>=0.12.0b3",
+        "starlette<0.13",
         "typing_extensions>=3.6.0",
     ],
     classifiers=CLASSIFIERS,

{"golden_diff": "diff --git a/ariadne/asgi.py b/ariadne/asgi.py\n--- a/ariadne/asgi.py\n+++ b/ariadne/asgi.py\n@@ -3,7 +3,7 @@\n \n from graphql import GraphQLError, GraphQLSchema\n from starlette.requests import Request\n-from starlette.responses import HTMLResponse, JSONResponse, Response\n+from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response\n from starlette.types import Receive, Scope, Send\n from starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect\n \n@@ -90,14 +90,14 @@\n \n     async def render_playground(  # pylint: disable=unused-argument\n         self, request: Request\n-    ) -> HTMLResponse:\n+    ) -> Response:\n         return HTMLResponse(PLAYGROUND_HTML)\n \n     async def graphql_http_server(self, request: Request) -> Response:\n         try:\n             data = await self.extract_data_from_request(request)\n         except HttpError as error:\n-            return Response(error.message or error.status, status_code=400)\n+            return PlainTextResponse(error.message or error.status, status_code=400)\n \n         context_value = await self.get_context_for_request(request)\n         success, response = await graphql(\ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -31,7 +31,7 @@\n     package_data={\"ariadne\": [\"py.typed\"]},\n     install_requires=[\n         \"graphql-core-next>=1.0.3\",\n-        \"starlette>=0.12.0b3\",\n+        \"starlette<0.13\",\n         \"typing_extensions>=3.6.0\",\n     ],\n     classifiers=CLASSIFIERS,\n", "issue": "Example not working\nI followed the example from the documentation\r\n```python\r\nfrom ariadne import QueryType, gql, make_executable_schema\r\nfrom ariadne.asgi import GraphQL\r\n\r\ntype_defs = gql(\"\"\"\r\n    type Query {\r\n        hello: String!\r\n    }\r\n\"\"\")\r\n\r\n# Create type instance for Query type defined in our schema...\r\nquery = QueryType()\r\n\r\n# ...and assign our resolver function to its \"hello\" field.\r\n@query.field(\"hello\")\r\ndef resolve_hello(_, info):\r\n    request = info.context[\"request\"]\r\n    user_agent = request.headers.get(\"user-agent\", \"guest\")\r\n    return \"Hello, %s!\" % user_agent\r\n\r\nschema = make_executable_schema(type_defs, query)\r\napp = GraphQL(schema, debug=True)\r\n```\r\nI started the app with `uvicorn test:app`, which starts just fine.\r\nBut when I browse to http://localhost:8000/ it errors:\r\n```ERROR: Exception in ASGI application\r\nTraceback (most recent call last):\r\n  File \"/home/jonas/.local/share/virtualenvs/api-ariadne-WWJK7Q5Z/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py\", line 372, in run_asgi\r\n    result = await asgi(self.receive, self.send)\r\n  File \"/home/jonas/.local/share/virtualenvs/api-ariadne-WWJK7Q5Z/lib/python3.7/site-packages/ariadne/asgi.py\", line 71, in handle_http\r\n    await response(receive, send)\r\nTypeError: __call__() missing 1 required positional argument: 'send'\r\nINFO: ('127.0.0.1', 42908) - \"GET / HTTP/1.1\" 500\r\n``` \r\nI'm using ariadne 0.3.0 and tried with uvicorn version 0.7.1, 0.7.0 and 0.6.1\n", "before_files": [{"content": "#! /usr/bin/env python\nimport os\nfrom setuptools import setup\n\nCLASSIFIERS = [\n    \"Development Status :: 4 - Beta\",\n    \"Intended Audience :: Developers\",\n    \"License :: OSI Approved :: BSD License\",\n    \"Operating System :: OS Independent\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Python :: 3.6\",\n    \"Programming Language :: Python :: 3.7\",\n    \"Topic :: Software Development :: Libraries :: Python Modules\",\n]\n\nREADME_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), \"README.md\")\nwith open(README_PATH, \"r\") as f:\n    README = f.read()\n\nsetup(\n    name=\"ariadne\",\n    author=\"Mirumee Software\",\n    author_email=\"hello@mirumee.com\",\n    description=\"Ariadne is a Python library for implementing GraphQL servers.\",\n    long_description=README,\n    long_description_content_type=\"text/markdown\",\n    license=\"BSD\",\n    version=\"0.4.0\",\n    url=\"https://github.com/mirumee/ariadne\",\n    packages=[\"ariadne\"],\n    package_data={\"ariadne\": [\"py.typed\"]},\n    install_requires=[\n        \"graphql-core-next>=1.0.3\",\n        \"starlette>=0.12.0b3\",\n        \"typing_extensions>=3.6.0\",\n    ],\n    classifiers=CLASSIFIERS,\n    platforms=[\"any\"],\n    zip_safe=False,\n)\n", "path": "setup.py"}, {"content": "import asyncio\nfrom typing import Any, AsyncGenerator, Dict, List, Optional, Tuple, cast\n\nfrom graphql import GraphQLError, GraphQLSchema\nfrom starlette.requests import Request\nfrom starlette.responses import HTMLResponse, JSONResponse, Response\nfrom starlette.types import Receive, Scope, Send\nfrom starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect\n\nfrom .constants import DATA_TYPE_JSON, PLAYGROUND_HTML\nfrom .exceptions import HttpBadRequestError, HttpError\nfrom .format_error import format_error\nfrom .graphql import graphql, subscribe\nfrom .logger import log_error\nfrom .types import ContextValue, ErrorFormatter, RootValue\n\nGQL_CONNECTION_INIT = \"connection_init\"  # Client -> Server\nGQL_CONNECTION_ACK = \"connection_ack\"  # Server -> Client\nGQL_CONNECTION_ERROR = \"connection_error\"  # Server -> Client\n\n# NOTE: The keep alive message type does not follow the standard due to connection optimizations\nGQL_CONNECTION_KEEP_ALIVE = \"ka\"  # Server -> Client\n\nGQL_CONNECTION_TERMINATE = \"connection_terminate\"  # Client -> Server\nGQL_START = \"start\"  # Client -> Server\nGQL_DATA = \"data\"  # Server -> Client\nGQL_ERROR = \"error\"  # Server -> Client\nGQL_COMPLETE = \"complete\"  # Server -> Client\nGQL_STOP = \"stop\"  # Client -> Server\n\n\nclass GraphQL:\n    def __init__(\n        self,\n        schema: GraphQLSchema,\n        *,\n        context_value: Optional[ContextValue] = None,\n        root_value: Optional[RootValue] = None,\n        debug: bool = False,\n        logger: Optional[str] = None,\n        error_formatter: ErrorFormatter = format_error,\n        keepalive: float = None,\n    ):\n        self.context_value = context_value\n        self.root_value = root_value\n        self.debug = debug\n        self.logger = logger\n        self.error_formatter = error_formatter\n        self.keepalive = keepalive\n        self.schema = schema\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send):\n        if scope[\"type\"] == \"http\":\n            await self.handle_http(scope=scope, receive=receive, send=send)\n        elif scope[\"type\"] == \"websocket\":\n            await self.handle_websocket(scope=scope, receive=receive, send=send)\n        else:\n            raise ValueError(\"Unknown scope type: %r\" % (scope[\"type\"],))\n\n    async def get_context_for_request(self, request: Any) -> Any:\n        if callable(self.context_value):\n            return self.context_value(request)\n        return self.context_value or {\"request\": request}\n\n    async def handle_http(self, scope: Scope, receive: Receive, send: Send):\n        request = Request(scope=scope, receive=receive)\n        if request.method == \"GET\":\n            response = await self.render_playground(request)\n        elif request.method == \"POST\":\n            response = await self.graphql_http_server(request)\n        else:\n            response = Response(status_code=405)\n        await response(scope, receive, send)\n\n    async def handle_websocket(self, scope: Scope, receive: Receive, send: Send):\n        websocket = WebSocket(scope=scope, receive=receive, send=send)\n        await self.websocket_server(websocket)\n\n    async def extract_data_from_request(\n        self, request: Request\n    ) -> Tuple[str, Optional[dict], Optional[str]]:\n        if request.headers.get(\"Content-Type\") != DATA_TYPE_JSON:\n            raise HttpBadRequestError(\n                \"Posted content must be of type {}\".format(DATA_TYPE_JSON)\n            )\n        try:\n            return await request.json()\n        except ValueError:\n            raise HttpBadRequestError(\"Request body is not a valid JSON\")\n\n    async def render_playground(  # pylint: disable=unused-argument\n        self, request: Request\n    ) -> HTMLResponse:\n        return HTMLResponse(PLAYGROUND_HTML)\n\n    async def graphql_http_server(self, request: Request) -> Response:\n        try:\n            data = await self.extract_data_from_request(request)\n        except HttpError as error:\n            return Response(error.message or error.status, status_code=400)\n\n        context_value = await self.get_context_for_request(request)\n        success, response = await graphql(\n            self.schema,\n            data,\n            context_value=context_value,\n            root_value=self.root_value,\n            debug=self.debug,\n            logger=self.logger,\n            error_formatter=self.error_formatter,\n        )\n        status_code = 200 if success else 400\n        return JSONResponse(response, status_code=status_code)\n\n    async def websocket_server(self, websocket: WebSocket) -> None:\n        subscriptions: Dict[str, AsyncGenerator] = {}\n        await websocket.accept(\"graphql-ws\")\n        try:\n            while websocket.application_state != WebSocketState.DISCONNECTED:\n                message = await websocket.receive_json()\n                await self.handle_websocket_message(message, websocket, subscriptions)\n        except WebSocketDisconnect:\n            pass\n        finally:\n            for operation_id in subscriptions:\n                await subscriptions[operation_id].aclose()\n\n    async def handle_websocket_message(  # pylint: disable=too-complex\n        self,\n        message: dict,\n        websocket: WebSocket,\n        subscriptions: Dict[str, AsyncGenerator],\n    ):\n        operation_id = cast(str, message.get(\"id\"))\n        message_type = cast(str, message.get(\"type\"))\n\n        if message_type == GQL_CONNECTION_INIT:\n            await websocket.send_json({\"type\": GQL_CONNECTION_ACK})\n            asyncio.ensure_future(self.keep_websocket_alive(websocket))\n        elif message_type == GQL_CONNECTION_TERMINATE:\n            await websocket.close()\n        elif message_type == GQL_START:\n            await self.start_websocket_subscription(\n                message.get(\"payload\"), operation_id, websocket, subscriptions\n            )\n        elif message_type == GQL_STOP:\n            if operation_id in subscriptions:\n                await subscriptions[operation_id].aclose()\n                del subscriptions[operation_id]\n\n    async def keep_websocket_alive(self, websocket: WebSocket):\n        if not self.keepalive:\n            return\n        while websocket.application_state != WebSocketState.DISCONNECTED:\n            try:\n                await websocket.send_json({\"type\": GQL_CONNECTION_KEEP_ALIVE})\n            except WebSocketDisconnect:\n                return\n            await asyncio.sleep(self.keepalive)\n\n    async def start_websocket_subscription(\n        self,\n        data: Any,\n        operation_id: str,\n        websocket: WebSocket,\n        subscriptions: Dict[str, AsyncGenerator],\n    ):\n        context_value = await self.get_context_for_request(websocket)\n        success, results = await subscribe(\n            self.schema,\n            data,\n            context_value=context_value,\n            root_value=self.root_value,\n            debug=self.debug,\n            logger=self.logger,\n            error_formatter=self.error_formatter,\n        )\n        if not success:\n            results = cast(List[dict], results)\n            await websocket.send_json(\n                {\"type\": GQL_ERROR, \"id\": operation_id, \"payload\": results[0]}\n            )\n        else:\n            results = cast(AsyncGenerator, results)\n            subscriptions[operation_id] = results\n            asyncio.ensure_future(\n                self.observe_async_results(results, operation_id, websocket)\n            )\n\n    async def observe_async_results(  # pylint: disable=too-complex\n        self, results: AsyncGenerator, operation_id: str, websocket: WebSocket\n    ) -> None:\n        try:\n            async for result in results:\n                payload = {}\n                if result.data:\n                    payload[\"data\"] = result.data\n                if result.errors:\n                    for error in result.errors:\n                        log_error(error, self.logger)\n                    payload[\"errors\"] = [\n                        self.error_formatter(error, self.debug)\n                        for error in result.errors\n                    ]\n                await websocket.send_json(\n                    {\"type\": GQL_DATA, \"id\": operation_id, \"payload\": payload}\n                )\n        except Exception as error:  # pylint: disable=broad-except\n            if not isinstance(error, GraphQLError):\n                error = GraphQLError(str(error), original_error=error)\n            log_error(error, self.logger)\n            payload = {\"errors\": [self.error_formatter(error, self.debug)]}\n            await websocket.send_json(\n                {\"type\": GQL_DATA, \"id\": operation_id, \"payload\": payload}\n            )\n\n        if websocket.application_state != WebSocketState.DISCONNECTED:\n            await websocket.send_json({\"type\": GQL_COMPLETE, \"id\": operation_id})\n", "path": "ariadne/asgi.py"}], "after_files": [{"content": "#! /usr/bin/env python\nimport os\nfrom setuptools import setup\n\nCLASSIFIERS = [\n    \"Development Status :: 4 - Beta\",\n    \"Intended Audience :: Developers\",\n    \"License :: OSI Approved :: BSD License\",\n    \"Operating System :: OS Independent\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Python :: 3.6\",\n    \"Programming Language :: Python :: 3.7\",\n    \"Topic :: Software Development :: Libraries :: Python Modules\",\n]\n\nREADME_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), \"README.md\")\nwith open(README_PATH, \"r\") as f:\n    README = f.read()\n\nsetup(\n    name=\"ariadne\",\n    author=\"Mirumee Software\",\n    author_email=\"hello@mirumee.com\",\n    description=\"Ariadne is a Python library for implementing GraphQL servers.\",\n    long_description=README,\n    long_description_content_type=\"text/markdown\",\n    license=\"BSD\",\n    version=\"0.4.0\",\n    url=\"https://github.com/mirumee/ariadne\",\n    packages=[\"ariadne\"],\n    package_data={\"ariadne\": [\"py.typed\"]},\n    install_requires=[\n        \"graphql-core-next>=1.0.3\",\n        \"starlette<0.13\",\n        \"typing_extensions>=3.6.0\",\n    ],\n    classifiers=CLASSIFIERS,\n    platforms=[\"any\"],\n    zip_safe=False,\n)\n", "path": "setup.py"}, {"content": "import asyncio\nfrom typing import Any, AsyncGenerator, Dict, List, Optional, Tuple, cast\n\nfrom graphql import GraphQLError, GraphQLSchema\nfrom starlette.requests import Request\nfrom starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse, Response\nfrom starlette.types import Receive, Scope, Send\nfrom starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect\n\nfrom .constants import DATA_TYPE_JSON, PLAYGROUND_HTML\nfrom .exceptions import HttpBadRequestError, HttpError\nfrom .format_error import format_error\nfrom .graphql import graphql, subscribe\nfrom .logger import log_error\nfrom .types import ContextValue, ErrorFormatter, RootValue\n\nGQL_CONNECTION_INIT = \"connection_init\"  # Client -> Server\nGQL_CONNECTION_ACK = \"connection_ack\"  # Server -> Client\nGQL_CONNECTION_ERROR = \"connection_error\"  # Server -> Client\n\n# NOTE: The keep alive message type does not follow the standard due to connection optimizations\nGQL_CONNECTION_KEEP_ALIVE = \"ka\"  # Server -> Client\n\nGQL_CONNECTION_TERMINATE = \"connection_terminate\"  # Client -> Server\nGQL_START = \"start\"  # Client -> Server\nGQL_DATA = \"data\"  # Server -> Client\nGQL_ERROR = \"error\"  # Server -> Client\nGQL_COMPLETE = \"complete\"  # Server -> Client\nGQL_STOP = \"stop\"  # Client -> Server\n\n\nclass GraphQL:\n    def __init__(\n        self,\n        schema: GraphQLSchema,\n        *,\n        context_value: Optional[ContextValue] = None,\n        root_value: Optional[RootValue] = None,\n        debug: bool = False,\n        logger: Optional[str] = None,\n        error_formatter: ErrorFormatter = format_error,\n        keepalive: float = None,\n    ):\n        self.context_value = context_value\n        self.root_value = root_value\n        self.debug = debug\n        self.logger = logger\n        self.error_formatter = error_formatter\n        self.keepalive = keepalive\n        self.schema = schema\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send):\n        if scope[\"type\"] == \"http\":\n            await self.handle_http(scope=scope, receive=receive, send=send)\n        elif scope[\"type\"] == \"websocket\":\n            await self.handle_websocket(scope=scope, receive=receive, send=send)\n        else:\n            raise ValueError(\"Unknown scope type: %r\" % (scope[\"type\"],))\n\n    async def get_context_for_request(self, request: Any) -> Any:\n        if callable(self.context_value):\n            return self.context_value(request)\n        return self.context_value or {\"request\": request}\n\n    async def handle_http(self, scope: Scope, receive: Receive, send: Send):\n        request = Request(scope=scope, receive=receive)\n        if request.method == \"GET\":\n            response = await self.render_playground(request)\n        elif request.method == \"POST\":\n            response = await self.graphql_http_server(request)\n        else:\n            response = Response(status_code=405)\n        await response(scope, receive, send)\n\n    async def handle_websocket(self, scope: Scope, receive: Receive, send: Send):\n        websocket = WebSocket(scope=scope, receive=receive, send=send)\n        await self.websocket_server(websocket)\n\n    async def extract_data_from_request(\n        self, request: Request\n    ) -> Tuple[str, Optional[dict], Optional[str]]:\n        if request.headers.get(\"Content-Type\") != DATA_TYPE_JSON:\n            raise HttpBadRequestError(\n                \"Posted content must be of type {}\".format(DATA_TYPE_JSON)\n            )\n        try:\n            return await request.json()\n        except ValueError:\n            raise HttpBadRequestError(\"Request body is not a valid JSON\")\n\n    async def render_playground(  # pylint: disable=unused-argument\n        self, request: Request\n    ) -> Response:\n        return HTMLResponse(PLAYGROUND_HTML)\n\n    async def graphql_http_server(self, request: Request) -> Response:\n        try:\n            data = await self.extract_data_from_request(request)\n        except HttpError as error:\n            return PlainTextResponse(error.message or error.status, status_code=400)\n\n        context_value = await self.get_context_for_request(request)\n        success, response = await graphql(\n            self.schema,\n            data,\n            context_value=context_value,\n            root_value=self.root_value,\n            debug=self.debug,\n            logger=self.logger,\n            error_formatter=self.error_formatter,\n        )\n        status_code = 200 if success else 400\n        return JSONResponse(response, status_code=status_code)\n\n    async def websocket_server(self, websocket: WebSocket) -> None:\n        subscriptions: Dict[str, AsyncGenerator] = {}\n        await websocket.accept(\"graphql-ws\")\n        try:\n            while websocket.application_state != WebSocketState.DISCONNECTED:\n                message = await websocket.receive_json()\n                await self.handle_websocket_message(message, websocket, subscriptions)\n        except WebSocketDisconnect:\n            pass\n        finally:\n            for operation_id in subscriptions:\n                await subscriptions[operation_id].aclose()\n\n    async def handle_websocket_message(  # pylint: disable=too-complex\n        self,\n        message: dict,\n        websocket: WebSocket,\n        subscriptions: Dict[str, AsyncGenerator],\n    ):\n        operation_id = cast(str, message.get(\"id\"))\n        message_type = cast(str, message.get(\"type\"))\n\n        if message_type == GQL_CONNECTION_INIT:\n            await websocket.send_json({\"type\": GQL_CONNECTION_ACK})\n            asyncio.ensure_future(self.keep_websocket_alive(websocket))\n        elif message_type == GQL_CONNECTION_TERMINATE:\n            await websocket.close()\n        elif message_type == GQL_START:\n            await self.start_websocket_subscription(\n                message.get(\"payload\"), operation_id, websocket, subscriptions\n            )\n        elif message_type == GQL_STOP:\n            if operation_id in subscriptions:\n                await subscriptions[operation_id].aclose()\n                del subscriptions[operation_id]\n\n    async def keep_websocket_alive(self, websocket: WebSocket):\n        if not self.keepalive:\n            return\n        while websocket.application_state != WebSocketState.DISCONNECTED:\n            try:\n                await websocket.send_json({\"type\": GQL_CONNECTION_KEEP_ALIVE})\n            except WebSocketDisconnect:\n                return\n            await asyncio.sleep(self.keepalive)\n\n    async def start_websocket_subscription(\n        self,\n        data: Any,\n        operation_id: str,\n        websocket: WebSocket,\n        subscriptions: Dict[str, AsyncGenerator],\n    ):\n        context_value = await self.get_context_for_request(websocket)\n        success, results = await subscribe(\n            self.schema,\n            data,\n            context_value=context_value,\n            root_value=self.root_value,\n            debug=self.debug,\n            logger=self.logger,\n            error_formatter=self.error_formatter,\n        )\n        if not success:\n            results = cast(List[dict], results)\n            await websocket.send_json(\n                {\"type\": GQL_ERROR, \"id\": operation_id, \"payload\": results[0]}\n            )\n        else:\n            results = cast(AsyncGenerator, results)\n            subscriptions[operation_id] = results\n            asyncio.ensure_future(\n                self.observe_async_results(results, operation_id, websocket)\n            )\n\n    async def observe_async_results(  # pylint: disable=too-complex\n        self, results: AsyncGenerator, operation_id: str, websocket: WebSocket\n    ) -> None:\n        try:\n            async for result in results:\n                payload = {}\n                if result.data:\n                    payload[\"data\"] = result.data\n                if result.errors:\n                    for error in result.errors:\n                        log_error(error, self.logger)\n                    payload[\"errors\"] = [\n                        self.error_formatter(error, self.debug)\n                        for error in result.errors\n                    ]\n                await websocket.send_json(\n                    {\"type\": GQL_DATA, \"id\": operation_id, \"payload\": payload}\n                )\n        except Exception as error:  # pylint: disable=broad-except\n            if not isinstance(error, GraphQLError):\n                error = GraphQLError(str(error), original_error=error)\n            log_error(error, self.logger)\n            payload = {\"errors\": [self.error_formatter(error, self.debug)]}\n            await websocket.send_json(\n                {\"type\": GQL_DATA, \"id\": operation_id, \"payload\": payload}\n            )\n\n        if websocket.application_state != WebSocketState.DISCONNECTED:\n            await websocket.send_json({\"type\": GQL_COMPLETE, \"id\": operation_id})\n", "path": "ariadne/asgi.py"}]}