From c6f8c30c84f02bb63594a810b771ddb28d9a15c9 Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Wed, 8 Jun 2016 17:22:27 +0100 Subject: [PATCH 1/8] Add connection_from_list_slice support to Connection This allows to return e.g. `Connection.for_node(Node).from_list([1, 2, 3, 4], args, context, info, 5389)` to get pagination support for sliced lists. --- graphene/relay/types.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/graphene/relay/types.py b/graphene/relay/types.py index 3ab55770..a14612f2 100644 --- a/graphene/relay/types.py +++ b/graphene/relay/types.py @@ -87,12 +87,17 @@ class Connection(ObjectType): {'edge_type': edge_type, 'edges': edges}) @classmethod - def from_list(cls, iterable, args, context, info): + def from_list(cls, iterable, args, context, info, total_count=None): assert isinstance( iterable, Iterable), 'Resolved value from the connection field have to be iterable' - connection = connection_from_list( - iterable, args, connection_type=cls, - edge_type=cls.edge_type, pageinfo_type=PageInfo) + + list_slice_length = len(iterable) + list_length = total_count if total_count else list_slice_length + + connection = connection_from_list_slice( + iterable, args, connection_type=cls, + edge_type=cls.edge_type, pageinfo_type=PageInfo, + list_length=list_length, list_slice_length=list_slice_length) connection.set_connection_data(iterable) return connection From 40705d3924e11d7778d269736a786f2782703306 Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Wed, 8 Jun 2016 17:30:30 +0100 Subject: [PATCH 2/8] Fix import --- graphene/relay/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene/relay/types.py b/graphene/relay/types.py index a14612f2..db4ea8e6 100644 --- a/graphene/relay/types.py +++ b/graphene/relay/types.py @@ -5,7 +5,7 @@ from functools import wraps import six -from graphql_relay.connection.arrayconnection import connection_from_list +from graphql_relay.connection.arrayconnection import connection_from_list_slice from graphql_relay.node.node import to_global_id from ..core.classtypes import InputObjectType, Interface, Mutation, ObjectType From 6734a603f2039ed1c7eadc7f768d97307c08276c Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Wed, 8 Jun 2016 17:37:03 +0100 Subject: [PATCH 3/8] Added test for sliced list support --- graphene/relay/tests/test_query.py | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/graphene/relay/tests/test_query.py b/graphene/relay/tests/test_query.py index 08e57226..1a898a15 100644 --- a/graphene/relay/tests/test_query.py +++ b/graphene/relay/tests/test_query.py @@ -40,6 +40,8 @@ class Query(graphene.ObjectType): context_nodes = relay.ConnectionField( MyNode, connection_type=MyConnection, customArg=graphene.String()) + sliced_nodes = relay.ConnectionField(MyNode) + def resolve_all_my_nodes(self, args, info): custom_arg = args.get('customArg') assert custom_arg == "1" @@ -51,6 +53,11 @@ class Query(graphene.ObjectType): assert custom_arg == "1" return [MyNode(name='my')] + def resolve_sliced_nodes(self, args, info): + sliced_list = [MyNode(name='my1'), MyNode(name='my2'), MyNode(name='my3')] + total_count = 10 + return Connection.for_node(MyNode).from_list(sliced_list, args, None, info, total_count) + schema.query = Query @@ -135,6 +142,47 @@ def test_connectionfield_context_query(): assert result.data == expected +def test_slice_connectionfield_query(): + query = ''' + query RebelsShipsQuery { + slicedNodes (first: 3) { + edges { + node { + name + } + }, + myCustomField + pageInfo { + hasNextPage + } + } + } + ''' + expected = { + 'slicedNodes': { + 'edges': [{ + 'node': { + 'name': 'my1' + } + },{ + 'node': { + 'name': 'my2' + } + },{ + 'node': { + 'name': 'my3' + } + }], + 'pageInfo': { + 'hasNextPage': True, + } + } + } + result = schema.execute(query) + assert not result.errors + assert result.data == expected + + @pytest.mark.parametrize('specialness,value', [(True, '!!!'), (False, '???')]) def test_get_node_info(specialness, value): query = ''' From b0ec253c2238cf203878e97f9c72dd5a8d92f7de Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Wed, 8 Jun 2016 17:37:37 +0100 Subject: [PATCH 4/8] fixed linting --- graphene/relay/types.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphene/relay/types.py b/graphene/relay/types.py index db4ea8e6..ced0140c 100644 --- a/graphene/relay/types.py +++ b/graphene/relay/types.py @@ -90,12 +90,12 @@ class Connection(ObjectType): def from_list(cls, iterable, args, context, info, total_count=None): assert isinstance( iterable, Iterable), 'Resolved value from the connection field have to be iterable' - + list_slice_length = len(iterable) list_length = total_count if total_count else list_slice_length - + connection = connection_from_list_slice( - iterable, args, connection_type=cls, + iterable, args, connection_type=cls, edge_type=cls.edge_type, pageinfo_type=PageInfo, list_length=list_length, list_slice_length=list_slice_length) connection.set_connection_data(iterable) From 7424e6eabc57faa3a933895b052e0ba71a3e1b73 Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Wed, 8 Jun 2016 17:45:50 +0100 Subject: [PATCH 5/8] Fix test --- graphene/relay/tests/test_query.py | 1 - 1 file changed, 1 deletion(-) diff --git a/graphene/relay/tests/test_query.py b/graphene/relay/tests/test_query.py index 1a898a15..0fea74c5 100644 --- a/graphene/relay/tests/test_query.py +++ b/graphene/relay/tests/test_query.py @@ -151,7 +151,6 @@ def test_slice_connectionfield_query(): name } }, - myCustomField pageInfo { hasNextPage } From 2a99904101e8f316facc96b878a487877ccb18b8 Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Wed, 8 Jun 2016 17:49:15 +0100 Subject: [PATCH 6/8] Update test_query.py --- graphene/relay/tests/test_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphene/relay/tests/test_query.py b/graphene/relay/tests/test_query.py index 0fea74c5..0fe1e48b 100644 --- a/graphene/relay/tests/test_query.py +++ b/graphene/relay/tests/test_query.py @@ -56,7 +56,7 @@ class Query(graphene.ObjectType): def resolve_sliced_nodes(self, args, info): sliced_list = [MyNode(name='my1'), MyNode(name='my2'), MyNode(name='my3')] total_count = 10 - return Connection.for_node(MyNode).from_list(sliced_list, args, None, info, total_count) + return relay.Connection.for_node(MyNode).from_list(sliced_list, args, None, info, total_count) schema.query = Query From 6f8b03d2d8c64dea184a80adcfb15f2c10243302 Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Mon, 13 Jun 2016 15:39:12 +0100 Subject: [PATCH 7/8] Fixed tests. --- graphene/relay/fields.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/graphene/relay/fields.py b/graphene/relay/fields.py index e79b9592..7f556575 100644 --- a/graphene/relay/fields.py +++ b/graphene/relay/fields.py @@ -29,7 +29,7 @@ class ConnectionField(Field): @with_context def resolver(self, instance, args, context, info): schema = info.schema.graphene_schema - connection_type = self.get_type(schema) + connection_type_for_node = self.get_type(schema) resolver = super(ConnectionField, self).resolver if has_context(resolver): @@ -37,17 +37,18 @@ class ConnectionField(Field): else: resolved = super(ConnectionField, self).resolver(instance, args, info) - if isinstance(resolved, connection_type): + if isinstance(resolved, self.connection_type): return resolved - return self.from_list(connection_type, resolved, args, context, info) + + return self.from_list(connection_type_for_node, resolved, args, context, info) def from_list(self, connection_type, resolved, args, context, info): return connection_type.from_list(resolved, args, context, info) def get_connection_type(self, node): connection_type = self.connection_type or node.get_connection_type() - edge_type = self.get_edge_type(node) - return connection_type.for_node(node, edge_type=edge_type) + self.connection_type = connection_type + return connection_type.for_node(node) def get_edge_type(self, node): edge_type = self.edge_type or node.get_edge_type() @@ -59,9 +60,9 @@ class ConnectionField(Field): node = schema.objecttype(type) assert is_node(node), 'Only nodes have connections.' schema.register(node) - connection_type = self.get_connection_type(node) + connection_type_for_node = self.get_connection_type(node) - return connection_type + return connection_type_for_node class NodeField(Field): From a821f19fcc6ac4a833cb932be0eea7a33e65f158 Mon Sep 17 00:00:00 2001 From: Markus Padourek Date: Mon, 13 Jun 2016 15:46:38 +0100 Subject: [PATCH 8/8] Fixed linting. --- graphene/relay/tests/test_query.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphene/relay/tests/test_query.py b/graphene/relay/tests/test_query.py index 0fe1e48b..d982aa8d 100644 --- a/graphene/relay/tests/test_query.py +++ b/graphene/relay/tests/test_query.py @@ -163,11 +163,11 @@ def test_slice_connectionfield_query(): 'node': { 'name': 'my1' } - },{ + }, { 'node': { 'name': 'my2' } - },{ + }, { 'node': { 'name': 'my3' }