Skip to content

Commit

Permalink
propagate explicit null args to resolvers
Browse files Browse the repository at this point in the history
  • Loading branch information
jaemk committed Sep 19, 2018
1 parent d60ff58 commit a8c8655
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 18 deletions.
33 changes: 23 additions & 10 deletions graphql/execution/tests/test_execute_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# type: ignore

from itertools import starmap, repeat
from typing import Union
from graphql.execution import execute
from graphql.language.parser import parse
from graphql.type import (
Expand Down Expand Up @@ -51,36 +53,44 @@ def test_executes_using_a_schema():
{
"id": GraphQLField(GraphQLNonNull(GraphQLString)),
"isPublished": GraphQLField(GraphQLBoolean),
"topic": GraphQLField(GraphQLString),
"author": GraphQLField(BlogAuthor),
"title": GraphQLField(GraphQLString),
"body": GraphQLField(GraphQLString),
"keywords": GraphQLField(GraphQLList(GraphQLString)),
},
)

def _resolve_article(obj, info, id, topic):
return Article(id, topic)

def _resolve_feed(*_):
return list(starmap(Article, zip(range(1, 10 + 1), repeat("food"))))

BlogQuery = GraphQLObjectType(
"Query",
{
"article": GraphQLField(
BlogArticle,
args={"id": GraphQLArgument(GraphQLID)},
resolver=lambda obj, info, **args: Article(args["id"]),
),
"feed": GraphQLField(
GraphQLList(BlogArticle),
resolver=lambda *_: map(Article, range(1, 10 + 1)),
args={
"id": GraphQLArgument(GraphQLID),
"topic": GraphQLArgument(GraphQLNonNull(GraphQLString)),
},
resolver=_resolve_article,
),
"feed": GraphQLField(GraphQLList(BlogArticle), resolver=_resolve_feed),
},
)

BlogSchema = GraphQLSchema(BlogQuery)

class Article(object):
def __init__(self, id):
# type: (int) -> None
def __init__(self, id, topic):
# type: (int, Union[str, None]) -> None
self.id = id
self.isPublished = True
self.author = Author()
self.topic = "My topic is {}".format(topic or "null")
self.title = "My Article {}".format(id)
self.body = "This is a post"
self.hidden = "This data is not exposed in the schema"
Expand All @@ -97,7 +107,7 @@ def pic(self, width, height):
@property
def recentArticle(self):
# type: () -> Article
return Article(1)
return Article(1, "food")

class Pic(object):
def __init__(self, uid, width, height):
Expand All @@ -112,7 +122,7 @@ def __init__(self, uid, width, height):
id,
title
},
article(id: "1") {
article(id: "1", topic: null) {
...articleFields,
author {
id,
Expand All @@ -132,6 +142,7 @@ def __init__(self, uid, width, height):
fragment articleFields on Article {
id,
isPublished,
topic,
title,
body,
hidden,
Expand Down Expand Up @@ -159,6 +170,7 @@ def __init__(self, uid, width, height):
"article": {
"id": "1",
"isPublished": True,
"topic": "My topic is null",
"title": "My Article 1",
"body": "This is a post",
"author": {
Expand All @@ -168,6 +180,7 @@ def __init__(self, uid, width, height):
"recentArticle": {
"id": "1",
"isPublished": True,
"topic": "My topic is food",
"title": "My Article 1",
"body": "This is a post",
"keywords": ["foo", "bar", "1", "true", None],
Expand Down
14 changes: 13 additions & 1 deletion graphql/execution/tests/test_mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,16 @@ def assert_evaluate_mutations_serially(executor=None):
},
fifth: immediatelyChangeTheNumber(newNumber: 5) {
theNumber
}
},
sixth: immediatelyChangeTheNumber(newNumber: null) {
theNumber
},
seventh: immediatelyChangeTheNumber(newNumber: 100) {
theNumber
},
eighth: immediatelyChangeTheNumber(newNumber: null) {
theNumber
},
}"""
ast = parse(doc)
result = execute(schema, ast, Root(6), operation_name="M", executor=executor)
Expand All @@ -118,6 +127,9 @@ def assert_evaluate_mutations_serially(executor=None):
"third": {"theNumber": 3},
"fourth": {"theNumber": 4},
"fifth": {"theNumber": 5},
"sixth": {"theNumber": None},
"seventh": {"theNumber": 100},
"eighth": {"theNumber": None},
}


Expand Down
21 changes: 21 additions & 0 deletions graphql/execution/tests/test_resolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,27 @@ def _test_schema(test_field):
)


def test_explicit_null_is_passed_to_resolver():
def resolver(_, __, maybe_string):
return 'maybe_string is "{}"'.format(maybe_string or "null")

schema = _test_schema(
GraphQLField(
GraphQLString,
args=OrderedDict([("maybe_string", GraphQLArgument(GraphQLString))]),
resolver=resolver,
)
)

result = graphql(schema, '{ test(maybe_string: "Cool") }')
assert not result.errors
assert result.data == {"test": 'maybe_string is "Cool"'}

result = graphql(schema, "{ test(maybe_string: null) }")
assert not result.errors
assert result.data == {"test": 'maybe_string is "null"'}


def test_default_function_accesses_properties():
# type: () -> None
schema = _test_schema(GraphQLField(GraphQLString))
Expand Down
15 changes: 8 additions & 7 deletions graphql/execution/values.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,16 @@ def get_argument_values(
continue

else:
value = value_from_ast(arg_ast.value, arg_type, variables) # type: ignore
if value is None:
arg_name = arg_def.out_name or name # type: ignore
arg_ast_value = arg_ast.value # type: ignore
value = value_from_ast(arg_ast_value, arg_type, variables) # type: ignore
if value is None and not isinstance(arg_ast_value, ast.NullValue):
if arg_def.default_value is not Undefined:
value = arg_def.default_value
result[arg_def.out_name or name] = value
result[arg_name] = arg_def.default_value
else:
result[arg_name] = None
else:
# We use out_name as the output name for the
# dict if exists
result[arg_def.out_name or name] = value
result[arg_name] = value

return result

Expand Down

0 comments on commit a8c8655

Please sign in to comment.