Skip to content

Commit 238f0a1

Browse files
committed
Added excution_context_class for custom ExecutionContext
1 parent d3bdab4 commit 238f0a1

File tree

2 files changed

+85
-73
lines changed

2 files changed

+85
-73
lines changed

graphql/execution/execute.py

+44-43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from inspect import isawaitable
22
from typing import (
33
Any, Awaitable, Dict, Iterable, List, NamedTuple, Optional, Set, Union,
4-
Tuple, cast)
4+
Tuple, Type, cast)
55

66
from ..error import GraphQLError, INVALID, located_error
77
from ..language import (
@@ -60,48 +60,6 @@ class ExecutionResult(NamedTuple):
6060
ExecutionResult.__new__.__defaults__ = (None, None) # type: ignore
6161

6262

63-
def execute(
64-
schema: GraphQLSchema, document: DocumentNode,
65-
root_value: Any=None, context_value: Any=None,
66-
variable_values: Dict[str, Any]=None,
67-
operation_name: str=None, field_resolver: GraphQLFieldResolver=None
68-
) -> MaybeAwaitable[ExecutionResult]:
69-
"""Execute a GraphQL operation.
70-
71-
Implements the "Evaluating requests" section of the GraphQL specification.
72-
73-
Returns an ExecutionResult (if all encountered resolvers are synchronous),
74-
or a coroutine object eventually yielding an ExecutionResult.
75-
76-
If the arguments to this function do not result in a legal execution
77-
context, a GraphQLError will be thrown immediately explaining the invalid
78-
input.
79-
"""
80-
# If arguments are missing or incorrect, throw an error.
81-
assert_valid_execution_arguments(schema, document, variable_values)
82-
83-
# If a valid execution context cannot be created due to incorrect
84-
# arguments, a "Response" with only errors is returned.
85-
exe_context = ExecutionContext.build(
86-
schema, document, root_value, context_value,
87-
variable_values, operation_name, field_resolver)
88-
89-
# Return early errors if execution context failed.
90-
if isinstance(exe_context, list):
91-
return ExecutionResult(data=None, errors=exe_context)
92-
93-
# Return a possible coroutine object that will eventually yield the data
94-
# described by the "Response" section of the GraphQL specification.
95-
#
96-
# If errors are encountered while executing a GraphQL field, only that
97-
# field and its descendants will be omitted, and sibling fields will still
98-
# be executed. An execution which encounters errors will still result in a
99-
# coroutine object that can be executed without errors.
100-
101-
data = exe_context.execute_operation(exe_context.operation, root_value)
102-
return exe_context.build_response(data)
103-
104-
10563
class ExecutionContext:
10664
"""Data that must be available at all points during query execution.
10765
@@ -794,6 +752,49 @@ def collect_subfields(
794752
return sub_field_nodes
795753

796754

755+
def execute(
756+
schema: GraphQLSchema, document: DocumentNode,
757+
root_value: Any=None, context_value: Any=None,
758+
variable_values: Dict[str, Any]=None,
759+
operation_name: str=None, field_resolver: GraphQLFieldResolver=None,
760+
execution_context_class: Type[ExecutionContext]=ExecutionContext,
761+
) -> MaybeAwaitable[ExecutionResult]:
762+
"""Execute a GraphQL operation.
763+
764+
Implements the "Evaluating requests" section of the GraphQL specification.
765+
766+
Returns an ExecutionResult (if all encountered resolvers are synchronous),
767+
or a coroutine object eventually yielding an ExecutionResult.
768+
769+
If the arguments to this function do not result in a legal execution
770+
context, a GraphQLError will be thrown immediately explaining the invalid
771+
input.
772+
"""
773+
# If arguments are missing or incorrect, throw an error.
774+
assert_valid_execution_arguments(schema, document, variable_values)
775+
776+
# If a valid execution context cannot be created due to incorrect
777+
# arguments, a "Response" with only errors is returned.
778+
exe_context = execution_context_class.build(
779+
schema, document, root_value, context_value,
780+
variable_values, operation_name, field_resolver)
781+
782+
# Return early errors if execution context failed.
783+
if isinstance(exe_context, list):
784+
return ExecutionResult(data=None, errors=exe_context)
785+
786+
# Return a possible coroutine object that will eventually yield the data
787+
# described by the "Response" section of the GraphQL specification.
788+
#
789+
# If errors are encountered while executing a GraphQL field, only that
790+
# field and its descendants will be omitted, and sibling fields will still
791+
# be executed. An execution which encounters errors will still result in a
792+
# coroutine object that can be executed without errors.
793+
794+
data = exe_context.execute_operation(exe_context.operation, root_value)
795+
return exe_context.build_response(data)
796+
797+
797798
def assert_valid_execution_arguments(
798799
schema: GraphQLSchema, document: DocumentNode,
799800
raw_variable_values: Dict[str, Any]=None) -> None:

graphql/graphql.py

+41-30
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
from asyncio import ensure_future
22
from inspect import isawaitable
3-
from typing import Any, Awaitable, Callable, Dict, Union, cast
3+
from typing import Any, Awaitable, Callable, Dict, Union, Type, cast
44

55
from .error import GraphQLError
66
from .execution import execute
77
from .language import parse, Source
88
from .pyutils import MaybeAwaitable
99
from .type import GraphQLSchema, validate_schema
10-
from .execution.execute import ExecutionResult
10+
from .execution.execute import ExecutionResult, ExecutionContext
1111

12-
__all__ = ['graphql', 'graphql_sync']
12+
__all__ = ["graphql", "graphql_sync"]
1313

1414

1515
async def graphql(
16-
schema: GraphQLSchema,
17-
source: Union[str, Source],
18-
root_value: Any=None,
19-
context_value: Any=None,
20-
variable_values: Dict[str, Any]=None,
21-
operation_name: str=None,
22-
field_resolver: Callable=None) -> ExecutionResult:
16+
schema: GraphQLSchema,
17+
source: Union[str, Source],
18+
root_value: Any = None,
19+
context_value: Any = None,
20+
variable_values: Dict[str, Any] = None,
21+
operation_name: str = None,
22+
field_resolver: Callable = None,
23+
execution_context_class: Type[ExecutionContext] = ExecutionContext,
24+
) -> ExecutionResult:
2325
"""Execute a GraphQL operation asynchronously.
2426
2527
This is the primary entry point function for fulfilling GraphQL operations
@@ -65,7 +67,9 @@ async def graphql(
6567
context_value,
6668
variable_values,
6769
operation_name,
68-
field_resolver)
70+
field_resolver,
71+
execution_context_class,
72+
)
6973

