Skip to content

Commit ceafd3b

Browse files
committed
perf: allow skipping of field plan generation
Replicates graphql/graphql-js@6d777e6
1 parent 7073a05 commit ceafd3b

File tree

6 files changed

+310
-198
lines changed

6 files changed

+310
-198
lines changed

docs/conf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
"GraphQLTypeResolver",
173173
"GraphQLWrappedResult",
174174
"GroupedFieldSet",
175+
"IncrementalContext",
175176
"IncrementalDataRecord",
176177
"IncrementalResult",
177178
"Middleware",
@@ -188,7 +189,10 @@
188189
"enum.Enum",
189190
"graphql.execution.build_field_plan.FieldGroup",
190191
"graphql.execution.build_field_plan.FieldPlan",
192+
"graphql.execution.collect_fields.CollectedFields",
191193
"graphql.execution.collect_fields.DeferUsage",
194+
"graphql.execution.collect_fields.FieldDetails",
195+
"graphql.execution.execute.IncrementalContext",
192196
"graphql.execution.execute.StreamArguments",
193197
"graphql.execution.execute.SubFieldPlan",
194198
"graphql.execution.execute.StreamUsage",
@@ -224,7 +228,7 @@
224228
"graphql.validation.rules.provided_required_arguments.ProvidedRequiredArgumentsOnDirectivesRule",
225229
}
226230

227-
ignore_references.update(__builtins__.keys())
231+
ignore_references.update(__builtins__)
228232

229233

230234
def on_missing_reference(app, env, node, contnode):

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ disallow_untyped_defs = false
276276
# silence pyright since we're using mypy already
277277
reportArgumentType = false
278278
reportIncompatibleVariableOverride = false
279+
reportInvalidTypeForm = false
279280
reportMissingModuleSource = false
280281
reportMissingTypeArgument = false
281282
reportReturnType = false

src/graphql/execution/build_field_plan.py

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@
22

33
from __future__ import annotations
44

5-
import sys
6-
from typing import TYPE_CHECKING, Dict, NamedTuple
5+
from typing import NamedTuple
76

87
from ..pyutils import RefMap, RefSet
9-
from .collect_fields import DeferUsage, FieldDetails
10-
11-
if TYPE_CHECKING:
12-
from ..language import FieldNode
8+
from .collect_fields import DeferUsage, FieldGroup, GroupedFieldSet
139

1410
try:
1511
from typing import TypeAlias
@@ -18,7 +14,6 @@
1814

