From 1afcdb03e00e733cee91ae604ddf81f122990d38 Mon Sep 17 00:00:00 2001 From: James <33908344+allen-munsch@users.noreply.github.com> Date: Thu, 26 Sep 2019 12:54:40 -0500 Subject: [PATCH 1/6] Add a helpful message to when a global_id fails to parse. --- graphene/relay/node.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/graphene/relay/node.py b/graphene/relay/node.py index 1a5c5bdb3..1564ce908 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -91,9 +91,13 @@ def get_node_from_global_id(cls, info, global_id, only_type=None): try: _type, _id = cls.from_global_id(global_id) graphene_type = info.schema.get_type(_type).graphene_type - except Exception: - return None - + except Exception as e: + raise Exception( + "Unable call from_global_id, is the id base64 encoding of 'TypeName:id': {} Exception: {}".format( + str(global_id), + str(e) + ) + ) if only_type: assert graphene_type == only_type, ("Must receive a {} id.").format( only_type._meta.name From 4f1144c543d01f48d52eb1d6ef782a58c621738a Mon Sep 17 00:00:00 2001 From: James <33908344+allen-munsch@users.noreply.github.com> Date: Thu, 26 Sep 2019 13:18:14 -0500 Subject: [PATCH 2/6] Update test_node to have errors on test_node_query_incorrect_id --- graphene/relay/tests/test_node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene/relay/tests/test_node.py b/graphene/relay/tests/test_node.py index 62fd31a3e..279b930ea 100644 --- a/graphene/relay/tests/test_node.py +++ b/graphene/relay/tests/test_node.py @@ -90,7 +90,7 @@ def test_node_query_incorrect_id(): executed = schema.execute( '{ node(id:"%s") { ... on MyNode { name } } }' % "something:2" ) - assert not executed.errors + assert executed.errors assert executed.data == {"node": None} From 68cdddd0b03241228f89c87e1ac610820f1a4a8d Mon Sep 17 00:00:00 2001 From: James <33908344+allen-munsch@users.noreply.github.com> Date: Thu, 26 Sep 2019 13:25:15 -0500 Subject: [PATCH 3/6] Black the node.py file --- graphene/relay/node.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/graphene/relay/node.py b/graphene/relay/node.py index 1564ce908..6b7b6af84 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -1,3 +1,4 @@ +from collections import OrderedDict from functools import partial from inspect import isclass @@ -61,7 +62,14 @@ def __init__(self, node, type=False, **kwargs): ) def get_resolver(self, parent_resolver): - return partial(self.node_type.node_resolver, get_type(self.field_type)) + def return_partial(*args, **kwargs): + print("\n\nDebugging get_resolver: ") + print(parent_resolver, args, kwargs) + return partial(self.node_type.node_resolver, get_type(self.field_type))( + *args, **kwargs + ) + + return return_partial class AbstractNode(Interface): @@ -71,7 +79,9 @@ class Meta: @classmethod def __init_subclass_with_meta__(cls, **options): _meta = InterfaceOptions(cls) - _meta.fields = {"id": GlobalID(cls, description="The ID of the object")} + _meta.fields = OrderedDict( + id=GlobalID(cls, description="The ID of the object.") + ) super(AbstractNode, cls).__init_subclass_with_meta__(_meta=_meta, **options) @@ -92,12 +102,8 @@ def get_node_from_global_id(cls, info, global_id, only_type=None): _type, _id = cls.from_global_id(global_id) graphene_type = info.schema.get_type(_type).graphene_type except Exception as e: - raise Exception( - "Unable call from_global_id, is the id base64 encoding of 'TypeName:id': {} Exception: {}".format( - str(global_id), - str(e) - ) - ) + print(e) + raise if only_type: assert graphene_type == only_type, ("Must receive a {} id.").format( only_type._meta.name From ce48acb710d1da35797334ddd9446d0bae5fcd62 Mon Sep 17 00:00:00 2001 From: James <33908344+allen-munsch@users.noreply.github.com> Date: Thu, 26 Sep 2019 13:28:40 -0500 Subject: [PATCH 4/6] Remove func wrapper used in debugging get_resolver partial --- graphene/relay/node.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/graphene/relay/node.py b/graphene/relay/node.py index 6b7b6af84..c84b479c3 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -1,4 +1,3 @@ -from collections import OrderedDict from functools import partial from inspect import isclass @@ -62,14 +61,7 @@ def __init__(self, node, type=False, **kwargs): ) def get_resolver(self, parent_resolver): - def return_partial(*args, **kwargs): - print("\n\nDebugging get_resolver: ") - print(parent_resolver, args, kwargs) - return partial(self.node_type.node_resolver, get_type(self.field_type))( - *args, **kwargs - ) - - return return_partial + return partial(self.node_type.node_resolver, get_type(self.field_type)) class AbstractNode(Interface): @@ -79,9 +71,7 @@ class Meta: @classmethod def __init_subclass_with_meta__(cls, **options): _meta = InterfaceOptions(cls) - _meta.fields = OrderedDict( - id=GlobalID(cls, description="The ID of the object.") - ) + _meta.fields = {"id": GlobalID(cls, description="The ID of the object")} super(AbstractNode, cls).__init_subclass_with_meta__(_meta=_meta, **options) @@ -102,8 +92,11 @@ def get_node_from_global_id(cls, info, global_id, only_type=None): _type, _id = cls.from_global_id(global_id) graphene_type = info.schema.get_type(_type).graphene_type except Exception as e: - print(e) - raise + raise Exception( + "Unable call from_global_id, is the id base64 encoding of 'TypeName:id': {} Exception: {}".format( + str(global_id), str(e) + ) + ) if only_type: assert graphene_type == only_type, ("Must receive a {} id.").format( only_type._meta.name From 989c3ef175034cee1caa3895384308d857d26cee Mon Sep 17 00:00:00 2001 From: James <33908344+allen-munsch@users.noreply.github.com> Date: Thu, 12 Dec 2019 10:43:56 -0600 Subject: [PATCH 5/6] Update node.py --- graphene/relay/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene/relay/node.py b/graphene/relay/node.py index c84b479c3..571f8b5c2 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -93,7 +93,7 @@ def get_node_from_global_id(cls, info, global_id, only_type=None): graphene_type = info.schema.get_type(_type).graphene_type except Exception as e: raise Exception( - "Unable call from_global_id, is the id base64 encoding of 'TypeName:id': {} Exception: {}".format( + "Unable to call from_global_id, is the id a base64 encoding of 'TypeName:id': {} Exception: {}".format( str(global_id), str(e) ) ) From ba33ab059de8a20d7a4050b71cc17ae613e4b05f Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Sat, 8 Feb 2020 11:45:58 +0000 Subject: [PATCH 6/6] Expand error messages --- graphene/relay/node.py | 24 ++++++++++++++++++++---- graphene/relay/tests/test_node.py | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/graphene/relay/node.py b/graphene/relay/node.py index 571f8b5c2..f8927ab76 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -90,13 +90,25 @@ def node_resolver(cls, only_type, root, info, id): def get_node_from_global_id(cls, info, global_id, only_type=None): try: _type, _id = cls.from_global_id(global_id) - graphene_type = info.schema.get_type(_type).graphene_type except Exception as e: raise Exception( - "Unable to call from_global_id, is the id a base64 encoding of 'TypeName:id': {} Exception: {}".format( - str(global_id), str(e) + ( + 'Unable to parse global ID "{global_id}". ' + 'Make sure it is a base64 encoded string in the format: "TypeName:id". ' + "Exception message: {exception}".format( + global_id=global_id, exception=str(e) + ) ) ) + + graphene_type = info.schema.get_type(_type) + if graphene_type is None: + raise Exception( + 'Relay Node "{_type}" not found in schema'.format(_type=_type) + ) + + graphene_type = graphene_type.graphene_type + if only_type: assert graphene_type == only_type, ("Must receive a {} id.").format( only_type._meta.name @@ -104,7 +116,11 @@ def get_node_from_global_id(cls, info, global_id, only_type=None): # We make sure the ObjectType implements the "Node" interface if cls not in graphene_type._meta.interfaces: - return None + raise Exception( + 'ObjectType "{_type}" does not implement the "{cls}" interface.'.format( + _type=_type, cls=cls + ) + ) get_node = getattr(graphene_type, "get_node", None) if get_node: diff --git a/graphene/relay/tests/test_node.py b/graphene/relay/tests/test_node.py index 279b930ea..de1802e90 100644 --- a/graphene/relay/tests/test_node.py +++ b/graphene/relay/tests/test_node.py @@ -1,3 +1,4 @@ +import re from graphql_relay import to_global_id from graphql.pyutils import dedent @@ -83,6 +84,20 @@ def test_node_requesting_non_node(): executed = schema.execute( '{ node(id:"%s") { __typename } } ' % Node.to_global_id("RootQuery", 1) ) + assert executed.errors + assert re.match( + r"ObjectType .* does not implement the .* interface.", + executed.errors[0].message, + ) + assert executed.data == {"node": None} + + +def test_node_requesting_unknown_type(): + executed = schema.execute( + '{ node(id:"%s") { __typename } } ' % Node.to_global_id("UnknownType", 1) + ) + assert executed.errors + assert re.match(r"Relay Node .* not found in schema", executed.errors[0].message) assert executed.data == {"node": None} @@ -91,6 +106,7 @@ def test_node_query_incorrect_id(): '{ node(id:"%s") { ... on MyNode { name } } }' % "something:2" ) assert executed.errors + assert re.match(r"Unable to parse global ID .*", executed.errors[0].message) assert executed.data == {"node": None}