diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0f7453c..58601c5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,4 +19,4 @@ jobs: - name: Run lint and static type checks run: tox env: - TOXENV: flake8,black,import-order,mypy,manifest + TOXENV: pre-commit,mypy diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0fab074 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +default_language_version: + python: python3.10 +exclude: LICENSE +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-merge-conflict + - id: check-json + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + exclude: ^docs/.*$ + - id: pretty-format-json + args: + - --autofix + - id: trailing-whitespace +- repo: https://github.com/mgedmin/check-manifest + rev: "0.49" + hooks: + - id: check-manifest +- repo: https://github.com/psf/black + rev: 23.7.0 + hooks: + - id: black +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.283 + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix, --show-fixes] diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..db5e5b6 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,35 @@ +select = [ + "E", # pycodestyle + "W", # pycodestyle + "F", # pyflake + "I", # isort + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade +] + +ignore = [ + "E501", # line-too-long + "B904", # check for raise statements in exception handlers that lack a from clause +] + +exclude = [ + "**/docs", +] + +target-version = "py38" + +[per-file-ignores] +# Ignore unused imports (F401) in these files +"__init__.py" = ["F401"] + +[isort] +known-first-party = ["graphql_server"] +force-wrap-aliases = true +combine-as-imports = true + +[pyupgrade] +# this keeps annotation syntaxes like Union[X, Y] instead of X | Y +# to not break Python 3.8 +# https://beta.ruff.rs/docs/settings/#pyupgrade-keep-runtime-typing +keep-runtime-typing = true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 98f59f0..79d237b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,8 +31,7 @@ Activate the virtualenv and install dependencies by running: python pip install -e ".[test]" ``` -If you are using Linux or MacOS, you can make use of Makefile command -`make dev-setup`, which is a shortcut for the above python command. +If you are using Linux or MacOS, you can make use of Makefile command `make dev-setup`, which is a shortcut for the above python command. ### Development on Conda @@ -60,8 +59,7 @@ After developing, the full test suite can be evaluated by running: pytest tests --cov=graphql-server -vv ``` -If you are using Linux or MacOS, you can make use of Makefile command -`make tests`, which is a shortcut for the above python command. +If you are using Linux or MacOS, you can make use of Makefile command `make tests`, which is a shortcut for the above python command. You can also test on several python environments by using tox. @@ -73,8 +71,7 @@ Install tox: pip install tox ``` -Run `tox` on your virtualenv (do not forget to activate it!) -and that's it! +Run `tox` on your virtualenv (do not forget to activate it!) and that's it! ### Running tox on Conda @@ -89,5 +86,4 @@ This install tox underneath so no need to install it before. Then uncomment the `requires = tox-conda` line on `tox.ini` file. -Run `tox` and you will see all the environments being created -and all passing tests. :rocket: +Run `tox` and you will see all the environments being created and all passing tests. :rocket: diff --git a/MANIFEST.in b/MANIFEST.in index a6c003d..67b0e2f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,6 +6,8 @@ include CONTRIBUTING.md include codecov.yml include tox.ini +include .pre-commit-config.yaml +include .ruff.toml recursive-include docs *.md *.svg diff --git a/codecov.yml b/codecov.yml index c393a12..c155caa 100644 --- a/codecov.yml +++ b/codecov.yml @@ -7,4 +7,4 @@ coverage: status: project: default: - target: auto \ No newline at end of file + target: auto diff --git a/graphql_server/aiohttp/graphqlview.py b/graphql_server/aiohttp/graphqlview.py index 4087946..ea23037 100644 --- a/graphql_server/aiohttp/graphqlview.py +++ b/graphql_server/aiohttp/graphqlview.py @@ -56,7 +56,7 @@ class GraphQLView: encode = staticmethod(json_encode) def __init__(self, **kwargs): - super(GraphQLView, self).__init__() + super().__init__() for key, value in kwargs.items(): if hasattr(self, key): setattr(self, key, value) @@ -177,7 +177,7 @@ async def __call__(self, request): *( ex if ex is not None and is_awaitable(ex) - else wrap_in_async(lambda: ex)() + else wrap_in_async(lambda x: x)(ex) for ex in execution_results ) ) @@ -188,15 +188,15 @@ async def __call__(self, request): exec_res, is_batch=isinstance(data, list), format_error=self.format_error, - encode=partial(self.encode, pretty=is_pretty), # noqa: ignore + encode=partial(self.encode, pretty=is_pretty), ) if is_graphiql: graphiql_data = GraphiQLData( result=result, - query=getattr(all_params[0], "query"), - variables=getattr(all_params[0], "variables"), - operation_name=getattr(all_params[0], "operation_name"), + query=all_params[0].query, + variables=all_params[0].variables, + operation_name=all_params[0].operation_name, subscription_url=self.subscriptions, headers=self.headers, ) @@ -225,7 +225,7 @@ async def __call__(self, request): except HttpQueryError as err: parsed_error = GraphQLError(err.message) return web.Response( - body=self.encode(dict(errors=[self.format_error(parsed_error)])), + body=self.encode({"errors": [self.format_error(parsed_error)]}), status=err.status_code, headers=err.headers, content_type="application/json", diff --git a/graphql_server/error.py b/graphql_server/error.py index b0ca74a..497f121 100644 --- a/graphql_server/error.py +++ b/graphql_server/error.py @@ -16,7 +16,7 @@ def __init__(self, status_code, message=None, is_graphql_error=False, headers=No self.message = message self.is_graphql_error = is_graphql_error self.headers = headers - super(HttpQueryError, self).__init__(message) + super().__init__(message) def __eq__(self, other): """Check whether this HTTP query error is equal to another one.""" diff --git a/graphql_server/flask/graphqlview.py b/graphql_server/flask/graphqlview.py index 7440f82..d59124d 100644 --- a/graphql_server/flask/graphqlview.py +++ b/graphql_server/flask/graphqlview.py @@ -53,7 +53,7 @@ class GraphQLView(View): encode = staticmethod(json_encode) def __init__(self, **kwargs): - super(GraphQLView, self).__init__() + super().__init__() for key, value in kwargs.items(): if hasattr(self, key): setattr(self, key, value) @@ -120,15 +120,15 @@ def dispatch_request(self): execution_results, is_batch=isinstance(data, list), format_error=self.format_error, - encode=partial(self.encode, pretty=pretty), # noqa + encode=partial(self.encode, pretty=pretty), ) if show_graphiql: graphiql_data = GraphiQLData( result=result, - query=getattr(all_params[0], "query"), - variables=getattr(all_params[0], "variables"), - operation_name=getattr(all_params[0], "operation_name"), + query=all_params[0].query, + variables=all_params[0].variables, + operation_name=all_params[0].operation_name, subscription_url=self.subscriptions, headers=self.headers, ) @@ -153,7 +153,7 @@ def dispatch_request(self): except HttpQueryError as e: parsed_error = GraphQLError(e.message) return Response( - self.encode(dict(errors=[self.format_error(parsed_error)])), + self.encode({"errors": [self.format_error(parsed_error)]}), status=e.status_code, headers=e.headers, content_type="application/json", diff --git a/graphql_server/quart/graphqlview.py b/graphql_server/quart/graphqlview.py index 7dd479f..8885e5e 100644 --- a/graphql_server/quart/graphqlview.py +++ b/graphql_server/quart/graphqlview.py @@ -57,7 +57,7 @@ class GraphQLView(View): encode = staticmethod(json_encode) def __init__(self, **kwargs): - super(GraphQLView, self).__init__() + super().__init__() for key, value in kwargs.items(): if hasattr(self, key): setattr(self, key, value) @@ -125,7 +125,7 @@ async def dispatch_request(self): *( ex if ex is not None and is_awaitable(ex) - else wrap_in_async(lambda: ex)() + else wrap_in_async(lambda x: x)(ex) for ex in execution_results ) ) @@ -136,15 +136,15 @@ async def dispatch_request(self): exec_res, is_batch=isinstance(data, list), format_error=self.format_error, - encode=partial(self.encode, pretty=pretty), # noqa + encode=partial(self.encode, pretty=pretty), ) if show_graphiql: graphiql_data = GraphiQLData( result=result, - query=getattr(all_params[0], "query"), - variables=getattr(all_params[0], "variables"), - operation_name=getattr(all_params[0], "operation_name"), + query=all_params[0].query, + variables=all_params[0].variables, + operation_name=all_params[0].operation_name, subscription_url=self.subscriptions, headers=self.headers, ) @@ -169,7 +169,7 @@ async def dispatch_request(self): except HttpQueryError as e: parsed_error = GraphQLError(e.message) return Response( - self.encode(dict(errors=[self.format_error(parsed_error)])), + self.encode({"errors": [self.format_error(parsed_error)]}), status=e.status_code, headers=e.headers, content_type="application/json", diff --git a/graphql_server/sanic/graphqlview.py b/graphql_server/sanic/graphqlview.py index 50e9922..37e0e0c 100644 --- a/graphql_server/sanic/graphqlview.py +++ b/graphql_server/sanic/graphqlview.py @@ -58,7 +58,7 @@ class GraphQLView(HTTPMethodView): encode = staticmethod(json_encode) def __init__(self, **kwargs): - super(GraphQLView, self).__init__() + super().__init__() for key, value in kwargs.items(): if hasattr(self, key): setattr(self, key, value) @@ -130,7 +130,7 @@ async def __handle_request(self, request, *args, **kwargs): *( ex if ex is not None and is_awaitable(ex) - else wrap_in_async(lambda: ex)() + else wrap_in_async(lambda x: x)(ex) for ex in execution_results ) ) @@ -141,15 +141,15 @@ async def __handle_request(self, request, *args, **kwargs): exec_res, is_batch=isinstance(data, list), format_error=self.format_error, - encode=partial(self.encode, pretty=pretty), # noqa: ignore + encode=partial(self.encode, pretty=pretty), ) if show_graphiql: graphiql_data = GraphiQLData( result=result, - query=getattr(all_params[0], "query"), - variables=getattr(all_params[0], "variables"), - operation_name=getattr(all_params[0], "operation_name"), + query=all_params[0].query, + variables=all_params[0].variables, + operation_name=all_params[0].operation_name, subscription_url=self.subscriptions, headers=self.headers, ) @@ -181,7 +181,7 @@ async def __handle_request(self, request, *args, **kwargs): except HttpQueryError as e: parsed_error = GraphQLError(e.message) return HTTPResponse( - self.encode(dict(errors=[self.format_error(parsed_error)])), + self.encode({"errors": [self.format_error(parsed_error)]}), status=e.status_code, headers=e.headers, content_type="application/json", diff --git a/graphql_server/webob/graphqlview.py b/graphql_server/webob/graphqlview.py index e3d5a42..78ff48a 100644 --- a/graphql_server/webob/graphqlview.py +++ b/graphql_server/webob/graphqlview.py @@ -52,7 +52,7 @@ class GraphQLView: encode = staticmethod(json_encode) def __init__(self, **kwargs): - super(GraphQLView, self).__init__() + super().__init__() for key, value in kwargs.items(): if hasattr(self, key): setattr(self, key, value) @@ -122,15 +122,15 @@ def dispatch_request(self, request): execution_results, is_batch=isinstance(data, list), format_error=self.format_error, - encode=partial(self.encode, pretty=pretty), # noqa + encode=partial(self.encode, pretty=pretty), ) if show_graphiql: graphiql_data = GraphiQLData( result=result, - query=getattr(all_params[0], "query"), - variables=getattr(all_params[0], "variables"), - operation_name=getattr(all_params[0], "operation_name"), + query=all_params[0].query, + variables=all_params[0].variables, + operation_name=all_params[0].operation_name, subscription_url=self.subscriptions, headers=self.headers, ) @@ -165,7 +165,7 @@ def dispatch_request(self, request): except HttpQueryError as e: parsed_error = GraphQLError(e.message) return Response( - self.encode(dict(errors=[self.format_error(parsed_error)])), + self.encode({"errors": [self.format_error(parsed_error)]}), status=e.status_code, charset=self.charset, headers=e.headers or {}, diff --git a/setup.cfg b/setup.cfg index 615a251..9888367 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,16 +1,3 @@ -[flake8] -exclude = docs -max-line-length = 88 -ignore = E203, E501, W503 - -[isort] -known_first_party=graphql_server -profile=black -multi_line_output=3 -include_trailing_comma=True -force_grid_wrap=0 -use_parentheses=True - [tool:pytest] norecursedirs = venv .venv .tox .git .cache .mypy_cache .pytest_cache markers = asyncio diff --git a/setup.py b/setup.py index ee568ab..9048304 100644 --- a/setup.py +++ b/setup.py @@ -16,11 +16,7 @@ ] dev_requires = [ - "flake8>=6,<7", - "isort>=5,<6", - "black>=23.9,<23.10", "mypy>=1.6,<1.7", - "check-manifest>=0.47,<1", ] + tests_requires install_flask_requires = [ diff --git a/tests/aiohttp/test_graphqlview.py b/tests/aiohttp/test_graphqlview.py index e5de233..3009426 100644 --- a/tests/aiohttp/test_graphqlview.py +++ b/tests/aiohttp/test_graphqlview.py @@ -179,7 +179,7 @@ async def test_allows_mutation_to_exist_within_a_get(client): async def test_allows_post_with_json_encoding(client): response = await client.post( "/graphql", - data=json.dumps(dict(query="{test}")), + data=json.dumps({"query": "{test}"}), headers={"content-type": "application/json"}, ) @@ -192,9 +192,9 @@ async def test_allows_sending_a_mutation_via_post(client): response = await client.post( "/graphql", data=json.dumps( - dict( - query="mutation TestMutation { writeTest { test } }", - ) + { + "query": "mutation TestMutation { writeTest { test } }", + } ), headers={"content-type": "application/json"}, ) @@ -222,10 +222,10 @@ async def test_supports_post_json_query_with_string_variables(client): response = await client.post( "/graphql", data=json.dumps( - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables=json.dumps({"who": "Dolly"}), - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": json.dumps({"who": "Dolly"}), + } ), headers={"content-type": "application/json"}, ) @@ -239,10 +239,10 @@ async def test_supports_post_json_query_with_json_variables(client): response = await client.post( "/graphql", data=json.dumps( - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables={"who": "Dolly"}, - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": {"who": "Dolly"}, + } ), headers={"content-type": "application/json"}, ) @@ -256,10 +256,10 @@ async def test_supports_post_url_encoded_query_with_string_variables(client): response = await client.post( "/graphql", data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables=json.dumps({"who": "Dolly"}), - ), + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": json.dumps({"who": "Dolly"}), + }, ), headers={"content-type": "application/x-www-form-urlencoded"}, ) @@ -273,9 +273,9 @@ async def test_supports_post_json_quey_with_get_variable_values(client): response = await client.post( url_string(variables=json.dumps({"who": "Dolly"})), data=json.dumps( - dict( - query="query helloWho($who: String){ test(who: $who) }", - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + } ), headers={"content-type": "application/json"}, ) @@ -289,9 +289,9 @@ async def test_post_url_encoded_query_with_get_variable_values(client): response = await client.post( url_string(variables=json.dumps({"who": "Dolly"})), data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + } ), headers={"content-type": "application/x-www-form-urlencoded"}, ) @@ -317,8 +317,8 @@ async def test_allows_post_with_operation_name(client): response = await client.post( "/graphql", data=json.dumps( - dict( - query=""" + { + "query": """ query helloYou { test(who: "You"), ...shared } query helloWorld { test(who: "World"), ...shared } query helloDolly { test(who: "Dolly"), ...shared } @@ -326,8 +326,8 @@ async def test_allows_post_with_operation_name(client): shared: test(who: "Everyone") } """, - operationName="helloWorld", - ) + "operationName": "helloWorld", + } ), headers={"content-type": "application/json"}, ) @@ -599,7 +599,7 @@ async def test_post_multipart_data(client): async def test_batch_allows_post_with_json_encoding(app, client): response = await client.post( "/graphql", - data=json.dumps([dict(id=1, query="{test}")]), + data=json.dumps([{"id": 1, "query": "{test}"}]), headers={"content-type": "application/json"}, ) @@ -614,11 +614,11 @@ async def test_batch_supports_post_json_query_with_json_variables(app, client): "/graphql", data=json.dumps( [ - dict( - id=1, - query="query helloWho($who: String){ test(who: $who) }", - variables={"who": "Dolly"}, - ) + { + "id": 1, + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": {"who": "Dolly"}, + } ] ), headers={"content-type": "application/json"}, @@ -635,9 +635,9 @@ async def test_batch_allows_post_with_operation_name(app, client): "/graphql", data=json.dumps( [ - dict( - id=1, - query=""" + { + "id": 1, + "query": """ query helloYou { test(who: "You"), ...shared } query helloWorld { test(who: "World"), ...shared } query helloDolly { test(who: "Dolly"), ...shared } @@ -645,8 +645,8 @@ async def test_batch_allows_post_with_operation_name(app, client): shared: test(who: "Everyone") } """, - operationName="helloWorld", - ) + "operationName": "helloWorld", + } ] ), headers={"content-type": "application/json"}, @@ -694,7 +694,7 @@ async def test_preflight_incorrect_request(client): async def test_custom_execution_context_class(client): response = await client.post( "/graphql", - data=json.dumps(dict(query="{test}")), + data=json.dumps({"query": "{test}"}), headers={"content-type": "application/json"}, ) diff --git a/tests/flask/test_graphqlview.py b/tests/flask/test_graphqlview.py index 34ddcb9..3a6b87c 100644 --- a/tests/flask/test_graphqlview.py +++ b/tests/flask/test_graphqlview.py @@ -191,7 +191,7 @@ def test_allows_sending_a_mutation_via_post(app, client): def test_allows_post_with_url_encoding(app, client): response = client.post( url_string(app), - data=urlencode(dict(query="{test}")), + data=urlencode({"query": "{test}"}), content_type="application/x-www-form-urlencoded", ) @@ -231,10 +231,10 @@ def test_supports_post_url_encoded_query_with_string_variables(app, client): response = client.post( url_string(app), data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables=json.dumps({"who": "Dolly"}), - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": json.dumps({"who": "Dolly"}), + } ), content_type="application/x-www-form-urlencoded", ) @@ -260,9 +260,9 @@ def test_post_url_encoded_query_with_get_variable_values(app, client): response = client.post( url_string(app, variables=json.dumps({"who": "Dolly"})), data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + } ), content_type="application/x-www-form-urlencoded", ) diff --git a/tests/quart/test_graphqlview.py b/tests/quart/test_graphqlview.py index 35a5494..17d12cc 100644 --- a/tests/quart/test_graphqlview.py +++ b/tests/quart/test_graphqlview.py @@ -245,7 +245,7 @@ async def test_allows_post_with_url_encoding(app: Quart, client: TestClientProto app, client, method="POST", - data=urlencode(dict(query="{test}")), + data=urlencode({"query": "{test}"}), headers=Headers({"Content-Type": "application/x-www-form-urlencoded"}), ) @@ -303,10 +303,10 @@ async def test_supports_post_url_encoded_query_with_string_variables( client, method="POST", data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables=json.dumps({"who": "Dolly"}), - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": json.dumps({"who": "Dolly"}), + } ), headers=Headers({"Content-Type": "application/x-www-form-urlencoded"}), ) @@ -345,9 +345,9 @@ async def test_post_url_encoded_query_with_get_variable_values( client, method="POST", data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + } ), headers=Headers({"Content-Type": "application/x-www-form-urlencoded"}), variables=json.dumps({"who": "Dolly"}), diff --git a/tests/sanic/test_graphqlview.py b/tests/sanic/test_graphqlview.py index 277eefd..24f2a92 100644 --- a/tests/sanic/test_graphqlview.py +++ b/tests/sanic/test_graphqlview.py @@ -224,10 +224,10 @@ def test_supports_post_url_encoded_query_with_string_variables(app): _, response = app.test_client.post( uri=url_string(), content=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables=json.dumps({"who": "Dolly"}), - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": json.dumps({"who": "Dolly"}), + } ), headers={"content-type": "application/x-www-form-urlencoded"}, ) @@ -253,9 +253,9 @@ def test_post_url_encoded_query_with_get_variable_values(app): _, response = app.test_client.post( uri=url_string(variables=json.dumps({"who": "Dolly"})), content=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + } ), headers={"content-type": "application/x-www-form-urlencoded"}, ) @@ -434,9 +434,9 @@ def test_handles_poorly_formed_variables(app): def test_handles_unsupported_http_methods(app): _, response = app.test_client.put(uri=url_string(query="{test}")) assert response.status == 405 - allowed_methods = set( + allowed_methods = { method.strip() for method in response.headers["Allow"].split(",") - ) + } assert allowed_methods in [{"GET", "POST"}, {"HEAD", "GET", "POST", "OPTIONS"}] assert response_json(response) == { "errors": [ diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py index 2ba2298..a0845e4 100644 --- a/tests/test_asyncio.py +++ b/tests/test_asyncio.py @@ -47,7 +47,7 @@ def test_get_responses_using_asyncio_executor(): async def get_results(): result_promises, params = run_http_query( - schema, "get", {}, dict(query=query), run_sync=False + schema, "get", {}, {"query": query}, run_sync=False ) res = [await result for result in result_promises] return res, params diff --git a/tests/test_helpers.py b/tests/test_helpers.py index ad62f62..30a0b2e 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -139,7 +139,7 @@ def test_encode_execution_results_with_format_error(): def format_error(error): return { "msg": error.message, - "loc": "{}:{}".format(error.locations[0].line, error.locations[0].column), + "loc": f"{error.locations[0].line}:{error.locations[0].column}", "pth": "/".join(error.path), } diff --git a/tests/test_query.py b/tests/test_query.py index 1ae3526..e0994db 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -39,7 +39,7 @@ def test_server_results(): def test_validate_schema(): query = "{test}" - results, params = run_http_query(invalid_schema, "get", {}, dict(query=query)) + results, params = run_http_query(invalid_schema, "get", {}, {"query": query}) assert as_dicts(results) == [ { "data": None, @@ -54,7 +54,7 @@ def test_validate_schema(): def test_allows_get_with_query_param(): query = "{test}" - results, params = run_http_query(schema, "get", {}, dict(query=query)) + results, params = run_http_query(schema, "get", {}, {"query": query}) assert as_dicts(results) == [{"data": {"test": "Hello World"}, "errors": None}] assert params == [GraphQLParams(query=query, variables=None, operation_name=None)] @@ -65,10 +65,10 @@ def test_allows_get_with_variable_values(): schema, "get", {}, - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables=json.dumps({"who": "Dolly"}), - ), + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": json.dumps({"who": "Dolly"}), + }, ) assert as_dicts(results) == [{"data": {"test": "Hello Dolly"}, "errors": None}] @@ -79,8 +79,8 @@ def test_allows_get_with_operation_name(): schema, "get", {}, - query_data=dict( - query=""" + query_data={ + "query": """ query helloYou { test(who: "You"), ...shared } query helloWorld { test(who: "World"), ...shared } query helloDolly { test(who: "Dolly"), ...shared } @@ -88,8 +88,8 @@ def test_allows_get_with_operation_name(): shared: test(who: "Everyone") } """, - operationName="helloWorld", - ), + "operationName": "helloWorld", + }, ) assert as_dicts(results) == [ @@ -102,7 +102,7 @@ def test_allows_get_with_operation_name(): def test_reports_validation_errors(): results, params = run_http_query( - schema, "get", {}, query_data=dict(query="{ test, unknownOne, unknownTwo }") + schema, "get", {}, query_data={"query": "{ test, unknownOne, unknownTwo }"} ) assert as_dicts(results) == [ @@ -134,7 +134,7 @@ def enter_field(self, node, *_args): schema, "get", {}, - query_data=dict(query="{ test }"), + query_data={"query": "{ test }"}, validation_rules=[CustomValidationRule], ) @@ -159,7 +159,7 @@ def test_reports_max_num_of_validation_errors(): schema, "get", {}, - query_data=dict(query="{ test, unknownOne, unknownTwo }"), + query_data={"query": "{ test, unknownOne, unknownTwo }"}, max_errors=1, ) @@ -207,12 +207,12 @@ def test_errors_when_missing_operation_name(): schema, "get", {}, - query_data=dict( - query=""" + query_data={ + "query": """ query TestQuery { test } mutation TestMutation { writeTest { test } } """ - ), + }, ) assert as_dicts(results) == [ @@ -237,11 +237,11 @@ def test_errors_when_sending_a_mutation_via_get(): schema, "get", {}, - query_data=dict( - query=""" + query_data={ + "query": """ mutation TestMutation { writeTest { test } } """ - ), + }, ) assert exc_info.value == HttpQueryError( @@ -256,11 +256,11 @@ def test_catching_errors_when_sending_a_mutation_via_get(): schema, "get", {}, - query_data=dict( - query=""" + query_data={ + "query": """ mutation TestMutation { writeTest { test } } """ - ), + }, catch=True, ) @@ -273,13 +273,13 @@ def test_errors_when_selecting_a_mutation_within_a_get(): schema, "get", {}, - query_data=dict( - query=""" + query_data={ + "query": """ query TestQuery { test } mutation TestMutation { writeTest { test } } """, - operationName="TestMutation", - ), + "operationName": "TestMutation", + }, ) assert exc_info.value == HttpQueryError( @@ -294,13 +294,13 @@ def test_allows_mutation_to_exist_within_a_get(): schema, "get", {}, - query_data=dict( - query=""" + query_data={ + "query": """ query TestQuery { test } mutation TestMutation { writeTest { test } } """, - operationName="TestQuery", - ), + "operationName": "TestQuery", + }, ) assert as_dicts(results) == [{"data": {"test": "Hello World"}, "errors": None}] @@ -311,16 +311,14 @@ def test_allows_sending_a_mutation_via_post(): schema, "post", {}, - query_data=dict(query="mutation TestMutation { writeTest { test } }"), + query_data={"query": "mutation TestMutation { writeTest { test } }"}, ) assert results == [({"writeTest": {"test": "Hello World"}}, None)] def test_allows_post_with_url_encoding(): - results, params = run_http_query( - schema, "post", {}, query_data=dict(query="{test}") - ) + results, params = run_http_query(schema, "post", {}, query_data={"query": "{test}"}) assert results == [({"test": "Hello World"}, None)] @@ -330,10 +328,10 @@ def test_supports_post_json_query_with_string_variables(): schema, "post", {}, - query_data=dict( - query="query helloWho($who: String){ test(who: $who) }", - variables='{"who": "Dolly"}', - ), + query_data={ + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": '{"who": "Dolly"}', + }, ) assert results == [({"test": "Hello Dolly"}, None)] @@ -357,10 +355,10 @@ def test_supports_post_url_encoded_query_with_string_variables(): schema, "post", {}, - query_data=dict( - query="query helloWho($who: String){ test(who: $who) }", - variables='{"who": "Dolly"}', - ), + query_data={ + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": '{"who": "Dolly"}', + }, ) assert results == [({"test": "Hello Dolly"}, None)] @@ -370,8 +368,8 @@ def test_supports_post_json_query_with_get_variable_values(): results, params = run_http_query( schema, "post", - data=dict(query="query helloWho($who: String){ test(who: $who) }"), - query_data=dict(variables={"who": "Dolly"}), + data={"query": "query helloWho($who: String){ test(who: $who) }"}, + query_data={"variables": {"who": "Dolly"}}, ) assert results == [({"test": "Hello Dolly"}, None)] @@ -381,8 +379,8 @@ def test_post_url_encoded_query_with_get_variable_values(): results, params = run_http_query( schema, "get", - data=dict(query="query helloWho($who: String){ test(who: $who) }"), - query_data=dict(variables='{"who": "Dolly"}'), + data={"query": "query helloWho($who: String){ test(who: $who) }"}, + query_data={"variables": '{"who": "Dolly"}'}, ) assert results == [({"test": "Hello Dolly"}, None)] @@ -392,8 +390,8 @@ def test_supports_post_raw_text_query_with_get_variable_values(): results, params = run_http_query( schema, "get", - data=dict(query="query helloWho($who: String){ test(who: $who) }"), - query_data=dict(variables='{"who": "Dolly"}'), + data={"query": "query helloWho($who: String){ test(who: $who) }"}, + query_data={"variables": '{"who": "Dolly"}'}, ) assert results == [({"test": "Hello Dolly"}, None)] @@ -403,8 +401,8 @@ def test_allows_post_with_operation_name(): results, params = run_http_query( schema, "get", - data=dict( - query=""" + data={ + "query": """ query helloYou { test(who: "You"), ...shared } query helloWorld { test(who: "World"), ...shared } query helloDolly { test(who: "Dolly"), ...shared } @@ -412,8 +410,8 @@ def test_allows_post_with_operation_name(): shared: test(who: "Everyone") } """, - operationName="helloWorld", - ), + "operationName": "helloWorld", + }, ) assert results == [({"test": "Hello World", "shared": "Hello Everyone"}, None)] @@ -423,8 +421,8 @@ def test_allows_post_with_get_operation_name(): results, params = run_http_query( schema, "get", - data=dict( - query=""" + data={ + "query": """ query helloYou { test(who: "You"), ...shared } query helloWorld { test(who: "World"), ...shared } query helloDolly { test(who: "Dolly"), ...shared } @@ -432,15 +430,15 @@ def test_allows_post_with_get_operation_name(): shared: test(who: "Everyone") } """ - ), - query_data=dict(operationName="helloWorld"), + }, + query_data={"operationName": "helloWorld"}, ) assert results == [({"test": "Hello World", "shared": "Hello Everyone"}, None)] def test_supports_pretty_printing_data(): - results, params = run_http_query(schema, "get", data=dict(query="{test}")) + results, params = run_http_query(schema, "get", data={"query": "{test}"}) result = {"data": results[0].data} assert json_encode(result, pretty=True) == ( @@ -449,14 +447,14 @@ def test_supports_pretty_printing_data(): def test_not_pretty_data_by_default(): - results, params = run_http_query(schema, "get", data=dict(query="{test}")) + results, params = run_http_query(schema, "get", data={"query": "{test}"}) result = {"data": results[0].data} assert json_encode(result) == '{"data":{"test":"Hello World"}}' def test_handles_field_errors_caught_by_graphql(): - results, params = run_http_query(schema, "get", data=dict(query="{thrower}")) + results, params = run_http_query(schema, "get", data={"query": "{thrower}"}) assert results == [ (None, [{"message": "Throws!", "locations": [(1, 2)], "path": ["thrower"]}]) @@ -467,7 +465,7 @@ def test_handles_field_errors_caught_by_graphql(): def test_handles_syntax_errors_caught_by_graphql(): - results, params = run_http_query(schema, "get", data=dict(query="syntaxerror")) + results, params = run_http_query(schema, "get", data={"query": "syntaxerror"}) assert results == [ ( @@ -491,7 +489,7 @@ def test_handles_errors_caused_by_a_lack_of_query(): def test_handles_errors_caused_by_invalid_query_type(): with raises(HttpQueryError) as exc_info: - results, params = run_http_query(schema, "get", dict(query=42)) + results, params = run_http_query(schema, "get", {"query": 42}) assert exc_info.value == HttpQueryError(400, "Unexpected query type.") @@ -525,10 +523,10 @@ def test_handles_poorly_formed_variables(): schema, "get", {}, - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables="who:You", - ), + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": "who:You", + }, ) assert exc_info.value == HttpQueryError(400, "Variables are invalid JSON.") @@ -597,7 +595,7 @@ def test_passes_request_into_request_context(): schema, "get", {}, - query_data=dict(query="{request}"), + query_data={"query": "{request}"}, context_value={"q": "testing"}, ) @@ -610,7 +608,7 @@ def __str__(self): return "CUSTOM CONTEXT" results, params = run_http_query( - schema, "get", {}, query_data=dict(query="{context}"), context_value=Context() + schema, "get", {}, query_data={"query": "{context}"}, context_value=Context() ) assert results == [({"context": "CUSTOM CONTEXT"}, None)] @@ -618,7 +616,7 @@ def __str__(self): def test_post_multipart_data(): query = "mutation TestMutation { writeTest { test } }" - results, params = run_http_query(schema, "post", {}, query_data=dict(query=query)) + results, params = run_http_query(schema, "post", {}, query_data={"query": query}) assert results == [({"writeTest": {"test": "Hello World"}}, None)] @@ -642,8 +640,8 @@ def test_batch_supports_post_json_query_with_json_variables(): def test_batch_allows_post_with_operation_name(): data = [ - dict( - query=""" + { + "query": """ query helloYou { test(who: "You"), ...shared } query helloWorld { test(who: "World"), ...shared } query helloDolly { test(who: "Dolly"), ...shared } @@ -651,8 +649,8 @@ def test_batch_allows_post_with_operation_name(): shared: test(who: "Everyone") } """, - operationName="helloWorld", - ) + "operationName": "helloWorld", + } ] data = load_json_body(json_encode(data)) results, params = run_http_query(schema, "post", data, batch_enabled=True) @@ -664,8 +662,8 @@ def test_graphiql_render_umlaut(): results, params = run_http_query( schema, "get", - data=dict(query="query helloWho($who: String){ test(who: $who) }"), - query_data=dict(variables='{"who": "Björn"}'), + data={"query": "query helloWho($who: String){ test(who: $who) }"}, + query_data={"variables": '{"who": "Björn"}'}, catch=True, ) result, status_code = encode_execution_results(results) diff --git a/tests/webob/app.py b/tests/webob/app.py index 083d179..fffbc88 100644 --- a/tests/webob/app.py +++ b/tests/webob/app.py @@ -11,7 +11,7 @@ def url_string(url="/graphql", **url_params): return f"{url}?{urlencode(url_params)}" if url_params else url -class Client(object): +class Client: def __init__(self, **kwargs): self.schema = kwargs.pop("schema", None) or Schema self.settings = kwargs.pop("settings", None) or {} diff --git a/tests/webob/test_graphiqlview.py b/tests/webob/test_graphiqlview.py index b456b60..209ae1a 100644 --- a/tests/webob/test_graphiqlview.py +++ b/tests/webob/test_graphiqlview.py @@ -5,7 +5,7 @@ @pytest.mark.parametrize( - "settings", [dict(graphiql=True), dict(graphiql=True, jinja_env=Environment())] + "settings", [{"graphiql": True}, {"graphiql": True, "jinja_env": Environment()}] ) def test_graphiql_is_enabled(client): response = client.get(url_string(query="{test}"), headers={"Accept": "text/html"}) @@ -13,7 +13,7 @@ def test_graphiql_is_enabled(client): @pytest.mark.parametrize( - "settings", [dict(graphiql=True), dict(graphiql=True, jinja_env=Environment())] + "settings", [{"graphiql": True}, {"graphiql": True, "jinja_env": Environment()}] ) def test_graphiql_simple_renderer(client): response = client.get(url_string(query="{test}"), headers={"Accept": "text/html"}) @@ -29,7 +29,7 @@ def test_graphiql_simple_renderer(client): @pytest.mark.parametrize( - "settings", [dict(graphiql=True), dict(graphiql=True, jinja_env=Environment())] + "settings", [{"graphiql": True}, {"graphiql": True, "jinja_env": Environment()}] ) def test_graphiql_html_is_not_accepted(client): response = client.get(url_string(), headers={"Accept": "application/json"}) diff --git a/tests/webob/test_graphqlview.py b/tests/webob/test_graphqlview.py index b72f12a..5acacd3 100644 --- a/tests/webob/test_graphqlview.py +++ b/tests/webob/test_graphqlview.py @@ -176,7 +176,7 @@ def test_allows_sending_a_mutation_via_post(client): def test_allows_post_with_url_encoding(client): response = client.post( url_string(), - data=urlencode(dict(query="{test}")), + data=urlencode({"query": "{test}"}), content_type="application/x-www-form-urlencoded", ) @@ -216,10 +216,10 @@ def test_supports_post_url_encoded_query_with_string_variables(client): response = client.post( url_string(), data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - variables=json.dumps({"who": "Dolly"}), - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + "variables": json.dumps({"who": "Dolly"}), + } ), content_type="application/x-www-form-urlencoded", ) @@ -245,9 +245,9 @@ def test_post_url_encoded_query_with_get_variable_values(client): response = client.post( url_string(variables=json.dumps({"who": "Dolly"})), data=urlencode( - dict( - query="query helloWho($who: String){ test(who: $who) }", - ) + { + "query": "query helloWho($who: String){ test(who: $who) }", + } ), content_type="application/x-www-form-urlencoded", ) @@ -310,7 +310,7 @@ def test_allows_post_with_get_operation_name(client): } -@pytest.mark.parametrize("settings", [dict(pretty=True)]) +@pytest.mark.parametrize("settings", [{"pretty": True}]) def test_supports_pretty_printing(client, settings): response = client.get(url_string(query="{test}")) @@ -319,7 +319,7 @@ def test_supports_pretty_printing(client, settings): ) -@pytest.mark.parametrize("settings", [dict(pretty=False)]) +@pytest.mark.parametrize("settings", [{"pretty": False}]) def test_not_pretty_by_default(client, settings): response = client.get(url_string(query="{test}")) @@ -435,7 +435,7 @@ def test_passes_request_into_request_context(client): assert response_json(response) == {"data": {"request": "testing"}} -@pytest.mark.parametrize("settings", [dict(context={"session": "CUSTOM CONTEXT"})]) +@pytest.mark.parametrize("settings", [{"context": {"session": "CUSTOM CONTEXT"}}]) def test_passes_custom_context_into_context(client, settings): response = client.get(url_string(query="{context { session request }}")) @@ -448,7 +448,7 @@ def test_passes_custom_context_into_context(client, settings): assert "request" in res["data"]["context"]["request"] -@pytest.mark.parametrize("settings", [dict(context="CUSTOM CONTEXT")]) +@pytest.mark.parametrize("settings", [{"context": "CUSTOM CONTEXT"}]) def test_context_remapped_if_not_mapping(client, settings): response = client.get(url_string(query="{context { session request }}")) @@ -465,7 +465,7 @@ class CustomContext(dict): property = "A custom property" -@pytest.mark.parametrize("settings", [dict(context=CustomContext())]) +@pytest.mark.parametrize("settings", [{"context": CustomContext()}]) def test_allow_empty_custom_context(client, settings): response = client.get(url_string(query="{context { property request }}")) @@ -504,7 +504,7 @@ def test_post_multipart_data(client): assert response_json(response) == {"data": {"writeTest": {"test": "Hello World"}}} -@pytest.mark.parametrize("settings", [dict(batch=True)]) +@pytest.mark.parametrize("settings", [{"batch": True}]) def test_batch_allows_post_with_json_encoding(client, settings): response = client.post( url_string(), @@ -524,7 +524,7 @@ def test_batch_allows_post_with_json_encoding(client, settings): ] -@pytest.mark.parametrize("settings", [dict(batch=True)]) +@pytest.mark.parametrize("settings", [{"batch": True}]) def test_batch_supports_post_json_query_with_json_variables(client, settings): response = client.post( url_string(), @@ -545,7 +545,7 @@ def test_batch_supports_post_json_query_with_json_variables(client, settings): ] -@pytest.mark.parametrize("settings", [dict(batch=True)]) +@pytest.mark.parametrize("settings", [{"batch": True}]) def test_batch_allows_post_with_operation_name(client, settings): response = client.post( url_string(), @@ -574,7 +574,7 @@ def test_batch_allows_post_with_operation_name(client, settings): @pytest.mark.parametrize( - "settings", [dict(execution_context_class=RepeatExecutionContext)] + "settings", [{"execution_context_class": RepeatExecutionContext}] ) def test_custom_execution_context_class(client): response = client.post( diff --git a/tox.ini b/tox.ini index 6627604..b44f66b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - black,flake8,import-order,mypy,manifest, + pre-commit,mypy, py{38,39,310,311} ; requires = tox-conda @@ -25,32 +25,14 @@ commands = py{38,39,310}: pytest tests {posargs} py{311}: pytest tests --cov-report=term-missing --cov=graphql_server {posargs} -[testenv:black] -basepython = python3.11 -deps = -e.[dev] -commands = - black --check graphql_server tests - -[testenv:flake8] -basepython = python3.11 -deps = -e.[dev] -commands = - flake8 setup.py graphql_server tests - -[testenv:import-order] -basepython = python3.11 -deps = -e.[dev] +[testenv:pre-commit] +skip_install = true +deps = pre-commit commands = - isort graphql_server/ tests/ + pre-commit run --all-files --show-diff-on-failure {posargs} [testenv:mypy] basepython = python3.11 deps = -e.[dev] commands = mypy graphql_server tests --ignore-missing-imports - -[testenv:manifest] -basepython = python3.11 -deps = -e.[dev] -commands = - check-manifest -v