Skip to content

Commit f2567ab

Browse files
committed
[RFC] Allow directives on variable definitions
Replicates graphql/graphql-js@1d7efa9
1 parent c585e34 commit f2567ab

File tree

14 files changed

+45
-12
lines changed

14 files changed

+45
-12
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ a query language for APIs created by Facebook.
1313

1414
The current version 1.0.0rc2 of GraphQL-core-next is up-to-date with GraphQL.js
1515
version 14.0.0rc2. All parts of the API are covered by an extensive test
16-
suite of currently 1547 unit tests.
16+
suite of currently 1549 unit tests.
1717

1818

1919
## Documentation

graphql/language/ast.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,12 @@ class OperationDefinitionNode(ExecutableDefinitionNode):
159159

160160

161161
class VariableDefinitionNode(Node):
162-
__slots__ = 'variable', 'type', 'default_value'
162+
__slots__ = 'variable', 'type', 'default_value', 'directives'
163163

164164
variable: 'VariableNode'
165165
type: 'TypeNode'
166166
default_value: Optional['ValueNode']
167+
directives: Optional[List['DirectiveNode']]
167168

168169

169170
class SelectionSetNode(Node):

graphql/language/directive_locations.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class DirectiveLocation(Enum):
1313
FIELD = 'field'
1414
FRAGMENT_DEFINITION = 'fragment definition'
1515
FRAGMENT_SPREAD = 'fragment spread'
16+
VARIABLE_DEFINITION = 'variable definition'
1617
INLINE_FRAGMENT = 'inline fragment'
1718

1819
# Type System Definitions

graphql/language/parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,14 @@ def parse_variable_definitions(lexer: Lexer) -> List[VariableDefinitionNode]:
169169

170170

171171
def parse_variable_definition(lexer: Lexer) -> VariableDefinitionNode:
172-
"""VariableDefinition: Variable: Type DefaultValue?"""
172+
"""VariableDefinition: Variable: Type DefaultValue? Directives[Const]?"""
173173
start = lexer.token
174174
return VariableDefinitionNode(
175175
variable=parse_variable(lexer),
176176
type=expect(lexer, TokenKind.COLON) and parse_type_reference(lexer),
177177
default_value=parse_value_literal(lexer, True)
178178
if skip(lexer, TokenKind.EQUALS) else None,
179+
directives=parse_directives(lexer, True),
179180
loc=loc(lexer, start))
180181

181182

graphql/language/printer.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ def leave_operation_definition(self, node, *_args):
5050
) else selection_set
5151

5252
def leave_variable_definition(self, node, *_args):
53-
return f"{node.variable}: {node.type}{wrap(' = ', node.default_value)}"
53+
return (f"{node.variable}: {node.type}"
54+
f"{wrap(' = ', node.default_value)}"
55+
f"{wrap(' ', ' '.join(node.directives))}")
5456

5557
def leave_selection_set(self, node, *_args):
5658
return block(node.selections)

graphql/language/visitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
'document': ('definitions',),
2828
'operation_definition': (
2929
'name', 'variable_definitions', 'directives', 'selection_set'),
30-
'variable_definition': ('variable', 'type', 'default_value'),
30+
'variable_definition': ('variable', 'type', 'default_value', 'directives'),
3131
'variable': ('name',),
3232
'selection_set': ('selections',),
3333
'field': ('alias', 'name', 'arguments', 'directives', 'selection_set'),

graphql/type/introspection.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ def print_value(value: Any, type_: GraphQLInputType) -> str:
106106
'INLINE_FRAGMENT': GraphQLEnumValue(
107107
DirectiveLocation.INLINE_FRAGMENT,
108108
description='Location adjacent to an inline fragment.'),
109+
'VARIABLE_DEFINITION': GraphQLEnumValue(
110+
DirectiveLocation.VARIABLE_DEFINITION,
111+
description='Location adjacent to a variable definition.'),
109112
'SCHEMA': GraphQLEnumValue(
110113
DirectiveLocation.SCHEMA,
111114
description='Location adjacent to a schema definition.'),

graphql/validation/rules/known_directives.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def enter_directive(
6969
'fragment_spread': DirectiveLocation.FRAGMENT_SPREAD,
7070
'inline_fragment': DirectiveLocation.INLINE_FRAGMENT,
7171
'fragment_definition': DirectiveLocation.FRAGMENT_DEFINITION,
72+
'variable_definition': DirectiveLocation.VARIABLE_DEFINITION,
7273
'schema_definition': DirectiveLocation.SCHEMA,
7374
'schema_extension': DirectiveLocation.SCHEMA,
7475
'scalar_type_definition': DirectiveLocation.SCALAR,

tests/language/test_parser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ def parses_constant_default_values():
8282
'query Foo($x: Complex = { a: { b: [ $var ] } }) { field }',
8383
'Unexpected $', (1, 37))
8484

85+
def parses_variable_definition_directives():
86+
parse('query Foo($x: Boolean = false @bar) { field }')
87+
8588
def does_not_accept_fragments_named_on():
8689
assert_syntax_error(
8790
'fragment on on on { on }', "Unexpected Name 'on'", (1, 10))

tests/language/test_printer.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ def correctly_prints_query_operation_with_artifacts():
4848
}
4949
""")
5050

51+
def correcty_prints_query_operation_with_variable_directive():
52+
query_ast_with_variable_directive = parse(
53+
'query ($foo: TestType = {a: 123}'
54+
' @testDirective(if: true) @test) { id }')
55+
assert print_ast(query_ast_with_variable_directive) == dedent("""
56+
query ($foo: TestType = {a: 123} @testDirective(if: true) @test) {
57+
id
58+
}
59+
""")
60+
5161
def correctly_prints_mutation_operation_with_artifacts():
5262
mutation_ast_with_artifacts = parse(
5363
'mutation ($foo: TestType) @testDirective { id, name }')

0 commit comments

Comments
 (0)