Skip to content

Commit bdab43b

Browse files
committed
Avoid per-argument work when coercing literal arguments
1 parent d49dddb commit bdab43b

2 files changed

Lines changed: 27 additions & 11 deletions

File tree

‎src/graphql/execution/values.py‎

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,23 @@ def get_argument_values(
435435
return coerced_values
436436

437437

438+
def _default_value_error_handler(
439+
arg_def: GraphQLArgument | GraphQLVariableSignature,
440+
arg_name: str,
441+
node: FieldNode | DirectiveNode | FragmentSpreadNode,
442+
) -> Callable[[GraphQLError, list[str | int]], None]:
443+
"""Build the error handler for an invalid argument default value."""
444+
445+
def on_arg_default_value_error(error: GraphQLError, path: list[str | int]) -> None:
446+
msg = (
447+
f"{print_argument_or_fragment_variable(arg_def, arg_name, node)}"
448+
f" has invalid default value{print_path_list(path)}: {error.message}"
449+
)
450+
raise GraphQLError(msg, node)
451+
452+
return on_arg_default_value_error
453+
454+
438455
def coerce_argument(
439456
coerced_values: dict[str, Any],
440457
node: FieldNode | DirectiveNode | FragmentSpreadNode,
@@ -449,13 +466,6 @@ def coerce_argument(
449466
arg_type = arg_def.type
450467
out_name = getattr(arg_def, "out_name", None) or arg_name
451468

452-
def on_arg_default_value_error(error: GraphQLError, path: list[str | int]) -> None:
453-
msg = (
454-
f"{print_argument_or_fragment_variable(arg_def, arg_name, node)}"
455-
f" has invalid default value{print_path_list(path)}: {error.message}"
456-
)
457-
raise GraphQLError(msg, node)
458-
459469
if argument_node is None:
460470
if is_required_argument(arg_def):
461471
# Note: ProvidedRequiredArgumentsRule validation should catch this
@@ -470,7 +480,7 @@ def on_arg_default_value_error(error: GraphQLError, path: list[str | int]) -> No
470480
coerced_values,
471481
out_name,
472482
arg_def,
473-
on_arg_default_value_error,
483+
_default_value_error_handler(arg_def, arg_name, node),
474484
hide_suggestions,
475485
)
476486
return
@@ -495,7 +505,7 @@ def on_arg_default_value_error(error: GraphQLError, path: list[str | int]) -> No
495505
coerced_values,
496506
out_name,
497507
arg_def,
498-
on_arg_default_value_error,
508+
_default_value_error_handler(arg_def, arg_name, node),
499509
hide_suggestions,
500510
)
501511
return

‎src/graphql/utilities/coerce_input_value.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from typing import TYPE_CHECKING, Any
5+
from typing import TYPE_CHECKING, Any, cast
66

77
from ..language import (
88
ListValueNode,
@@ -30,6 +30,7 @@
3030
if TYPE_CHECKING:
3131
from ..execution.get_variable_signature import GraphQLVariableSignature
3232
from ..execution.values import FragmentVariableValues, VariableValues
33+
from ..language import ConstValueNode
3334
from ..type import GraphQLArgument, GraphQLInputField
3435

3536
__all__ = ["coerce_default_value", "coerce_input_literal", "coerce_input_value"]
@@ -320,9 +321,14 @@ def coerce_input_literal(
320321
leaf_type = assert_leaf_type(type_)
321322
try:
322323
if leaf_type.coerce_input_literal is not None:
323-
return leaf_type.coerce_input_literal(
324+
# A bare variable was handled above, so only list and object literals
325+
# can still contain variables; other literals are already constant.
326+
const_node = (
324327
replace_variables(value_node, variable_values, fragment_variable_values)
328+
if isinstance(value_node, (ListValueNode, ObjectValueNode))
329+
else cast("ConstValueNode", value_node)
325330
)
331+
return leaf_type.coerce_input_literal(const_node)
326332
return leaf_type.parse_literal(
327333
value_node, variable_values.coerced if variable_values else None
328334
)

0 commit comments

Comments
 (0)