Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use graphql-core-next instead of graphql-core + support async #17

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions graphql_server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import json
from collections import namedtuple, MutableMapping
from inspect import isawaitable
from collections import namedtuple
from collections.abc import MutableMapping

import six
from graphql import get_default_backend
from graphql import execute, parse, OperationType
from graphql.error import format_error as default_format_error
from graphql.execution import ExecutionResult

Expand All @@ -11,7 +13,7 @@
# Necessary for static type checking
if False: # flake8: noqa
from typing import List, Dict, Optional, Tuple, Any, Union, Callable, Type
from graphql import GraphQLSchema, GraphQLBackend
from graphql import GraphQLSchema


class SkipException(Exception):
Expand All @@ -22,7 +24,7 @@ class SkipException(Exception):
GraphQLResponse = namedtuple("GraphQLResponse", "result,status_code")


def run_http_query(
async def run_http_query(
schema, # type: GraphQLSchema
request_method, # type: str
data, # type: Union[Dict, List[Dict]]
Expand Down Expand Up @@ -68,7 +70,7 @@ def run_http_query(
all_params = [get_graphql_params(entry, extra_data) for entry in data]

responses = [
get_response(schema, params, catch_exc, allow_only_query, **execute_options)
await get_response(schema, params, catch_exc, allow_only_query, **execute_options)
for params in all_params
]

Expand Down Expand Up @@ -123,7 +125,7 @@ def get_graphql_params(data, query_data):
return GraphQLParams(query, load_json_variables(variables), operation_name)


def get_response(
async def get_response(
schema, # type: GraphQLSchema
params, # type: GraphQLParams
catch, # type: Type[BaseException]
Expand All @@ -132,7 +134,7 @@ def get_response(
):
# type: (...) -> Optional[ExecutionResult]
try:
execution_result = execute_graphql_request(
execution_result = await execute_graphql_request(
schema, params, allow_only_query, **kwargs
)
except catch:
Expand All @@ -149,49 +151,51 @@ def format_execution_result(
status_code = 200

if execution_result:
if execution_result.invalid:
if execution_result.errors:
status_code = 400
response = execution_result.to_dict(format_error=format_error)
response = execution_result._asdict()
else:
response = None

return GraphQLResponse(response, status_code)


def execute_graphql_request(
async def execute_graphql_request(
schema, # type: GraphQLSchema
params, # type: GraphQLParams
allow_only_query=False, # type: bool
backend=None, # type: GraphQLBackend
**kwargs # type: Dict
):
if not params.query:
raise HttpQueryError(400, "Must provide query string.")

try:
if not backend:
backend = get_default_backend()
document = backend.document_from_string(schema, params.query)
document = parse(params.query)
except Exception as e:
return ExecutionResult(errors=[e], invalid=True)
return ExecutionResult(errors=[e])

if allow_only_query:
operation_type = document.get_operation_type(params.operation_name)
if operation_type and operation_type != "query":
operations = [definition.operation for definition in document.definitions]
is_query = [op == OperationType.QUERY for op in operations]
if is_query and not all(is_query):
raise HttpQueryError(
405,
"Can only perform a {} operation from a POST request.".format(
operation_type
document.definitions[0].operation
),
headers={"Allow": "POST"},
)

try:
return document.execute(
operation_name=params.operation_name, variables=params.variables, **kwargs
result = execute(
schema, document,
operation_name=params.operation_name, variable_values=params.variables, **kwargs
)
if not isawaitable(result):
return result
return await result
except Exception as e:
return ExecutionResult(errors=[e], invalid=True)
return ExecutionResult(errors=[e])


def load_json_body(data):
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

required_packages = ["graphql-core>=2.1", "promise"]
required_packages = ["graphql-core-next>=1.0.2", "promise"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question: how did you pick this version to >= for?


setup(
name="graphql-server-core",
Expand Down Expand Up @@ -28,7 +28,7 @@
keywords="api graphql protocol rest",
packages=find_packages(exclude=["tests"]),
install_requires=required_packages,
tests_require=["pytest>=2.7.3"],
tests_require=["pytest>=4.3.1"],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see in the CR where you're changing or adding tests that use any new features of pytest; why did you bump the version here?

include_package_data=True,
zip_safe=False,
platforms="any",
Expand Down