From 7af41373a75f89ed6bb7c324c0a8773cedd6643f Mon Sep 17 00:00:00 2001 From: Amit Saha <amitsaha.in@gmail.com> Date: Fri, 20 Nov 2015 11:19:22 +1100 Subject: [PATCH 01/10] Example of querying a Python object --- examples/field_example.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 examples/field_example.py diff --git a/examples/field_example.py b/examples/field_example.py new file mode 100644 index 00000000..f9218d0e --- /dev/null +++ b/examples/field_example.py @@ -0,0 +1,30 @@ +import graphene + +class Person(graphene.Interface): + name = graphene.String() + age = graphene.ID() + +class Patron(Person): + id = graphene.ID() + +class Query(graphene.ObjectType): + + patron = graphene.Field(Patron) + + def resolve_patron(self, args, info): + return Patron(id=1, name='Demo') + +schema = graphene.Schema(query=Query) +query = ''' + query something{ + patron { + id + name + } +} +''' +result = schema.execute(query) +# Print the result +print result.data['patron'] + + From 932e3d8b00768b1b3c103d3d44f714db5bb3a3e6 Mon Sep 17 00:00:00 2001 From: Amit Saha <amitsaha.in@gmail.com> Date: Fri, 20 Nov 2015 11:47:10 +1100 Subject: [PATCH 02/10] Fix flake8 issues in field example --- examples/field_example.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/field_example.py b/examples/field_example.py index f9218d0e..f5ddada9 100644 --- a/examples/field_example.py +++ b/examples/field_example.py @@ -1,12 +1,15 @@ import graphene + class Person(graphene.Interface): name = graphene.String() age = graphene.ID() + class Patron(Person): id = graphene.ID() + class Query(graphene.ObjectType): patron = graphene.Field(Patron) @@ -26,5 +29,3 @@ query = ''' result = schema.execute(query) # Print the result print result.data['patron'] - - From 295fba37d16abfa437ef6886d93613258196d411 Mon Sep 17 00:00:00 2001 From: Amit Saha <amitsaha.in@gmail.com> Date: Fri, 20 Nov 2015 11:55:32 +1100 Subject: [PATCH 03/10] field example: use print() to keep Python 3 flake 8 happy --- examples/field_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/field_example.py b/examples/field_example.py index f5ddada9..cc2d3eef 100644 --- a/examples/field_example.py +++ b/examples/field_example.py @@ -28,4 +28,4 @@ query = ''' ''' result = schema.execute(query) # Print the result -print result.data['patron'] +print(result.data['patron']) From bb170f1ca116fb9d5ac8be2bc4ff5e2830bd9909 Mon Sep 17 00:00:00 2001 From: Syrus Akbary <me@syrusakbary.com> Date: Thu, 19 Nov 2015 19:15:49 -0800 Subject: [PATCH 04/10] Updated version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6b0d1458..97657e41 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ class PyTest(TestCommand): setup( name='graphene', - version='0.4.0.1', + version='0.4.1', description='Graphene: Python DSL for GraphQL', long_description=open('README.rst').read(), From f69665dcd86e89fd0aad447ac95af1891afc06b0 Mon Sep 17 00:00:00 2001 From: Syrus Akbary <me@syrusakbary.com> Date: Thu, 19 Nov 2015 19:17:02 -0800 Subject: [PATCH 05/10] Flake8 improvements and README update --- README.rst | 4 +++- graphene/contrib/django/tests/test_types.py | 2 +- graphene/relay/tests/test_types.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index b8afcf8d..ea5e2635 100644 --- a/README.rst +++ b/README.rst @@ -12,7 +12,9 @@ easily. `Django <http://github.com/graphql-python/swapi-graphene>`__ implementation -*What is supported in this Python version?* **Everything**: Interfaces, ObjectTypes, Scalars, Unions and Relay (Nodes, Connections and Mutations), in addition to queries, mutations and subscriptions. +*What is supported in this Python version?* **Everything**: Interfaces, +ObjectTypes, Scalars, Unions and Relay (Nodes, Connections), in addition +to queries, mutations and subscriptions. Installation ------------ diff --git a/graphene/contrib/django/tests/test_types.py b/graphene/contrib/django/tests/test_types.py index 0e8eaa11..7f9dd35a 100644 --- a/graphene/contrib/django/tests/test_types.py +++ b/graphene/contrib/django/tests/test_types.py @@ -1,6 +1,6 @@ -from pytest import raises from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType from mock import patch +from pytest import raises from graphene import Schema from graphene.contrib.django.types import DjangoInterface, DjangoNode diff --git a/graphene/relay/tests/test_types.py b/graphene/relay/tests/test_types.py index 1f3c56bf..dd731c40 100644 --- a/graphene/relay/tests/test_types.py +++ b/graphene/relay/tests/test_types.py @@ -1,5 +1,5 @@ -from pytest import raises from graphql.core.type import GraphQLList +from pytest import raises import graphene from graphene import relay From d6a5269f0b3f0b4a1d4653f43c40ebca19828164 Mon Sep 17 00:00:00 2001 From: Syrus Akbary <me@syrusakbary.com> Date: Thu, 19 Nov 2015 19:50:39 -0800 Subject: [PATCH 06/10] Added support for old behavior of get_node --- graphene/contrib/django/tests/test_types.py | 2 +- graphene/contrib/django/types.py | 2 +- graphene/relay/tests/test_types.py | 24 ++++++++++++++++++++- graphene/relay/types.py | 24 +++++++++++++++++++-- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/graphene/contrib/django/tests/test_types.py b/graphene/contrib/django/tests/test_types.py index 7f9dd35a..5d7f582e 100644 --- a/graphene/contrib/django/tests/test_types.py +++ b/graphene/contrib/django/tests/test_types.py @@ -36,7 +36,7 @@ def test_django_interface(): @patch('graphene.contrib.django.tests.models.Article.objects.get', return_value=Article(id=1)) def test_django_get_node(get): - human = Human.get_node(1) + human = Human.get_node(1, None) get.assert_called_with(id=1) assert human.id == 1 diff --git a/graphene/contrib/django/types.py b/graphene/contrib/django/types.py index 7b223294..430b410d 100644 --- a/graphene/contrib/django/types.py +++ b/graphene/contrib/django/types.py @@ -67,7 +67,7 @@ class DjangoNode(BaseNode, DjangoInterface): id = GlobalIDField() @classmethod - def get_node(cls, id): + def get_node(cls, id, info=None): try: instance = cls._meta.model.objects.get(id=id) return cls(instance) diff --git a/graphene/relay/tests/test_types.py b/graphene/relay/tests/test_types.py index dd731c40..d9f64c00 100644 --- a/graphene/relay/tests/test_types.py +++ b/graphene/relay/tests/test_types.py @@ -11,10 +11,32 @@ class OtherNode(relay.Node): name = graphene.String() @classmethod - def get_node(cls, id): + def get_node(cls, id, info): pass +def test_works_old_get_node(): + class Part(relay.Node): + x = graphene.String() + + @classmethod + def get_node(cls, id): + return id + + assert Part.get_node(1) == 1 + + +def test_works_old_static_get_node(): + class Part(relay.Node): + x = graphene.String() + + @staticmethod + def get_node(id): + return id + + assert Part.get_node(1) == 1 + + def test_field_no_contributed_raises_error(): with raises(Exception) as excinfo: class Part(relay.Node): diff --git a/graphene/relay/types.py b/graphene/relay/types.py index 08df4869..8e86f362 100644 --- a/graphene/relay/types.py +++ b/graphene/relay/types.py @@ -1,3 +1,5 @@ +import warnings +from functools import wraps from graphql_relay.node.node import to_global_id from ..core.types import (Boolean, Field, InputObjectType, Interface, List, @@ -73,8 +75,26 @@ class BaseNode(object): def _prepare_class(cls): from graphene.relay.utils import is_node if is_node(cls): - assert hasattr( - cls, 'get_node'), 'get_node classmethod not found in %s Node' % cls + get_node = getattr(cls, 'get_node') + assert get_node, 'get_node classmethod not found in %s Node' % cls + assert callable(get_node), 'get_node have to be callable' + args = 3 + if isinstance(get_node, staticmethod): + args -= 1 + + if get_node.func_code.co_argcount < args: + warnings.warn("get_node will receive also the info arg" + " in future versions of graphene".format(cls.__name__), + FutureWarning) + + @staticmethod + @wraps(get_node) + def wrapped_node(*node_args): + if len(node_args) < args: + node_args += (None, ) + return get_node(*node_args[:-1]) + + setattr(cls, 'get_node', wrapped_node) def to_global_id(self): type_name = self._meta.type_name From 0d4164648fc3af8ed6358570e665f9b1cd636cb5 Mon Sep 17 00:00:00 2001 From: Syrus Akbary <me@syrusakbary.com> Date: Thu, 19 Nov 2015 20:00:10 -0800 Subject: [PATCH 07/10] Fixed instance getter using _root. --- graphene/contrib/django/types.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/graphene/contrib/django/types.py b/graphene/contrib/django/types.py index 430b410d..f17893f0 100644 --- a/graphene/contrib/django/types.py +++ b/graphene/contrib/django/types.py @@ -49,6 +49,14 @@ class InstanceObjectType(BaseObjectType): )) super(InstanceObjectType, self).__init__(_root=_root) + @property + def instance(self): + return self._root + + @instance.setter + def instance(self, value): + self._root = value + def __getattr__(self, attr): return getattr(self._root, attr) From d50fb33660c515dbc371817ea3be1f282a715b2b Mon Sep 17 00:00:00 2001 From: Syrus Akbary <me@syrusakbary.com> Date: Thu, 19 Nov 2015 20:13:41 -0800 Subject: [PATCH 08/10] Fixed arg count compatibility in Python3 --- graphene/relay/types.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/graphene/relay/types.py b/graphene/relay/types.py index 8e86f362..a803d2f3 100644 --- a/graphene/relay/types.py +++ b/graphene/relay/types.py @@ -1,3 +1,4 @@ +import inspect import warnings from functools import wraps from graphql_relay.node.node import to_global_id @@ -82,7 +83,8 @@ class BaseNode(object): if isinstance(get_node, staticmethod): args -= 1 - if get_node.func_code.co_argcount < args: + get_node_num_args = len(inspect.getargspec(get_node).args) + if get_node_num_args < args: warnings.warn("get_node will receive also the info arg" " in future versions of graphene".format(cls.__name__), FutureWarning) From 6c7cb4040798fc0d6d76f38c2af3e5d157198a1a Mon Sep 17 00:00:00 2001 From: Syrus Akbary <me@syrusakbary.com> Date: Thu, 19 Nov 2015 20:14:49 -0800 Subject: [PATCH 09/10] Updated version with bugfixes --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 97657e41..100e2321 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ class PyTest(TestCommand): setup( name='graphene', - version='0.4.1', + version='0.4.1.1', description='Graphene: Python DSL for GraphQL', long_description=open('README.rst').read(), From f3f210b523f1733e48bb6316ecbb15e198dd503c Mon Sep 17 00:00:00 2001 From: Amit Saha <amitsaha.in@gmail.com> Date: Fri, 20 Nov 2015 16:25:18 +1100 Subject: [PATCH 10/10] Modify the field example to remove the use of interface --- examples/field_example.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/field_example.py b/examples/field_example.py index cc2d3eef..be41969d 100644 --- a/examples/field_example.py +++ b/examples/field_example.py @@ -1,15 +1,12 @@ import graphene -class Person(graphene.Interface): +class Patron(graphene.ObjectType): + id = graphene.ID() name = graphene.String() age = graphene.ID() -class Patron(Person): - id = graphene.ID() - - class Query(graphene.ObjectType): patron = graphene.Field(Patron) @@ -27,5 +24,4 @@ query = ''' } ''' result = schema.execute(query) -# Print the result print(result.data['patron'])