Skip to content

Commit e49f851

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

File tree

2 files changed

+86
-72
lines changed

2 files changed

+86
-72
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

+42-29
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,30 @@ 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()
103111
raise RuntimeError(
104-
'GraphQL execution failed to complete synchronously.')
112+
"GraphQL execution failed to complete synchronously."
113+
)
105114

106115
return cast(ExecutionResult, result)
107116

108117

109118
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]:
119+
schema,
120+
source,
121+
root_value,
122+
context_value,
123+
variable_values,
124+
operation_name,
125+
field_resolver,
126+
execution_context_class,
127+
) -> MaybeAwaitable[ExecutionResult]:
118128
"""Execute a query, return asynchronously only if necessary."""
119129
# Validate Schema
120130
schema_validation_errors = validate_schema(schema)
@@ -132,6 +142,7 @@ def graphql_impl(
132142

133143
# Validate
134144
from .validation import validate
145+
135146
validation_errors = validate(schema, document)
136147
if validation_errors:
137148
return ExecutionResult(data=None, errors=validation_errors)
@@ -144,4 +155,6 @@ def graphql_impl(
144155
context_value,
145156
variable_values,
146157
operation_name,
147-
field_resolver)
158+
field_resolver,
159+
execution_context_class,
160+
)

0 commit comments

Comments
 (0)