1915
__all__ = [
2016
"DeferUsageSet",
21-
"FieldGroup",
2217
"FieldPlan",
2318
"GroupedFieldSet",
2419
"build_field_plan",
@@ -28,23 +23,6 @@
2823
DeferUsageSet: TypeAlias = RefSet[DeferUsage]
2924

3025

31-
class FieldGroup(NamedTuple):
32-
"""A group of fields with defer usages."""
33-
34-
fields: list[FieldDetails]
35-
defer_usages: DeferUsageSet | None = None
36-
37-
def to_nodes(self) -> list[FieldNode]:
38-
"""Return the field nodes in this group."""
39-
return [field_details.node for field_details in self.fields]
40-
41-
42-
if sys.version_info < (3, 9):
43-
GroupedFieldSet: TypeAlias = Dict[str, FieldGroup]
44-
else: # Python >= 3.9
45-
GroupedFieldSet: TypeAlias = dict[str, FieldGroup]
46-
47-
4826
class FieldPlan(NamedTuple):
4927
"""A plan for executing fields."""
5028

@@ -53,7 +31,7 @@ class FieldPlan(NamedTuple):
5331

5432

5533
def build_field_plan(
56-
fields: dict[str, list[FieldDetails]],
34+
original_grouped_field_set: GroupedFieldSet,
5735
parent_defer_usages: DeferUsageSet | None = None,
5836
) -> FieldPlan:
5937
"""Build a plan for executing fields."""
@@ -64,12 +42,12 @@ def build_field_plan(
6442

6543
new_grouped_field_sets: RefMap[DeferUsageSet, GroupedFieldSet] = RefMap()
6644

67-
map_: dict[str, tuple[DeferUsageSet, list[FieldDetails]]] = {}
45+
map_: dict[str, tuple[DeferUsageSet, FieldGroup]] = {}
6846

69-
for response_key, field_details_list in fields.items():
47+
for response_key, field_group in original_grouped_field_set.items():
7048
defer_usage_set: RefSet[DeferUsage] = RefSet()
7149
in_original_result = False
72-
for field_details in field_details_list:
50+
for field_details in field_group:
7351
defer_usage = field_details.defer_usage
7452
if defer_usage is None:
7553
in_original_result = True
@@ -85,15 +63,11 @@ def build_field_plan(
8563
ancestor in defer_usage_set for ancestor in defer_usage.ancestors
8664
)
8765
}
88-
map_[response_key] = (defer_usage_set, field_details_list)
66+
map_[response_key] = (defer_usage_set, field_group)
8967

90-
for response_key, [defer_usage_set, field_details_list] in map_.items():
68+
for response_key, [defer_usage_set, field_group] in map_.items():
9169
if defer_usage_set == parent_defer_usages:
92-
field_group = grouped_field_set.get(response_key)
93-
if field_group is None: # pragma: no cover else
94-
field_group = FieldGroup([], defer_usage_set)
95-
grouped_field_set[response_key] = field_group
96-
field_group.fields.extend(field_details_list)
70+
grouped_field_set[response_key] = field_group
9771
continue
9872

9973
for (
@@ -107,10 +81,6 @@ def build_field_plan(
10781
new_grouped_field_set = {}
10882
new_grouped_field_sets[defer_usage_set] = new_grouped_field_set
10983

110-
field_group = new_grouped_field_set.get(response_key)
111-
if field_group is None: # pragma: no cover else
112-
field_group = FieldGroup([], defer_usage_set)
113-
new_grouped_field_set[response_key] = field_group
114-
field_group.fields.extend(field_details_list)
84+
new_grouped_field_set[response_key] = field_group
11585

11686
return FieldPlan(grouped_field_set, new_grouped_field_sets)

src/graphql/execution/collect_fields.py

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

33
from __future__ import annotations
44

5+
import sys
56
from collections import defaultdict
67
from typing import Any, NamedTuple
78

@@ -25,11 +26,18 @@
2526
from ..utilities.type_from_ast import type_from_ast
2627
from .values import get_directive_values
2728

29+
try:
30+
from typing import TypeAlias
31+
except ImportError: # Python < 3.10
32+
from typing_extensions import TypeAlias
33+
2834
__all__ = [
2935
"CollectFieldsContext",
3036
"CollectedFields",
3137
"DeferUsage",
3238
"FieldDetails",
39+
"FieldGroup",
40+
"GroupedFieldSet",
3341
"collect_fields",
3442
"collect_subfields",
3543
]
@@ -59,6 +67,16 @@ class FieldDetails(NamedTuple):
5967
defer_usage: DeferUsage | None
6068

6169

70+
if sys.version_info < (3, 9):
71+
from typing import Dict, List
72+
73+
FieldGroup: TypeAlias = List[FieldDetails]
74+
GroupedFieldSet: TypeAlias = Dict[str, FieldGroup]
75+
else: # Python >= 3.9
76+
FieldGroup: TypeAlias = list[FieldDetails]
77+
GroupedFieldSet: TypeAlias = dict[str, FieldGroup]
78+
79+
6280
class CollectFieldsContext(NamedTuple):
6381
"""Context for collecting fields."""
6482

@@ -73,7 +91,7 @@ class CollectFieldsContext(NamedTuple):
7391
class CollectedFields(NamedTuple):
7492
"""Collected fields with new defer usages."""
7593

76-
fields: dict[str, list[FieldDetails]]
94+
grouped_field_set: GroupedFieldSet
7795
new_defer_usages: list[DeferUsage]
7896

7997

@@ -117,7 +135,7 @@ def collect_subfields(
117135
variable_values: dict[str, Any],
118136
operation: OperationDefinitionNode,
119137
return_type: GraphQLObjectType,
120-
field_details: list[FieldDetails],
138+
field_group: FieldGroup,
121139
) -> CollectedFields:
122140
"""Collect subfields.
123141
@@ -141,7 +159,7 @@ def collect_subfields(
141159
sub_grouped_field_set: dict[str, list[FieldDetails]] = defaultdict(list)
142160
new_defer_usages: list[DeferUsage] = []
143161

144-
for field_detail in field_details:
162+
for field_detail in field_group:
145163
node = field_detail.node
146164
if node.selection_set:
147165
collect_fields_impl(

0 commit comments

Comments
 (0)