9
9
from graphene .types .utils import yank_fields_from_attrs
10
10
from graphene .utils .str_converters import to_snake_case
11
11
12
- from graphene_mongo import MongoengineConnectionField
13
12
from .converter import convert_mongoengine_field
14
13
from .registry import Registry , get_global_registry , get_inputs_registry
15
14
from .utils import get_model_fields , is_valid_mongoengine_model , get_query_fields
@@ -71,57 +70,56 @@ def construct_self_referenced_fields(self_referenced, registry):
71
70
return fields
72
71
73
72
74
- class MongoengineObjectTypeOptions (ObjectTypeOptions ):
75
-
76
- model = None
77
- registry = None # type: Registry
78
- connection = None
79
- filter_fields = ()
80
- order_by = None
81
-
82
-
83
- class MongoengineObjectType (ObjectType ):
84
- @classmethod
85
- def __init_subclass_with_meta__ (
86
- cls ,
87
- model = None ,
88
- registry = None ,
89
- skip_registry = False ,
90
- only_fields = (),
91
- required_fields = (),
92
- exclude_fields = (),
93
- filter_fields = None ,
94
- connection = None ,
95
- connection_class = None ,
96
- use_connection = None ,
97
- connection_field_class = None ,
98
- interfaces = (),
99
- _meta = None ,
100
- order_by = None ,
101
- ** options
102
- ):
103
-
104
- assert is_valid_mongoengine_model (model ), (
105
- "The attribute model in {}.Meta must be a valid Mongoengine Model. "
106
- 'Received "{}" instead.'
107
- ).format (cls .__name__ , type (model ))
108
-
109
- if not registry :
110
- registry = get_global_registry ()
111
-
112
- assert isinstance (registry , Registry ), (
113
- "The attribute registry in {}.Meta needs to be an instance of "
114
- 'Registry, received "{}".'
115
- ).format (cls .__name__ , registry )
116
- converted_fields , self_referenced = construct_fields (
117
- model , registry , only_fields , exclude_fields
118
- )
119
- mongoengine_fields = yank_fields_from_attrs (
120
- converted_fields , _as = graphene .Field
121
- )
122
- if use_connection is None and interfaces :
123
- use_connection = any (
124
- (issubclass (interface , Node ) for interface in interfaces )
73
+ def create_graphene_generic_class (object_type , option_type ):
74
+ class MongoengineGenericObjectTypeOptions (option_type ):
75
+
76
+ model = None
77
+ registry = None # type: Registry
78
+ connection = None
79
+ filter_fields = ()
80
+ non_required_fields = ()
81
+ order_by = None
82
+
83
+ class GrapheneMongoengineGenericType (object_type ):
84
+ @classmethod
85
+ def __init_subclass_with_meta__ (
86
+ cls ,
87
+ model = None ,
88
+ registry = None ,
89
+ skip_registry = False ,
90
+ only_fields = (),
91
+ required_fields = (),
92
+ exclude_fields = (),
93
+ non_required_fields = (),
94
+ filter_fields = None ,
95
+ connection = None ,
96
+ connection_class = None ,
97
+ use_connection = None ,
98
+ connection_field_class = None ,
99
+ interfaces = (),
100
+ _meta = None ,
101
+ order_by = None ,
102
+ ** options
103
+ ):
104
+
105
+ assert is_valid_mongoengine_model (model ), (
106
+ "The attribute model in {}.Meta must be a valid Mongoengine Model. "
107
+ 'Received "{}" instead.'
108
+ ).format (cls .__name__ , type (model ))
109
+
110
+ if not registry :
111
+ # input objects shall be registred in a separated registry
112
+ if issubclass (cls , InputObjectType ):
113
+ registry = get_inputs_registry ()
114
+ else :
115
+ registry = get_global_registry ()
116
+
117
+ assert isinstance (registry , Registry ), (
118
+ "The attribute registry in {}.Meta needs to be an instance of "
119
+ 'Registry({}), received "{}".'
120
+ ).format (object_type , cls .__name__ , registry )
121
+ converted_fields , self_referenced = construct_fields (
122
+ model , registry , only_fields , exclude_fields , non_required_fields
125
123
)
126
124
mongoengine_fields = yank_fields_from_attrs (
127
125
converted_fields , _as = graphene .Field
@@ -130,45 +128,46 @@ def __init_subclass_with_meta__(
130
128
use_connection = any (
131
129
(issubclass (interface , Node ) for interface in interfaces )
132
130
)
131
+ mongoengine_fields = yank_fields_from_attrs (
132
+ converted_fields , _as = graphene .Field
133
+ )
134
+ if use_connection is None and interfaces :
135
+ use_connection = any (
136
+ (issubclass (interface , Node ) for interface in interfaces )
137
+ )
133
138
134
- if use_connection and not connection :
135
- # We create the connection automatically
136
- if not connection_class :
137
- connection_class = Connection
139
+ if use_connection and not connection :
140
+ # We create the connection automatically
141
+ if not connection_class :
142
+ connection_class = Connection
138
143
139
- connection = connection_class .create_type (
140
- "{}Connection" .format (cls .__name__ ), node = cls
141
- )
144
+ connection = connection_class .create_type (
145
+ "{}Connection" .format (cls .__name__ ), node = cls
146
+ )
142
147
143
- if _meta :
144
- assert isinstance (_meta , MongoengineObjectTypeOptions ), (
145
- "_meta must be an instance of MongoengineObjectTypeOptions, "
146
- "received {}"
147
- ).format (_meta .__class__ )
148
- else :
149
- _meta = MongoengineObjectTypeOptions (cls )
150
-
151
- _meta .model = model
152
- _meta .registry = registry
153
- _meta .fields = mongoengine_fields
154
- _meta .filter_fields = filter_fields
155
- _meta .connection = connection
156
- _meta .connection_field_class = connection_field_class
157
- # Save them for later
158
- _meta .only_fields = only_fields
159
- _meta .required_fields = required_fields
160
- _meta .exclude_fields = exclude_fields
161
- _meta .order_by = order_by
162
-
163
- super (MongoengineObjectType , cls ).__init_subclass_with_meta__ (
164
- _meta = _meta , interfaces = interfaces , ** options
165
- )
166
-
167
- if not skip_registry :
168
- registry .register (cls )
169
- # Notes: Take care list of self-reference fields.
170
- converted_fields = construct_self_referenced_fields (
171
- self_referenced , registry
148
+ if _meta :
149
+ assert isinstance (_meta , MongoengineGenericObjectTypeOptions ), (
150
+ "_meta must be an instance of MongoengineGenericObjectTypeOptions, "
151
+ "received {}"
152
+ ).format (_meta .__class__ )
153
+ else :
154
+ _meta = MongoengineGenericObjectTypeOptions (option_type )
155
+
156
+ _meta .model = model
157
+ _meta .registry = registry
158
+ _meta .fields = mongoengine_fields
159
+ _meta .filter_fields = filter_fields
160
+ _meta .connection = connection
161
+ _meta .connection_field_class = connection_field_class
162
+ # Save them for later
163
+ _meta .only_fields = only_fields
164
+ _meta .required_fields = required_fields
165
+ _meta .exclude_fields = exclude_fields
166
+ _meta .non_required_fields = non_required_fields
167
+ _meta .order_by = order_by
168
+
169
+ super (GrapheneMongoengineGenericType , cls ).__init_subclass_with_meta__ (
170
+ _meta = _meta , interfaces = interfaces , ** options
172
171
)
173
172
174
173
if not skip_registry :
@@ -177,12 +176,6 @@ def __init_subclass_with_meta__(
177
176
converted_fields = construct_self_referenced_fields (
178
177
self_referenced , registry
179
178
)
180
- if converted_fields :
181
- mongoengine_fields = yank_fields_from_attrs (
182
- converted_fields , _as = graphene .Field
183
- )
184
- cls ._meta .fields .update (mongoengine_fields )
185
- registry .register (cls )
186
179
187
180
@classmethod
188
181
def rescan_fields (cls ):
@@ -200,49 +193,43 @@ def rescan_fields(cls):
200
193
converted_fields , _as = graphene .Field
201
194
)
202
195
203
- @classmethod
204
- def rescan_fields (cls ):
205
- """Attempts to rescan fields and will insert any not converted initially"""
206
-
207
- converted_fields , self_referenced = construct_fields (
208
- cls ._meta .model ,
209
- cls ._meta .registry ,
210
- cls ._meta .only_fields ,
211
- cls ._meta .exclude_fields ,
212
- )
213
-
214
- mongoengine_fields = yank_fields_from_attrs (
215
- converted_fields , _as = graphene .Field
216
- )
217
-
218
- # The initial scan should take precedence
219
- for field in mongoengine_fields :
220
- if field not in cls ._meta .fields :
221
- cls ._meta .fields .update ({field : mongoengine_fields [field ]})
222
- # Self-referenced fields can't change between scans!
223
-
224
- @classmethod
225
- def is_type_of (cls , root , info ):
226
- if isinstance (root , cls ):
227
- return True
228
- # XXX: Take care FileField
229
- if isinstance (root , mongoengine .GridFSProxy ):
230
- return True
231
- if not is_valid_mongoengine_model (type (root )):
232
- raise Exception (('Received incompatible instance "{}".' ).format (root ))
233
- return isinstance (root , cls ._meta .model )
234
-
235
- @classmethod
236
- def get_node (cls , info , id ):
237
- required_fields = list ()
238
- for field in cls ._meta .required_fields :
239
- if field in cls ._meta .model ._fields_ordered :
240
- required_fields .append (field )
241
- for field in get_query_fields (info ):
242
- if to_snake_case (field ) in cls ._meta .model ._fields_ordered :
243
- required_fields .append (to_snake_case (field ))
244
- required_fields = list (set (required_fields ))
245
- return cls ._meta .model .objects .no_dereference ().only (* required_fields ).get (pk = id )
246
-
247
- def resolve_id (self , info ):
248
- return str (self .id )
196
+ # The initial scan should take precedence
197
+ for field in mongoengine_fields :
198
+ if field not in cls ._meta .fields :
199
+ cls ._meta .fields .update ({field : mongoengine_fields [field ]})
200
+ # Self-referenced fields can't change between scans!
201
+
202
+ @classmethod
203
+ def is_type_of (cls , root , info ):
204
+ if isinstance (root , cls ):
205
+ return True
206
+ # XXX: Take care FileField
207
+ if isinstance (root , mongoengine .GridFSProxy ):
208
+ return True
209
+ if not is_valid_mongoengine_model (type (root )):
210
+ raise Exception (('Received incompatible instance "{}".' ).format (root ))
211
+ return isinstance (root , cls ._meta .model )
212
+
213
+ @classmethod
214
+ def get_node (cls , info , id ):
215
+ required_fields = list ()
216
+ for field in cls ._meta .required_fields :
217
+ if field in cls ._meta .model ._fields_ordered :
218
+ required_fields .append (field )
219
+ for field in get_query_fields (info ):
220
+ if to_snake_case (field ) in cls ._meta .model ._fields_ordered :
221
+ required_fields .append (to_snake_case (field ))
222
+ required_fields = list (set (required_fields ))
223
+ return cls ._meta .model .objects .no_dereference ().only (* required_fields ).get (pk = id )
224
+
225
+ def resolve_id (self , info ):
226
+ return str (self .id )
227
+
228
+ return GrapheneMongoengineGenericType , MongoengineGenericObjectTypeOptions
229
+
230
+
231
+ MongoengineObjectType , MongoengineObjectTypeOptions = create_graphene_generic_class (ObjectType , ObjectTypeOptions )
232
+ MongoengineInterfaceType , MongoengineInterfaceTypeOptions = create_graphene_generic_class (Interface , InterfaceOptions )
233
+ MongoengineInputType , MongoengineInputTypeOptions = create_graphene_generic_class (InputObjectType , InputObjectTypeOptions )
234
+
235
+ GrapheneMongoengineObjectTypes = (MongoengineObjectType , MongoengineInputType , MongoengineInterfaceType )
0 commit comments