Skip to content

Commit a56477d

Browse files
committed
Split out 'ASTValidationContext'
Replicates graphql/graphql-js@0a9a533
1 parent 27d0ce3 commit a56477d

29 files changed

+208
-136
lines changed

graphql/language/ast.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class DefinitionNode(Node):
146146
class ExecutableDefinitionNode(DefinitionNode):
147147
__slots__ = 'name', 'directives', 'variable_definitions', 'selection_set'
148148

149+
name: Optional[NameNode]
149150
directives: Optional[List['DirectiveNode']]
150151
variable_definitions: List['VariableDefinitionNode']
151152
selection_set: 'SelectionSetNode'
@@ -155,7 +156,6 @@ class OperationDefinitionNode(ExecutableDefinitionNode):
155156
__slots__ = 'operation',
156157

157158
operation: OperationType
158-
name: Optional[NameNode]
159159

160160

161161
class VariableDefinitionNode(Node):
@@ -328,7 +328,7 @@ class SchemaDefinitionNode(TypeSystemDefinitionNode):
328328
operation_types: List['OperationTypeDefinitionNode']
329329

330330

331-
class OperationTypeDefinitionNode(TypeSystemDefinitionNode):
331+
class OperationTypeDefinitionNode(Node):
332332
__slots__ = 'operation', 'type'
333333

334334
operation: OperationType

graphql/validation/rules/__init__.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,28 @@
44

55
from ...error import GraphQLError
66
from ...language.visitor import Visitor
7-
from ..validation_context import ValidationContext
7+
from ..validation_context import ASTValidationContext, ValidationContext
88

9-
__all__ = ['ValidationRule', 'RuleType']
9+
__all__ = ['ASTValidationRule', 'ValidationRule', 'RuleType']
1010

1111

12-
class ValidationRule(Visitor):
12+
class ASTValidationRule(Visitor):
1313

14-
def __init__(self, context: ValidationContext) -> None:
14+
context: ASTValidationContext
15+
16+
def __init__(self, context: ASTValidationContext) -> None:
1517
self.context = context
1618

1719
def report_error(self, error: GraphQLError):
1820
self.context.report_error(error)
1921

2022

21-
RuleType = Type[ValidationRule]
23+
class ValidationRule(ASTValidationRule):
24+
25+
context: ValidationContext
26+
27+
def __init__(self, context: ValidationContext) -> None:
28+
super().__init__(context)
29+
30+
31+
RuleType = Type[ASTValidationRule]
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
from typing import Union, cast
2+
13
from ...error import GraphQLError
24
from ...language import (
3-
FragmentDefinitionNode, OperationDefinitionNode,
4-
SchemaDefinitionNode, SchemaExtensionNode)
5-
from . import ValidationRule
5+
DirectiveDefinitionNode, DocumentNode, FragmentDefinitionNode,
6+
OperationDefinitionNode, SchemaDefinitionNode, SchemaExtensionNode,
7+
TypeDefinitionNode)
8+
from . import ASTValidationRule
69

710
__all__ = ['ExecutableDefinitionsRule', 'non_executable_definitions_message']
811

@@ -11,20 +14,22 @@ def non_executable_definitions_message(def_name: str) -> str:
1114
return f'The {def_name} definition is not executable.'
1215

1316

14-
class ExecutableDefinitionsRule(ValidationRule):
17+
class ExecutableDefinitionsRule(ASTValidationRule):
1518
"""Executable definitions
1619
1720
A GraphQL document is only valid for execution if all definitions are
1821
either operation or fragment definitions.
1922
"""
2023

21-
def enter_document(self, node, *_args):
24+
def enter_document(self, node: DocumentNode, *_args):
2225
for definition in node.definitions:
2326
if not isinstance(definition, (
2427
OperationDefinitionNode, FragmentDefinitionNode)):
2528
self.report_error(GraphQLError(
2629
non_executable_definitions_message(
2730
'schema' if isinstance(definition, (
2831
SchemaDefinitionNode, SchemaExtensionNode))
29-
else definition.name.value), [definition]))
32+
else cast(Union[
33+
DirectiveDefinitionNode, TypeDefinitionNode],
34+
definition).name.value), [definition]))
3035
return self.SKIP

graphql/validation/rules/fields_on_correct_type.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
GraphQLAbstractType, GraphQLSchema, GraphQLOutputType,
66
is_abstract_type, is_interface_type, is_object_type)
77
from ...error import GraphQLError
8+
from ...language import FieldNode
89
from ...pyutils import quoted_or_list, suggestion_list
910
from . import ValidationRule
1011

@@ -32,7 +33,7 @@ class FieldsOnCorrectTypeRule(ValidationRule):
3233
parent type, or are an allowed meta field such as __typename.
3334
"""
3435

35-
def enter_field(self, node, *_args):
36+
def enter_field(self, node: FieldNode, *_args):
3637
type_ = self.context.get_parent_type()
3738
if not type_:
3839
return

graphql/validation/rules/fragments_on_composite_types.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from ...error import GraphQLError
2-
from ...language.printer import print_ast
2+
from ...language import FragmentDefinitionNode, InlineFragmentNode, print_ast
33
from ...type import is_composite_type
44
from ...utilities import type_from_ast
55
from . import ValidationRule
@@ -29,7 +29,7 @@ class FragmentsOnCompositeTypesRule(ValidationRule):
2929
type condition must also be a composite type.
3030
"""
3131

