We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Change how globals are passed in GraphQL
Currently global variables are passed as their own special `globals` field. This is a non-standard field and it gets in the way of existing frameworks and libraries.

An alternative to that would be to use the `variables` field that's part of the GraphQL standard and add `__globals__` to that.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `edb/testbase/http.py`
Content:
```
1 #
2 # This source file is part of the EdgeDB open source project.
3 #
4 # Copyright 2019-present MagicStack Inc. and the EdgeDB authors.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #     http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 
19 
20 from __future__ import annotations
21 from typing import *
22 
23 import json
24 import urllib.parse
25 import urllib.request
26 
27 import edgedb
28 
29 from edb.errors import base as base_errors
30 
31 from edb.common import assert_data_shape
32 
33 from . import server
34 
35 
36 bag = assert_data_shape.bag
37 
38 
39 class BaseHttpExtensionTest(server.QueryTestCase):
40     EXTENSION_SETUP: List[str] = []
41 
42     @classmethod
43     def get_extension_name(cls):
44         raise NotImplementedError
45 
46     @classmethod
47     def get_extension_path(cls):
48         return cls.get_extension_name()
49 
50     @classmethod
51     def get_api_prefix(cls):
52         extpath = cls.get_extension_path()
53         dbname = cls.get_database_name()
54         return f'/db/{dbname}/{extpath}'
55 
56     @classmethod
57     def get_setup_script(cls):
58         script = super().get_setup_script()
59 
60         extname = cls.get_extension_name()
61         script += f'\nCREATE EXTENSION pgcrypto;\n'
62         script += f'\nCREATE EXTENSION {extname};\n'
63         script += "\n".join(cls.EXTENSION_SETUP)
64         return script
65 
66     @classmethod
67     def tearDownClass(cls):
68         extname = cls.get_extension_name()
69         cls.loop.run_until_complete(
70             cls.con.execute(f'DROP EXTENSION {extname};')
71         )
72         super().tearDownClass()
73 
74 
75 class ExtAuthTestCase(BaseHttpExtensionTest):
76 
77     @classmethod
78     def get_extension_name(cls):
79         return 'auth'
80 
81     @classmethod
82     def get_extension_path(cls):
83         return 'ext/auth'
84 
85 
86 class EdgeQLTestCase(BaseHttpExtensionTest):
87 
88     @classmethod
89     def get_extension_name(cls):
90         return 'edgeql_http'
91 
92     @classmethod
93     def get_extension_path(cls):
94         return 'edgeql'
95 
96     def edgeql_query(
97             self, query, *, use_http_post=True, variables=None, globals=None):
98         req_data = {
99             'query': query
100         }
101 
102         if use_http_post:
103             if variables is not None:
104                 req_data['variables'] = variables
105             if globals is not None:
106                 req_data['globals'] = globals
107             req = urllib.request.Request(self.http_addr, method='POST')
108             req.add_header('Content-Type', 'application/json')
109             response = urllib.request.urlopen(
110                 req, json.dumps(req_data).encode(), context=self.tls_context
111             )
112             resp_data = json.loads(response.read())
113         else:
114             if variables is not None:
115                 req_data['variables'] = json.dumps(variables)
116             if globals is not None:
117                 req_data['globals'] = json.dumps(globals)
118             response = urllib.request.urlopen(
119                 f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',
120                 context=self.tls_context,
121             )
122             resp_data = json.loads(response.read())
123 
124         if 'data' in resp_data:
125             return resp_data['data']
126 
127         err = resp_data['error']
128 
129         ex_msg = err['message'].strip()
130         ex_code = err['code']
131 
132         raise edgedb.EdgeDBError._from_code(ex_code, ex_msg)
133 
134     def assert_edgeql_query_result(self, query, result, *,
135                                    msg=None, sort=None,
136                                    use_http_post=True,
137                                    variables=None,
138                                    globals=None):
139         res = self.edgeql_query(
140             query,
141             use_http_post=use_http_post,
142             variables=variables,
143             globals=globals)
144 
145         if sort is not None:
146             # GQL will always have a single object returned. The data is
147             # in the top-level fields, so that's what needs to be sorted.
148             for r in res.values():
149                 assert_data_shape.sort_results(r, sort)
150 
151         assert_data_shape.assert_data_shape(
152             res, result, self.fail, message=msg)
153         return res
154 
155 
156 class GraphQLTestCase(BaseHttpExtensionTest):
157 
158     @classmethod
159     def get_extension_name(cls):
160         return 'graphql'
161 
162     def graphql_query(self, query, *, operation_name=None,
163                       use_http_post=True,
164                       variables=None,
165                       globals=None):
166         req_data = {
167             'query': query
168         }
169 
170         if operation_name is not None:
171             req_data['operationName'] = operation_name
172 
173         if use_http_post:
174             if variables is not None:
175                 req_data['variables'] = variables
176             if globals is not None:
177                 req_data['globals'] = globals
178             req = urllib.request.Request(self.http_addr, method='POST')
179             req.add_header('Content-Type', 'application/json')
180             response = urllib.request.urlopen(
181                 req, json.dumps(req_data).encode(), context=self.tls_context
182             )
183             resp_data = json.loads(response.read())
184         else:
185             if variables is not None:
186                 req_data['variables'] = json.dumps(variables)
187             if globals is not None:
188                 req_data['globals'] = json.dumps(globals)
189             response = urllib.request.urlopen(
190                 f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',
191                 context=self.tls_context,
192             )
193             resp_data = json.loads(response.read())
194 
195         if 'data' in resp_data:
196             return resp_data['data']
197 
198         err = resp_data['errors'][0]
199 
200         typename, msg = err['message'].split(':', 1)
201         msg = msg.strip()
202 
203         try:
204             ex_type = getattr(edgedb, typename)
205         except AttributeError:
206             raise AssertionError(
207                 f'server returned an invalid exception typename: {typename!r}'
208                 f'\n  Message: {msg}')
209 
210         ex = ex_type(msg)
211 
212         if 'locations' in err:
213             # XXX Fix this when LSP "location" objects are implemented
214             ex._attrs[base_errors.FIELD_LINE_START] = str(
215                 err['locations'][0]['line']).encode()
216             ex._attrs[base_errors.FIELD_COLUMN_START] = str(
217                 err['locations'][0]['column']).encode()
218 
219         raise ex
220 
221     def assert_graphql_query_result(self, query, result, *,
222                                     msg=None, sort=None,
223                                     operation_name=None,
224                                     use_http_post=True,
225                                     variables=None,
226                                     globals=None):
227         res = self.graphql_query(
228             query,
229             operation_name=operation_name,
230             use_http_post=use_http_post,
231             variables=variables,
232             globals=globals)
233 
234         if sort is not None:
235             # GQL will always have a single object returned. The data is
236             # in the top-level fields, so that's what needs to be sorted.
237             for r in res.values():
238                 assert_data_shape.sort_results(r, sort)
239 
240         assert_data_shape.assert_data_shape(
241             res, result, self.fail, message=msg)
242         return res
243
```
--- 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/edb/testbase/http.py b/edb/testbase/http.py
--- a/edb/testbase/http.py
+++ b/edb/testbase/http.py
@@ -162,7 +162,8 @@
     def graphql_query(self, query, *, operation_name=None,
                       use_http_post=True,
                       variables=None,
-                      globals=None):
+                      globals=None,
+                      deprecated_globals=None):
         req_data = {
             'query': query
         }
