Skip to content

Commit ec998aa

Browse files
committed
Check for __typename of objects (solves #25)
1 parent 96aa6d5 commit ec998aa

File tree

3 files changed

+70
-30
lines changed

3 files changed

+70
-30
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ a query language for APIs created by Facebook.
1313
[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
1414

1515
The current version 1.0.1 of GraphQL-core-next is up-to-date with GraphQL.js version
16-
14.0.2. All parts of the API are covered by an extensive test suite of currently 1679
16+
14.0.2. All parts of the API are covered by an extensive test suite of currently 1681
1717
unit tests.
1818

1919

@@ -187,9 +187,9 @@ Design goals for the GraphQL-core-next library are:
187187
library and language versions
188188
* to be very close to the GraphQL.js reference implementation, while still using a
189189
Pythonic API and code style
190-
* making use of Python type hints, similar to how GraphQL.js makes use of Flow
191-
* using of [black](https://github.com/ambv/black) for automatic code formatting
192-
* replicate the complete Mocha-based test suite of GraphQL.js using
190+
* to make extensive use of Python type hints, similar to how GraphQL.js makes use of Flow
191+
* to use [black](https://github.com/ambv/black) for automatic code formatting
192+
* to replicate the complete Mocha-based test suite of GraphQL.js using
193193
[pytest](https://docs.pytest.org/)
194194

195195
Some restrictions (mostly in line with the design goals):

graphql/execution/execute.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,8 +1108,14 @@ def default_resolve_type_fn(
11081108
"""
11091109

11101110
# First, look for `__typename`.
1111-
if isinstance(value, dict) and isinstance(value.get("__typename"), str):
1112-
return value["__typename"]
1111+
type_name = (
1112+
value.get("__typename")
1113+
if isinstance(value, dict)
1114+
# need to de-mangle the attribute assumed to be "private" in Python
1115+
else getattr(value, f"_{value.__class__.__name__}__typename", None)
1116+
)
1117+
if isinstance(type_name, str):
1118+
return type_name
11131119

11141120
# Otherwise, test each possible type.
11151121
possible_types = info.schema.get_possible_types(abstract_type)

tests/utilities/test_build_ast_schema.py

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ def can_build_recursive_union():
369369
msg = str(exc_info.value)
370370
assert msg == "Hello types must be GraphQLObjectType objects."
371371

372-
def specifying_union_type_using_typename():
372+
def describe_specifying_union_type_using_typename():
373+
373374
schema = build_schema(
374375
"""
375376
type Query {
@@ -401,19 +402,33 @@ def specifying_union_type_using_typename():
401402
}
402403
"""
403404

404-
root = {
405-
"fruits": [
406-
{"color": "green", "__typename": "Apple"},
407-
{"length": 5, "__typename": "Banana"},
408-
]
409-
}
405+
expected = ({"fruits": [{"color": "green"}, {"length": 5}]}, None)
410406

411-
assert graphql_sync(schema, query, root) == (
412-
{"fruits": [{"color": "green"}, {"length": 5}]},
413-
None,
414-
)
407+
def using_dicts():
408+
root = {
409+
"fruits": [
410+
{"color": "green", "__typename": "Apple"},
411+
{"length": 5, "__typename": "Banana"},
412+
]
413+
}
414+
415+
assert graphql_sync(schema, query, root) == expected
416+
417+
def using_objects():
418+
class Apple:
419+
__typename = "Apple"
420+
color = "green"
421+
422+
class Banana:
423+
__typename = "Banana"
424+
length = 5
425+
426+
class Root:
427+
fruits = [Apple(), Banana()]
428+
429+
assert graphql_sync(schema, query, Root()) == expected
415430

416-
def specifying_interface_type_using_typename():
431+
def describe_specifying_interface_type_using_typename():
417432
schema = build_schema(
418433
"""
419434
type Query {
@@ -450,18 +465,7 @@ def specifying_interface_type_using_typename():
450465
}
451466
"""
452467

453-
root = {
454-
"characters": [
455-
{"name": "Han Solo", "totalCredits": 10, "__typename": "Human"},
456-
{
457-
"name": "R2-D2",
458-
"primaryFunction": "Astromech",
459-
"__typename": "Droid",
460-
},
461-
]
462-
}
463-
464-
assert graphql_sync(schema, query, root) == (
468+
expected = (
465469
{
466470
"characters": [
467471
{"name": "Han Solo", "totalCredits": 10},
@@ -471,6 +475,36 @@ def specifying_interface_type_using_typename():
471475
None,
472476
)
473477

478+
def using_dicts():
479+
root = {
480+
"characters": [
481+
{"name": "Han Solo", "totalCredits": 10, "__typename": "Human"},
482+
{
483+
"name": "R2-D2",
484+
"primaryFunction": "Astromech",
485+
"__typename": "Droid",
486+
},
487+
]
488+
}
489+
490+
assert graphql_sync(schema, query, root) == expected
491+
492+
def using_objects():
493+
class Human:
494+
__typename = "Human"
495+
name = "Han Solo"
496+
totalCredits = 10
497+
498+
class Droid:
499+
__typename = "Droid"
500+
name = "R2-D2"
501+
primaryFunction = "Astromech"
502+
503+
class Root:
504+
characters = [Human(), Droid()]
505+
506+
assert graphql_sync(schema, query, Root()) == expected
507+
474508
def custom_scalar():
475509
sdl = dedent(
476510
"""

0 commit comments

Comments
 (0)