Skip to content

Commit c49b5c9

Browse files
committed
[RFC] Make operation name optional.
Implements graphql/graphql-spec#99 Closes #6
1 parent 1df92df commit c49b5c9

File tree

3 files changed

+41
-18
lines changed

3 files changed

+41
-18
lines changed

graphql/core/execution/base.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,33 @@ def __init__(self, schema, root, document_ast, operation_name, args, request_con
3232
to execute, which we will pass throughout the other execution
3333
methods."""
3434
errors = []
35-
operations = {}
35+
operation = None
3636
fragments = {}
37-
for statement in document_ast.definitions:
38-
if isinstance(statement, ast.OperationDefinition):
39-
name = ''
40-
if statement.name:
41-
name = statement.name.value
42-
operations[name] = statement
43-
elif isinstance(statement, ast.FragmentDefinition):
44-
fragments[statement.name.value] = statement
45-
if not operation_name and len(operations) != 1:
46-
raise GraphQLError(
47-
'Must provide operation name '
48-
'if query contains multiple operations')
49-
op_name = operation_name or next(iter(operations.keys()))
50-
operation = operations.get(op_name)
37+
38+
for definition in document_ast.definitions:
39+
if isinstance(definition, ast.OperationDefinition):
40+
if not operation_name and operation:
41+
raise GraphQLError('Must provide operation name if query contains multiple operations')
42+
43+
if not operation_name or definition.name and definition.name.value == operation_name:
44+
operation = definition
45+
46+
elif isinstance(definition, ast.FragmentDefinition):
47+
fragments[definition.name.value] = definition
48+
49+
else:
50+
raise GraphQLError(
51+
u'GraphQL cannot execute a request containing a {}.'.format(definition.__class__.__name__),
52+
definition
53+
)
54+
5155
if not operation:
52-
raise GraphQLError('Unknown operation name: {}'.format(op_name))
56+
if operation_name:
57+
raise GraphQLError(u'Unknown operation named "{}".'.format(operation_name))
58+
59+
else:
60+
raise GraphQLError('Must provide an operation.')
61+
5362
variables = get_variable_values(schema, operation.variable_definitions or [], args)
5463

5564
self.schema = schema

graphql/core/language/parser.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,17 @@ def parse_operation_definition(parser):
199199
selection_set=parse_selection_set(parser),
200200
loc=loc(parser, start)
201201
)
202+
202203
operation_token = expect(parser, TokenKind.NAME)
203204
operation = operation_token.value
205+
206+
name = None
207+
if peek(parser, TokenKind.NAME):
208+
name = parse_name(parser)
209+
204210
return ast.OperationDefinition(
205211
operation=operation,
206-
name=parse_name(parser),
212+
name=name,
207213
variable_definitions=parse_variable_definitions(parser),
208214
directives=parse_directives(parser),
209215
selection_set=parse_selection_set(parser),

tests/core_language/test_parser.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def test_parse_provides_useful_errors():
4343
def test_parse_provides_useful_error_when_using_source():
4444
with raises(LanguageError) as excinfo:
4545
parse(Source('query', 'MyQuery.graphql'))
46-
assert 'Syntax Error MyQuery.graphql (1:6) Expected Name, found EOF' in str(excinfo.value)
46+
assert 'Syntax Error MyQuery.graphql (1:6) Expected {, found EOF' in str(excinfo.value)
4747

4848

4949
def test_parses_variable_inline_values():
@@ -134,6 +134,14 @@ def test_parses_kitchen_sink():
134134
parse(KITCHEN_SINK)
135135

136136

137+
def test_parses_anonymous_operations():
138+
parse('''
139+
mutation {
140+
mutationField
141+
}
142+
''')
143+
144+
137145
def test_parse_creates_ast():
138146
source = Source("""{
139147
node(id: 4) {

0 commit comments

Comments
 (0)