Skip to content

Commit c38ebb3

Browse files
committed
refactor: cleanup filter type generation
1 parent 4e34a79 commit c38ebb3

File tree

1 file changed

+47
-51
lines changed

1 file changed

+47
-51
lines changed

graphene_sqlalchemy/types.py

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import inspect
2+
import logging
23
import warnings
34
from collections import OrderedDict
45
from functools import partial
@@ -46,6 +47,8 @@
4647
if SQL_VERSION_HIGHER_EQUAL_THAN_1_4:
4748
from sqlalchemy.ext.asyncio import AsyncSession
4849

50+
logger = logging.getLogger(__name__)
51+
4952

5053
class ORMField(OrderedType):
5154
def __init__(
@@ -171,6 +174,37 @@ def filter_field_from_field(
171174
return graphene.InputField(filter_class)
172175

173176

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+
174208
def filter_field_from_type_field(
175209
field: Union[graphene.Field, graphene.Dynamic, Type[UnmountedType]],
176210
registry: Registry,
@@ -180,63 +214,25 @@ def filter_field_from_type_field(
180214
# If a custom filter type was set for this field, use it here
181215
if filter_type:
182216
return graphene.InputField(filter_type)
183-
if issubclass(type(field), graphene.Scalar):
217+
elif issubclass(type(field), graphene.Scalar):
184218
filter_class = registry.get_filter_for_scalar_type(type(field))
185219
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):
234225
if inspect.isfunction(field._type) or isinstance(field._type, partial):
235226
return Dynamic(lambda: filter_field_from_field(field, get_nullable_type(field.type), registry, model_attr))
236227
else:
237228
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
240236

241237

242238
def get_polymorphic_on(model):

0 commit comments

Comments
 (0)