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'])