7074
if isawaitable(result):
7175
return await cast(Awaitable[ExecutionResult], result)
@@ -74,13 +78,15 @@ async def graphql(
7478

7579

7680
def graphql_sync(
77-
schema: GraphQLSchema,
78-
source: Union[str, Source],
79-
root_value: Any = None,
80-
context_value: Any = None,
81-
variable_values: Dict[str, Any] = None,
82-
operation_name: str = None,
83-
field_resolver: Callable = None) -> ExecutionResult:
81+
schema: GraphQLSchema,
82+
source: Union[str, Source],
83+
root_value: Any = None,
84+
context_value: Any = None,
85+
variable_values: Dict[str, Any] = None,
86+
operation_name: str = None,
87+
field_resolver: Callable = None,
88+
execution_context_class: Type[ExecutionContext] = ExecutionContext,
89+
) -> ExecutionResult:
8490
"""Execute a GraphQL operation synchronously.
8591
8692
The graphql_sync function also fulfills GraphQL operations by parsing,
@@ -95,26 +101,28 @@ def graphql_sync(
95101
context_value,
96102
variable_values,
97103
operation_name,
98-
field_resolver)
104+
field_resolver,
105+
execution_context_class,
106+
)
99107

100108
# Assert that the execution was synchronous.
101109
if isawaitable(result):
102110
ensure_future(cast(Awaitable[ExecutionResult], result)).cancel()
103-
raise RuntimeError(
104-
'GraphQL execution failed to complete synchronously.')
111+
raise RuntimeError("GraphQL execution failed to complete synchronously.")
105112

106113
return cast(ExecutionResult, result)
107114

108115

109116
def graphql_impl(
110-
schema,
111-
source,
112-
root_value,
113-
context_value,
114-
variable_values,
115-
operation_name,
116-
field_resolver
117-
) -> MaybeAwaitable[ExecutionResult]:
117+
schema,
118+
source,
119+
root_value,
120+
context_value,
121+
variable_values,
122+
operation_name,
123+
field_resolver,
124+
execution_context_class,
125+
) -> MaybeAwaitable[ExecutionResult]:
118126
"""Execute a query, return asynchronously only if necessary."""
119127
# Validate Schema
120128
schema_validation_errors = validate_schema(schema)
@@ -132,6 +140,7 @@ def graphql_impl(
132140

133141
# Validate
134142
from .validation import validate
143+
135144
validation_errors = validate(schema, document)
136145
if validation_errors:
137146
return ExecutionResult(data=None, errors=validation_errors)
@@ -144,4 +153,6 @@ def graphql_impl(
144153
context_value,
145154
variable_values,
146155
operation_name,
147-
field_resolver)
156+
field_resolver,
157+
execution_context_class,
158+
)

0 commit comments

Comments
 (0)