@@ -174,7 +175,13 @@
             if variables is not None:
                 req_data['variables'] = variables
             if globals is not None:
-                req_data['globals'] = globals
+                if variables is None:
+                    req_data['variables'] = dict()
+                req_data['variables']['__globals__'] = globals
+            # Support testing the old way of sending globals.
+            if deprecated_globals is not None:
+                req_data['globals'] = deprecated_globals
+
             req = urllib.request.Request(self.http_addr, method='POST')
             req.add_header('Content-Type', 'application/json')
             response = urllib.request.urlopen(
@@ -182,10 +189,15 @@
             )
             resp_data = json.loads(response.read())
         else:
+            if globals is not None:
+                if variables is None:
+                    variables = dict()
+                variables['__globals__'] = globals
+            # Support testing the old way of sending globals.
+            if deprecated_globals is not None:
+                req_data['globals'] = json.dumps(deprecated_globals)
             if variables is not None:
                 req_data['variables'] = json.dumps(variables)
-            if globals is not None:
-                req_data['globals'] = json.dumps(globals)
             response = urllib.request.urlopen(
                 f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',
                 context=self.tls_context,
@@ -223,13 +235,15 @@
                                     operation_name=None,
                                     use_http_post=True,
                                     variables=None,
-                                    globals=None):
+                                    globals=None,
+                                    deprecated_globals=None):
         res = self.graphql_query(
             query,
             operation_name=operation_name,
             use_http_post=use_http_post,
             variables=variables,
-            globals=globals)
+            globals=globals,
+            deprecated_globals=deprecated_globals)
 
         if sort is not None:
             # GQL will always have a single object returned. The data is

