1
1
import inspect
2
+ import logging
2
3
import warnings
3
4
from collections import OrderedDict
4
5
from functools import partial
46
47
if SQL_VERSION_HIGHER_EQUAL_THAN_1_4 :
47
48
from sqlalchemy .ext .asyncio import AsyncSession
48
49
50
+ logger = logging .getLogger (__name__ )
51
+
49
52
50
53
class ORMField (OrderedType ):
51
54
def __init__ (
@@ -171,6 +174,37 @@ def filter_field_from_field(
171
174
return graphene .InputField (filter_class )
172
175
173
176
177
+ def resolve_dynamic_relationship_filter (
178
+ field : graphene .Dynamic ,
179
+ registry : Registry ,
180
+ model_attr : Any ,
181
+ ) -> Optional [Union [graphene .InputField , graphene .Dynamic ]]:
182
+ # Resolve Dynamic Type
183
+ type_ = get_nullable_type (field .get_type ())
184
+ from graphene_sqlalchemy import SQLAlchemyConnectionField
185
+
186
+ # Connections always result in list filters
187
+ if isinstance (type_ , SQLAlchemyConnectionField ):
188
+ inner_type = get_nullable_type (type_ .type .Edge .node ._type )
189
+ reg_res = get_or_create_relationship_filter (inner_type , registry )
190
+ # Field relationships can either be a list or a single object
191
+ elif isinstance (type_ , Field ):
192
+ if isinstance (type_ .type , graphene .List ):
193
+ inner_type = get_nullable_type (type_ .type .of_type )
194
+ reg_res = get_or_create_relationship_filter (inner_type , registry )
195
+ else :
196
+ reg_res = registry .get_filter_for_base_type (type_ .type )
197
+ else :
198
+ # Other dynamic type constellation are not yet supported,
199
+ # please open an issue with reproduction if you need them
200
+ reg_res = None
201
+
202
+ if not reg_res :
203
+ return None
204
+
205
+ return graphene .InputField (reg_res )
206
+
207
+
174
208
def filter_field_from_type_field (
175
209
field : Union [graphene .Field , graphene .Dynamic , Type [UnmountedType ]],
176
210
registry : Registry ,
@@ -180,63 +214,25 @@ def filter_field_from_type_field(
180
214
# If a custom filter type was set for this field, use it here
181
215
if filter_type :
182
216
return graphene .InputField (filter_type )
183
- if issubclass (type (field ), graphene .Scalar ):
217
+ elif issubclass (type (field ), graphene .Scalar ):
184
218
filter_class = registry .get_filter_for_scalar_type (type (field ))
185
219
return graphene .InputField (filter_class )
186
- # If the field is Dynamic, we don't know its type yet and can't select the right filter
187
- if isinstance (field , graphene .Dynamic ):
188
-
189
- def resolve_dynamic ():
190
- # Resolve Dynamic Type
191
- type_ = get_nullable_type (field .get_type ())
192
- from graphene_sqlalchemy import SQLAlchemyConnectionField
193
-
194
- from .fields import UnsortedSQLAlchemyConnectionField
195
-
196
- if isinstance (type_ , SQLAlchemyConnectionField ) or isinstance (
197
- type_ , UnsortedSQLAlchemyConnectionField
198
- ):
199
- inner_type = get_nullable_type (type_ .type .Edge .node ._type )
200
- reg_res = get_or_create_relationship_filter (inner_type , registry )
201
- if not reg_res :
202
- print ("filter class was none!!!" )
203
- print (type_ )
204
- return graphene .InputField (reg_res )
205
- elif isinstance (type_ , Field ):
206
- if isinstance (type_ .type , graphene .List ):
207
- inner_type = get_nullable_type (type_ .type .of_type )
208
- reg_res = get_or_create_relationship_filter (inner_type , registry )
209
- if not reg_res :
210
- print ("filter class was none!!!" )
211
- print (type_ )
212
- return graphene .InputField (reg_res )
213
- reg_res = registry .get_filter_for_base_type (type_ .type )
214
-
215
- return graphene .InputField (reg_res )
216
- else :
217
- warnings .warn (f"Unexpected Dynamic Type: { type_ } " ) # Investigate
218
- # raise Exception(f"Unexpected Dynamic Type: {type_}")
219
-
220
- return Dynamic (resolve_dynamic )
221
-
222
- if isinstance (field , graphene .List ):
223
- print ("Got list" )
224
- return
225
- # if isinstance(field._type, types.FunctionType):
226
- # print("got field with function type")
227
- # return
228
- if isinstance (field ._type , graphene .Dynamic ):
229
- return
230
- if isinstance (field ._type , graphene .List ):
231
- print ("got field with list type" )
232
- return
233
- if isinstance (field , graphene .Field ):
220
+ # If the generated field is Dynamic, it is always a relationship
221
+ # (due to graphene-sqlalchemy's conversion mechanism).
222
+ elif isinstance (field , graphene .Dynamic ):
223
+ return Dynamic (partial (resolve_dynamic_relationship_filter , field , registry , model_attr ))
224
+ elif isinstance (field , graphene .Field ):
234
225
if inspect .isfunction (field ._type ) or isinstance (field ._type , partial ):
235
226
return Dynamic (lambda : filter_field_from_field (field , get_nullable_type (field .type ), registry , model_attr ))
236
227
else :
237
228
return filter_field_from_field (field , get_nullable_type (field .type ), registry , model_attr )
238
-
239
- raise Exception (f"Expected a graphene.Field or graphene.Dynamic, but got: { field } " )
229
+ # Unsupported but theoretically possible cases, please drop us an issue with reproduction if you need them
230
+ elif isinstance (field , graphene .List ) or isinstance (field ._type , graphene .List ):
231
+ # Pure lists are not yet supported
232
+ pass
233
+ elif isinstance (field ._type , graphene .Dynamic ):
234
+ # Fields with nested dynamic Dynamic are not yet supported
235
+ pass
240
236
241
237
242
238
def get_polymorphic_on (model ):
0 commit comments