Skip to content

Commit 45acfe3

Browse files
committed
merge generic types
1 parent 75b3012 commit 45acfe3

File tree

1 file changed

+127
-140
lines changed

1 file changed

+127
-140
lines changed

graphene_mongo/types.py

Lines changed: 127 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from graphene.types.utils import yank_fields_from_attrs
1010
from graphene.utils.str_converters import to_snake_case
1111

12-
from graphene_mongo import MongoengineConnectionField
1312
from .converter import convert_mongoengine_field
1413
from .registry import Registry, get_global_registry, get_inputs_registry
1514
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):
7170
return fields
7271

7372

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
125123
)
126124
mongoengine_fields = yank_fields_from_attrs(
127125
converted_fields, _as=graphene.Field
@@ -130,45 +128,46 @@ def __init_subclass_with_meta__(
130128
use_connection = any(
131129
(issubclass(interface, Node) for interface in interfaces)
132130
)
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+
)
133138

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
138143

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+
)
142147

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
172171
)
173172

174173
if not skip_registry:
@@ -177,12 +176,6 @@ def __init_subclass_with_meta__(
177176
converted_fields = construct_self_referenced_fields(
178177
self_referenced, registry
179178
)
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)
186179

187180
@classmethod
188181
def rescan_fields(cls):
@@ -200,49 +193,43 @@ def rescan_fields(cls):
200193
converted_fields, _as=graphene.Field
201194
)
202195

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

Comments
 (0)