{"golden_diff": "diff --git a/edb/testbase/http.py b/edb/testbase/http.py\n--- a/edb/testbase/http.py\n+++ b/edb/testbase/http.py\n@@ -162,7 +162,8 @@\n     def graphql_query(self, query, *, operation_name=None,\n                       use_http_post=True,\n                       variables=None,\n-                      globals=None):\n+                      globals=None,\n+                      deprecated_globals=None):\n         req_data = {\n             'query': query\n         }\n@@ -174,7 +175,13 @@\n             if variables is not None:\n                 req_data['variables'] = variables\n             if globals is not None:\n-                req_data['globals'] = globals\n+                if variables is None:\n+                    req_data['variables'] = dict()\n+                req_data['variables']['__globals__'] = globals\n+            # Support testing the old way of sending globals.\n+            if deprecated_globals is not None:\n+                req_data['globals'] = deprecated_globals\n+\n             req = urllib.request.Request(self.http_addr, method='POST')\n             req.add_header('Content-Type', 'application/json')\n             response = urllib.request.urlopen(\n@@ -182,10 +189,15 @@\n             )\n             resp_data = json.loads(response.read())\n         else:\n+            if globals is not None:\n+                if variables is None:\n+                    variables = dict()\n+                variables['__globals__'] = globals\n+            # Support testing the old way of sending globals.\n+            if deprecated_globals is not None:\n+                req_data['globals'] = json.dumps(deprecated_globals)\n             if variables is not None:\n                 req_data['variables'] = json.dumps(variables)\n-            if globals is not None:\n-                req_data['globals'] = json.dumps(globals)\n             response = urllib.request.urlopen(\n                 f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',\n                 context=self.tls_context,\n@@ -223,13 +235,15 @@\n                                     operation_name=None,\n                                     use_http_post=True,\n                                     variables=None,\n-                                    globals=None):\n+                                    globals=None,\n+                                    deprecated_globals=None):\n         res = self.graphql_query(\n             query,\n             operation_name=operation_name,\n             use_http_post=use_http_post,\n             variables=variables,\n-            globals=globals)\n+            globals=globals,\n+            deprecated_globals=deprecated_globals)\n \n         if sort is not None:\n             # GQL will always have a single object returned. The data is\n", "issue": "Change how globals are passed in GraphQL\nCurrently global variables are passed as their own special `globals` field. This is a non-standard field and it gets in the way of existing frameworks and libraries.\r\n\r\nAn alternative to that would be to use the `variables` field that's part of the GraphQL standard and add `__globals__` to that.\n", "before_files": [{"content": "#\n# This source file is part of the EdgeDB open source project.\n#\n# Copyright 2019-present MagicStack Inc. and the EdgeDB authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n\nfrom __future__ import annotations\nfrom typing import *\n\nimport json\nimport urllib.parse\nimport urllib.request\n\nimport edgedb\n\nfrom edb.errors import base as base_errors\n\nfrom edb.common import assert_data_shape\n\nfrom . import server\n\n\nbag = assert_data_shape.bag\n\n\nclass BaseHttpExtensionTest(server.QueryTestCase):\n    EXTENSION_SETUP: List[str] = []\n\n    @classmethod\n    def get_extension_name(cls):\n        raise NotImplementedError\n\n    @classmethod\n    def get_extension_path(cls):\n        return cls.get_extension_name()\n\n    @classmethod\n    def get_api_prefix(cls):\n        extpath = cls.get_extension_path()\n        dbname = cls.get_database_name()\n        return f'/db/{dbname}/{extpath}'\n\n    @classmethod\n    def get_setup_script(cls):\n        script = super().get_setup_script()\n\n        extname = cls.get_extension_name()\n        script += f'\\nCREATE EXTENSION pgcrypto;\\n'\n        script += f'\\nCREATE EXTENSION {extname};\\n'\n        script += \"\\n\".join(cls.EXTENSION_SETUP)\n        return script\n\n    @classmethod\n    def tearDownClass(cls):\n        extname = cls.get_extension_name()\n        cls.loop.run_until_complete(\n            cls.con.execute(f'DROP EXTENSION {extname};')\n        )\n        super().tearDownClass()\n\n\nclass ExtAuthTestCase(BaseHttpExtensionTest):\n\n    @classmethod\n    def get_extension_name(cls):\n        return 'auth'\n\n    @classmethod\n    def get_extension_path(cls):\n        return 'ext/auth'\n\n\nclass EdgeQLTestCase(BaseHttpExtensionTest):\n\n    @classmethod\n    def get_extension_name(cls):\n        return 'edgeql_http'\n\n    @classmethod\n    def get_extension_path(cls):\n        return 'edgeql'\n\n    def edgeql_query(\n            self, query, *, use_http_post=True, variables=None, globals=None):\n        req_data = {\n            'query': query\n        }\n\n        if use_http_post:\n            if variables is not None:\n                req_data['variables'] = variables\n            if globals is not None:\n                req_data['globals'] = globals\n            req = urllib.request.Request(self.http_addr, method='POST')\n            req.add_header('Content-Type', 'application/json')\n            response = urllib.request.urlopen(\n                req, json.dumps(req_data).encode(), context=self.tls_context\n            )\n            resp_data = json.loads(response.read())\n        else:\n            if variables is not None:\n                req_data['variables'] = json.dumps(variables)\n            if globals is not None:\n                req_data['globals'] = json.dumps(globals)\n            response = urllib.request.urlopen(\n                f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',\n                context=self.tls_context,\n            )\n            resp_data = json.loads(response.read())\n\n        if 'data' in resp_data:\n            return resp_data['data']\n\n        err = resp_data['error']\n\n        ex_msg = err['message'].strip()\n        ex_code = err['code']\n\n        raise edgedb.EdgeDBError._from_code(ex_code, ex_msg)\n\n    def assert_edgeql_query_result(self, query, result, *,\n                                   msg=None, sort=None,\n                                   use_http_post=True,\n                                   variables=None,\n                                   globals=None):\n        res = self.edgeql_query(\n            query,\n            use_http_post=use_http_post,\n            variables=variables,\n            globals=globals)\n\n        if sort is not None:\n            # GQL will always have a single object returned. The data is\n            # in the top-level fields, so that's what needs to be sorted.\n            for r in res.values():\n                assert_data_shape.sort_results(r, sort)\n\n        assert_data_shape.assert_data_shape(\n            res, result, self.fail, message=msg)\n        return res\n\n\nclass GraphQLTestCase(BaseHttpExtensionTest):\n\n    @classmethod\n    def get_extension_name(cls):\n        return 'graphql'\n\n    def graphql_query(self, query, *, operation_name=None,\n                      use_http_post=True,\n                      variables=None,\n                      globals=None):\n        req_data = {\n            'query': query\n        }\n\n        if operation_name is not None:\n            req_data['operationName'] = operation_name\n\n        if use_http_post:\n            if variables is not None:\n                req_data['variables'] = variables\n            if globals is not None:\n                req_data['globals'] = globals\n            req = urllib.request.Request(self.http_addr, method='POST')\n            req.add_header('Content-Type', 'application/json')\n            response = urllib.request.urlopen(\n                req, json.dumps(req_data).encode(), context=self.tls_context\n            )\n            resp_data = json.loads(response.read())\n        else:\n            if variables is not None:\n                req_data['variables'] = json.dumps(variables)\n            if globals is not None:\n                req_data['globals'] = json.dumps(globals)\n            response = urllib.request.urlopen(\n                f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',\n                context=self.tls_context,\n            )\n            resp_data = json.loads(response.read())\n\n        if 'data' in resp_data:\n            return resp_data['data']\n\n        err = resp_data['errors'][0]\n\n        typename, msg = err['message'].split(':', 1)\n        msg = msg.strip()\n\n        try:\n            ex_type = getattr(edgedb, typename)\n        except AttributeError:\n            raise AssertionError(\n                f'server returned an invalid exception typename: {typename!r}'\n                f'\\n  Message: {msg}')\n\n        ex = ex_type(msg)\n\n        if 'locations' in err:\n            # XXX Fix this when LSP \"location\" objects are implemented\n            ex._attrs[base_errors.FIELD_LINE_START] = str(\n                err['locations'][0]['line']).encode()\n            ex._attrs[base_errors.FIELD_COLUMN_START] = str(\n                err['locations'][0]['column']).encode()\n\n        raise ex\n\n    def assert_graphql_query_result(self, query, result, *,\n                                    msg=None, sort=None,\n                                    operation_name=None,\n                                    use_http_post=True,\n                                    variables=None,\n                                    globals=None):\n        res = self.graphql_query(\n            query,\n            operation_name=operation_name,\n            use_http_post=use_http_post,\n            variables=variables,\n            globals=globals)\n\n        if sort is not None:\n            # GQL will always have a single object returned. The data is\n            # in the top-level fields, so that's what needs to be sorted.\n            for r in res.values():\n                assert_data_shape.sort_results(r, sort)\n\n        assert_data_shape.assert_data_shape(\n            res, result, self.fail, message=msg)\n        return res\n", "path": "edb/testbase/http.py"}], "after_files": [{"content": "#\n# This source file is part of the EdgeDB open source project.\n#\n# Copyright 2019-present MagicStack Inc. and the EdgeDB authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n\nfrom __future__ import annotations\nfrom typing import *\n\nimport json\nimport urllib.parse\nimport urllib.request\n\nimport edgedb\n\nfrom edb.errors import base as base_errors\n\nfrom edb.common import assert_data_shape\n\nfrom . import server\n\n\nbag = assert_data_shape.bag\n\n\nclass BaseHttpExtensionTest(server.QueryTestCase):\n    EXTENSION_SETUP: List[str] = []\n\n    @classmethod\n    def get_extension_name(cls):\n        raise NotImplementedError\n\n    @classmethod\n    def get_extension_path(cls):\n        return cls.get_extension_name()\n\n    @classmethod\n    def get_api_prefix(cls):\n        extpath = cls.get_extension_path()\n        dbname = cls.get_database_name()\n        return f'/db/{dbname}/{extpath}'\n\n    @classmethod\n    def get_setup_script(cls):\n        script = super().get_setup_script()\n\n        extname = cls.get_extension_name()\n        script += f'\\nCREATE EXTENSION pgcrypto;\\n'\n        script += f'\\nCREATE EXTENSION {extname};\\n'\n        script += \"\\n\".join(cls.EXTENSION_SETUP)\n        return script\n\n    @classmethod\n    def tearDownClass(cls):\n        extname = cls.get_extension_name()\n        cls.loop.run_until_complete(\n            cls.con.execute(f'DROP EXTENSION {extname};')\n        )\n        super().tearDownClass()\n\n\nclass ExtAuthTestCase(BaseHttpExtensionTest):\n\n    @classmethod\n    def get_extension_name(cls):\n        return 'auth'\n\n    @classmethod\n    def get_extension_path(cls):\n        return 'ext/auth'\n\n\nclass EdgeQLTestCase(BaseHttpExtensionTest):\n\n    @classmethod\n    def get_extension_name(cls):\n        return 'edgeql_http'\n\n    @classmethod\n    def get_extension_path(cls):\n        return 'edgeql'\n\n    def edgeql_query(\n            self, query, *, use_http_post=True, variables=None, globals=None):\n        req_data = {\n            'query': query\n        }\n\n        if use_http_post:\n            if variables is not None:\n                req_data['variables'] = variables\n            if globals is not None:\n                req_data['globals'] = globals\n            req = urllib.request.Request(self.http_addr, method='POST')\n            req.add_header('Content-Type', 'application/json')\n            response = urllib.request.urlopen(\n                req, json.dumps(req_data).encode(), context=self.tls_context\n            )\n            resp_data = json.loads(response.read())\n        else:\n            if variables is not None:\n                req_data['variables'] = json.dumps(variables)\n            if globals is not None:\n                req_data['globals'] = json.dumps(globals)\n            response = urllib.request.urlopen(\n                f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',\n                context=self.tls_context,\n            )\n            resp_data = json.loads(response.read())\n\n        if 'data' in resp_data:\n            return resp_data['data']\n\n        err = resp_data['error']\n\n        ex_msg = err['message'].strip()\n        ex_code = err['code']\n\n        raise edgedb.EdgeDBError._from_code(ex_code, ex_msg)\n\n    def assert_edgeql_query_result(self, query, result, *,\n                                   msg=None, sort=None,\n                                   use_http_post=True,\n                                   variables=None,\n                                   globals=None):\n        res = self.edgeql_query(\n            query,\n            use_http_post=use_http_post,\n            variables=variables,\n            globals=globals)\n\n        if sort is not None:\n            # GQL will always have a single object returned. The data is\n            # in the top-level fields, so that's what needs to be sorted.\n            for r in res.values():\n                assert_data_shape.sort_results(r, sort)\n\n        assert_data_shape.assert_data_shape(\n            res, result, self.fail, message=msg)\n        return res\n\n\nclass GraphQLTestCase(BaseHttpExtensionTest):\n\n    @classmethod\n    def get_extension_name(cls):\n        return 'graphql'\n\n    def graphql_query(self, query, *, operation_name=None,\n                      use_http_post=True,\n                      variables=None,\n                      globals=None,\n                      deprecated_globals=None):\n        req_data = {\n            'query': query\n        }\n\n        if operation_name is not None:\n            req_data['operationName'] = operation_name\n\n        if use_http_post:\n            if variables is not None:\n                req_data['variables'] = variables\n            if globals is not None:\n                if variables is None:\n                    req_data['variables'] = dict()\n                req_data['variables']['__globals__'] = globals\n            # Support testing the old way of sending globals.\n            if deprecated_globals is not None:\n                req_data['globals'] = deprecated_globals\n\n            req = urllib.request.Request(self.http_addr, method='POST')\n            req.add_header('Content-Type', 'application/json')\n            response = urllib.request.urlopen(\n                req, json.dumps(req_data).encode(), context=self.tls_context\n            )\n            resp_data = json.loads(response.read())\n        else:\n            if globals is not None:\n                if variables is None:\n                    variables = dict()\n                variables['__globals__'] = globals\n            # Support testing the old way of sending globals.\n            if deprecated_globals is not None:\n                req_data['globals'] = json.dumps(deprecated_globals)\n            if variables is not None:\n                req_data['variables'] = json.dumps(variables)\n            response = urllib.request.urlopen(\n                f'{self.http_addr}/?{urllib.parse.urlencode(req_data)}',\n                context=self.tls_context,\n            )\n            resp_data = json.loads(response.read())\n\n        if 'data' in resp_data:\n            return resp_data['data']\n\n        err = resp_data['errors'][0]\n\n        typename, msg = err['message'].split(':', 1)\n        msg = msg.strip()\n\n        try:\n            ex_type = getattr(edgedb, typename)\n        except AttributeError:\n            raise AssertionError(\n                f'server returned an invalid exception typename: {typename!r}'\n                f'\\n  Message: {msg}')\n\n        ex = ex_type(msg)\n\n        if 'locations' in err:\n            # XXX Fix this when LSP \"location\" objects are implemented\n            ex._attrs[base_errors.FIELD_LINE_START] = str(\n                err['locations'][0]['line']).encode()\n            ex._attrs[base_errors.FIELD_COLUMN_START] = str(\n                err['locations'][0]['column']).encode()\n\n        raise ex\n\n    def assert_graphql_query_result(self, query, result, *,\n                                    msg=None, sort=None,\n                                    operation_name=None,\n                                    use_http_post=True,\n                                    variables=None,\n                                    globals=None,\n                                    deprecated_globals=None):\n        res = self.graphql_query(\n            query,\n            operation_name=operation_name,\n            use_http_post=use_http_post,\n            variables=variables,\n            globals=globals,\n            deprecated_globals=deprecated_globals)\n\n        if sort is not None:\n            # GQL will always have a single object returned. The data is\n            # in the top-level fields, so that's what needs to be sorted.\n            for r in res.values():\n                assert_data_shape.sort_results(r, sort)\n\n        assert_data_shape.assert_data_shape(\n            res, result, self.fail, message=msg)\n        return res\n", "path": "edb/testbase/http.py"}]}