32-
def enter_inline_fragment(self, node, *_args):
32+
def enter_inline_fragment(self, node: InlineFragmentNode, *_args):
3333
type_condition = node.type_condition
3434
if type_condition:
3535
type_ = type_from_ast(self.context.schema, type_condition)
@@ -38,7 +38,7 @@ def enter_inline_fragment(self, node, *_args):
3838
inline_fragment_on_non_composite_error_message(
3939
print_ast(type_condition)), [type_condition]))
4040

41-
def enter_fragment_definition(self, node, *_args):
41+
def enter_fragment_definition(self, node: FragmentDefinitionNode, *_args):
4242
type_condition = node.type_condition
4343
type_ = type_from_ast(self.context.schema, type_condition)
4444
if type_ and not is_composite_type(type_):

graphql/validation/rules/known_argument_names.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import List
22

33
from ...error import GraphQLError
4-
from ...language import FieldNode, DirectiveNode
4+
from ...language import ArgumentNode, FieldNode, DirectiveNode
55
from ...pyutils import quoted_or_list, suggestion_list
66
from . import ValidationRule
77

@@ -37,7 +37,8 @@ class KnownArgumentNamesRule(ValidationRule):
3737
that field.
3838
"""
3939

40-
def enter_argument(self, node, _key, _parent, _path, ancestors):
40+
def enter_argument(
41+
self, node: ArgumentNode, _key, _parent, _path, ancestors):
4142
context = self.context
4243
arg_def = context.get_argument()
4344
if not arg_def:

graphql/validation/rules/known_directives.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from typing import cast
22

33
from ...error import GraphQLError
4-
from ...language import DirectiveLocation, Node, OperationDefinitionNode
4+
from ...language import (
5+
DirectiveLocation, DirectiveNode, Node, OperationDefinitionNode)
56
from . import ValidationRule
67

78
__all__ = [
@@ -13,7 +14,7 @@ def unknown_directive_message(directive_name: str) -> str:
1314
return f"Unknown directive '{directive_name}'."
1415

1516

16-
def misplaced_directive_message(directive_name, location):
17+
def misplaced_directive_message(directive_name: str, location: str) -> str:
1718
return f"Directive '{directive_name}' may not be used on {location}."
1819

1920

@@ -24,7 +25,8 @@ class KnownDirectivesRule(ValidationRule):
2425
schema and legally positioned.
2526
"""
2627

27-
def enter_directive(self, node, _key, _parent, _path, ancestors):
28+
def enter_directive(
29+
self, node: DirectiveNode, _key, _parent, _path, ancestors):
2830
for definition in self.context.schema.directives:
2931
if definition.name == node.name.value:
3032
candidate_location = get_directive_location_for_ast_path(

graphql/validation/rules/known_fragment_names.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from ...error import GraphQLError
2+
from ...language import FragmentSpreadNode
23
from . import ValidationRule
34

45
__all__ = ['KnownFragmentNamesRule', 'unknown_fragment_message']
@@ -15,7 +16,7 @@ class KnownFragmentNamesRule(ValidationRule):
1516
refer to fragments defined in the same document.
1617
"""
1718

18-
def enter_fragment_spread(self, node, *_args):
19+
def enter_fragment_spread(self, node: FragmentSpreadNode, *_args):
1920
fragment_name = node.name.value
2021
fragment = self.context.get_fragment(fragment_name)
2122
if not fragment:

graphql/validation/rules/known_type_names.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import List
22

33
from ...error import GraphQLError
4+
from ...language import NamedTypeNode
45
from ...pyutils import suggestion_list
56
from . import ValidationRule
67

@@ -33,7 +34,7 @@ def enter_union_type_definition(self, *_args):
3334
def enter_input_object_type_definition(self, *_args):
3435
return self.SKIP
3536

36-
def enter_named_type(self, node, *_args):
37+
def enter_named_type(self, node: NamedTypeNode, *_args):
3738
schema = self.context.schema
3839
type_name = node.name.value
3940
if not schema.get_type(type_name):
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from ...language import OperationDefinitionNode
21
from ...error import GraphQLError
3-
from . import ValidationRule
2+
from ...language import DocumentNode, OperationDefinitionNode
3+
from . import ASTValidationContext, ASTValidationRule
44

55
__all__ = [
66
'LoneAnonymousOperationRule', 'anonymous_operation_not_alone_message']
@@ -10,24 +10,25 @@ def anonymous_operation_not_alone_message() -> str:
1010
return 'This anonymous operation must be the only defined operation.'
1111

1212

13-
class LoneAnonymousOperationRule(ValidationRule):
13+
class LoneAnonymousOperationRule(ASTValidationRule):
1414
"""Lone anonymous operation
1515
1616
A GraphQL document is only valid if when it contains an anonymous operation
1717
(the query short-hand) that it contains only that one operation definition.
1818
1919
"""
2020

21-
def __init__(self, context):
21+
def __init__(self, context: ASTValidationContext) -> None:
2222
super().__init__(context)
2323
self.operation_count = 0
2424

25-
def enter_document(self, node, *_args):
25+
def enter_document(self, node: DocumentNode, *_args):
2626
self.operation_count = sum(
2727
1 for definition in node.definitions
2828
if isinstance(definition, OperationDefinitionNode))
2929

30-
def enter_operation_definition(self, node, *_args):
30+
def enter_operation_definition(
31+
self, node: OperationDefinitionNode, *_args):
3132
if not node.name and self.operation_count > 1:
3233
self.report_error(GraphQLError(
3334
anonymous_operation_not_alone_message(), [node]))

0 commit comments

Comments
 (0)