1
1
import inspect
2
+ import six
2
3
import warnings
3
4
from collections import Iterable
4
5
from functools import wraps
5
6
6
7
from graphql_relay .connection .arrayconnection import connection_from_list
7
8
from graphql_relay .node .node import to_global_id
8
9
9
- from ..core .types import (Boolean , Field , InputObjectType , Interface , List ,
10
- Mutation , ObjectType , String )
10
+ from ..core .classtypes import InputObjectType , Interface , Mutation , ObjectType
11
+ from ..core .classtypes .mutation import MutationMeta
12
+ from ..core .classtypes .interface import InterfaceMeta
13
+ from ..core .types import Boolean , Field , List , String
11
14
from ..core .types .argument import ArgumentsGroup
12
15
from ..core .types .definitions import NonNull
13
16
from ..utils import memoize
@@ -83,33 +86,43 @@ def get_connection_data(self):
83
86
return self ._connection_data
84
87
85
88
86
- class BaseNode (object ):
89
+ class NodeMeta (InterfaceMeta ):
90
+ def construct_get_node (cls ):
91
+ get_node = getattr (cls , 'get_node' , None )
92
+ assert get_node , 'get_node classmethod not found in %s Node' % cls
93
+ assert callable (get_node ), 'get_node have to be callable'
94
+ args = 3
95
+ if isinstance (get_node , staticmethod ):
96
+ args -= 1
87
97
88
- @classmethod
89
- def _prepare_class (cls ):
90
- from graphene .relay .utils import is_node
91
- if is_node (cls ):
92
- get_node = getattr (cls , 'get_node' )
93
- assert get_node , 'get_node classmethod not found in %s Node' % cls
94
- assert callable (get_node ), 'get_node have to be callable'
95
- args = 3
96
- if isinstance (get_node , staticmethod ):
97
- args -= 1
98
-
99
- get_node_num_args = len (inspect .getargspec (get_node ).args )
100
- if get_node_num_args < args :
101
- warnings .warn ("get_node will receive also the info arg"
102
- " in future versions of graphene" .format (cls .__name__ ),
103
- FutureWarning )
104
-
105
- @staticmethod
106
- @wraps (get_node )
107
- def wrapped_node (* node_args ):
108
- if len (node_args ) < args :
109
- node_args += (None , )
110
- return get_node (* node_args [:- 1 ])
111
-
112
- setattr (cls , 'get_node' , wrapped_node )
98
+ get_node_num_args = len (inspect .getargspec (get_node ).args )
99
+ if get_node_num_args < args :
100
+ warnings .warn ("get_node will receive also the info arg"
101
+ " in future versions of graphene" .format (cls .__name__ ),
102
+ FutureWarning )
103
+
104
+ @staticmethod
105
+ @wraps (get_node )
106
+ def wrapped_node (* node_args ):
107
+ if len (node_args ) < args :
108
+ node_args += (None , )
109
+ return get_node (* node_args [:- 1 ])
110
+
111
+ setattr (cls , 'get_node' , wrapped_node )
112
+
113
+ def construct (cls , * args , ** kwargs ):
114
+ cls = super (NodeMeta , cls ).construct (* args , ** kwargs )
115
+ if not cls ._meta .abstract :
116
+ cls .construct_get_node ()
117
+ return cls
118
+
119
+
120
+ class Node (six .with_metaclass (NodeMeta , Interface )):
121
+ '''An object with an ID'''
122
+ id = GlobalIDField ()
123
+
124
+ class Meta :
125
+ abstract = True
113
126
114
127
def to_global_id (self ):
115
128
type_name = self ._meta .type_name
@@ -127,27 +140,31 @@ def get_edge_type(cls):
127
140
return cls .edge_type
128
141
129
142
130
- class Node (BaseNode , Interface ):
131
- '''An object with an ID'''
132
- id = GlobalIDField ()
133
-
134
-
135
143
class MutationInputType (InputObjectType ):
136
144
client_mutation_id = String (required = True )
137
145
138
146
139
- class ClientIDMutation (Mutation ):
140
- client_mutation_id = String (required = True )
147
+ class RelayMutationMeta (MutationMeta ):
148
+ def construct (cls , * args , ** kwargs ):
149
+ cls = super (RelayMutationMeta , cls ).construct (* args , ** kwargs )
150
+ if not cls ._meta .abstract :
151
+ assert hasattr (
152
+ cls , 'mutate_and_get_payload' ), 'You have to implement mutate_and_get_payload'
153
+ return cls
141
154
142
- @classmethod
143
- def _construct_arguments (cls , items ):
144
- assert hasattr (
145
- cls , 'mutate_and_get_payload' ), 'You have to implement mutate_and_get_payload'
155
+ def construct_arguments (cls , items ):
146
156
new_input_type = type ('{}Input' .format (
147
157
cls ._meta .type_name ), (MutationInputType , ), items )
148
158
cls .add_to_class ('input_type' , new_input_type )
149
159
return ArgumentsGroup (input = NonNull (new_input_type ))
150
160
161
+
162
+ class ClientIDMutation (six .with_metaclass (RelayMutationMeta , Mutation )):
163
+ client_mutation_id = String (required = True )
164
+
165
+ class Meta :
166
+ abstract = True
167
+
151
168
@classmethod
152
169
def mutate (cls , instance , args , info ):
153
170
input = args .get ('input' )
0 commit comments