9856 cleanup

This commit is contained in:
Arthur 2024-03-13 14:21:02 -07:00
parent 9c53f76d9e
commit da0c23bc0c

View File

@ -12,19 +12,32 @@ from utilities.filters import *
def autotype_decorator(filterset): def autotype_decorator(filterset):
"""
Decorator used to auto creates a dataclass used by Strawberry based on a filterset.
Must go after the Strawberry decorator as follows:
def show_field(field_type, fieldname, v, cls): @strawberry_django.filter(models.Example, lookups=True)
print(f"cls: {cls}") @autotype_decorator(filtersets.ExampleFilterSet)
print(f"{fieldname}: {v}") class ExampleFilter(BaseFilterMixin):
print(field_type) pass
print("")
def create_attribute_and_function(cls, fieldname, attr_type, create_function): The Filter itself must be derived from BaseFilterMixin. For items listed in meta.fields
of the filterset, usually just a type specifier is generated, so for
`fields = [created, ]` the dataclass would be:
class ExampleFilter(BaseFilterMixin):
created: auto
For other filter fields a function needs to be created for Strawberry with the
naming convention `filter_{fieldname}` which is auto detected and called by
Strawberry, this function uses the filterset to handle the query.
"""
def create_attribute_and_function(cls, fieldname, attr_type, should_create_function):
if fieldname not in cls.__annotations__ and attr_type: if fieldname not in cls.__annotations__ and attr_type:
cls.__annotations__[fieldname] = attr_type cls.__annotations__[fieldname] = attr_type
fname = f"filter_{fieldname}" fname = f"filter_{fieldname}"
if create_function and not hasattr(cls, fname): if should_create_function and not hasattr(cls, fname):
filter_by_filterset = getattr(cls, 'filter_by_filterset') filter_by_filterset = getattr(cls, 'filter_by_filterset')
setattr(cls, fname, partialmethod(filter_by_filterset, key=fieldname)) setattr(cls, fname, partialmethod(filter_by_filterset, key=fieldname))
@ -33,138 +46,141 @@ def autotype_decorator(filterset):
fields = filterset.get_fields() fields = filterset.get_fields()
model = filterset._meta.model model = filterset._meta.model
for fieldname in fields.keys(): for fieldname in fields.keys():
create_function = False should_create_function = False
attr_type = auto attr_type = auto
if fieldname not in cls.__annotations__: if fieldname not in cls.__annotations__:
field = model._meta.get_field(fieldname) field = model._meta.get_field(fieldname)
if isinstance(field, CounterCacheField): if isinstance(field, CounterCacheField):
create_function = True should_create_function = True
attr_type = BigInt attr_type = BigInt | None
elif isinstance(field, ASNField): elif isinstance(field, ASNField):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
elif isinstance(field, ColorField): elif isinstance(field, ColorField):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
create_attribute_and_function(cls, fieldname, attr_type, create_function) create_attribute_and_function(cls, fieldname, attr_type, should_create_function)
declared_filters = filterset.declared_filters declared_filters = filterset.declared_filters
for fieldname, v in declared_filters.items(): for fieldname, field in declared_filters.items():
create_function = False should_create_function = False
attr_type = None attr_type = None
# NetBox Filter types - put base classes after derived classes # NetBox Filter types - put base classes after derived classes
if isinstance(v, ContentTypeFilter): if isinstance(field, ContentTypeFilter):
create_function = True should_create_function = True
attr_type = str | None attr_type = str | None
elif isinstance(v, MACAddressFilter): elif isinstance(field, MACAddressFilter):
show_field("MACAddressFilter", fieldname, v, cls) pass
elif isinstance(v, MultiValueArrayFilter): elif isinstance(field, MultiValueArrayFilter):
show_field("MultiValueArrayFilter", fieldname, v, cls) pass
elif isinstance(v, MultiValueCharFilter): elif isinstance(field, MultiValueCharFilter):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
elif isinstance(v, MultiValueDateFilter): elif isinstance(field, MultiValueDateFilter):
attr_type = auto attr_type = auto
elif isinstance(v, MultiValueDateTimeFilter): elif isinstance(field, MultiValueDateTimeFilter):
attr_type = auto attr_type = auto
elif isinstance(v, MultiValueDecimalFilter): elif isinstance(field, MultiValueDecimalFilter):
show_field("MultiValueDecimalFilter", fieldname, v, cls) pass
elif isinstance(v, MultiValueMACAddressFilter): elif isinstance(field, MultiValueMACAddressFilter):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
elif isinstance(v, MultiValueNumberFilter): elif isinstance(field, MultiValueNumberFilter):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
elif isinstance(v, MultiValueTimeFilter): elif isinstance(field, MultiValueTimeFilter):
show_field("MultiValueTimeFilter", fieldname, v, cls) pass
elif isinstance(v, MultiValueWWNFilter): elif isinstance(field, MultiValueWWNFilter):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
elif isinstance(v, NullableCharFieldFilter): elif isinstance(field, NullableCharFieldFilter):
show_field("NullableCharFieldFilter", fieldname, v, cls) pass
elif isinstance(v, NumericArrayFilter): elif isinstance(field, NumericArrayFilter):
create_function = True should_create_function = True
attr_type = int attr_type = int
elif isinstance(v, TreeNodeMultipleChoiceFilter): elif isinstance(field, TreeNodeMultipleChoiceFilter):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
# From django_filters - ordering of these matters as base classes must # From django_filters - ordering of these matters as base classes must
# come after derived classes so the base class doesn't get matched first # come after derived classes so the base class doesn't get matched first
elif issubclass(type(v), django_filters.OrderingFilter): # a pass for the check (no attr_type) means we don't currently handle
show_field("OrderingFilter", fieldname, v, cls) # or use that type
elif issubclass(type(v), django_filters.BaseRangeFilter): elif issubclass(type(field), django_filters.OrderingFilter):
show_field("BaseRangeFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.BaseInFilter): elif issubclass(type(field), django_filters.BaseRangeFilter):
show_field("BaseInFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.LookupChoiceFilter): elif issubclass(type(field), django_filters.BaseInFilter):
show_field("LookupChoiceFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.AllValuesMultipleFilter): elif issubclass(type(field), django_filters.LookupChoiceFilter):
show_field("AllValuesMultipleFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.AllValuesFilter): elif issubclass(type(field), django_filters.AllValuesMultipleFilter):
show_field("AllValuesFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.TimeRangeFilter): elif issubclass(type(field), django_filters.AllValuesFilter):
show_field("TimeRangeFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.IsoDateTimeFromToRangeFilter): elif issubclass(type(field), django_filters.TimeRangeFilter):
create_function = True pass
elif issubclass(type(field), django_filters.IsoDateTimeFromToRangeFilter):
should_create_function = True
attr_type = str | None attr_type = str | None
elif issubclass(type(v), django_filters.DateTimeFromToRangeFilter): elif issubclass(type(field), django_filters.DateTimeFromToRangeFilter):
create_function = True should_create_function = True
attr_type = str | None attr_type = str | None
elif issubclass(type(v), django_filters.DateFromToRangeFilter): elif issubclass(type(field), django_filters.DateFromToRangeFilter):
create_function = True should_create_function = True
attr_type = str | None attr_type = str | None
elif issubclass(type(v), django_filters.DateRangeFilter): elif issubclass(type(field), django_filters.DateRangeFilter):
create_function = True should_create_function = True
attr_type = str | None attr_type = str | None
elif issubclass(type(v), django_filters.RangeFilter): elif issubclass(type(field), django_filters.RangeFilter):
show_field("RangeFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.NumericRangeFilter): elif issubclass(type(field), django_filters.NumericRangeFilter):
show_field("NumericRangeFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.NumberFilter): elif issubclass(type(field), django_filters.NumberFilter):
create_function = True should_create_function = True
attr_type = int attr_type = int
elif issubclass(type(v), django_filters.ModelMultipleChoiceFilter): elif issubclass(type(field), django_filters.ModelMultipleChoiceFilter):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
elif issubclass(type(v), django_filters.ModelChoiceFilter): elif issubclass(type(field), django_filters.ModelChoiceFilter):
create_function = True should_create_function = True
attr_type = str | None attr_type = str | None
elif issubclass(type(v), django_filters.DurationFilter): elif issubclass(type(field), django_filters.DurationFilter):
show_field("DurationFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.IsoDateTimeFilter): elif issubclass(type(field), django_filters.IsoDateTimeFilter):
show_field("IsoDateTimeFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.DateTimeFilter): elif issubclass(type(field), django_filters.DateTimeFilter):
attr_type = auto attr_type = auto
elif issubclass(type(v), django_filters.TimeFilter): elif issubclass(type(field), django_filters.TimeFilter):
attr_type = auto attr_type = auto
elif issubclass(type(v), django_filters.DateFilter): elif issubclass(type(field), django_filters.DateFilter):
attr_type = auto attr_type = auto
elif issubclass(type(v), django_filters.TypedMultipleChoiceFilter): elif issubclass(type(field), django_filters.TypedMultipleChoiceFilter):
show_field("TypedMultipleChoiceFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.MultipleChoiceFilter): elif issubclass(type(field), django_filters.MultipleChoiceFilter):
create_function = True should_create_function = True
attr_type = List[str] | None attr_type = List[str] | None
elif issubclass(type(v), django_filters.TypedChoiceFilter): elif issubclass(type(field), django_filters.TypedChoiceFilter):
show_field("TypedChoiceFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.ChoiceFilter): elif issubclass(type(field), django_filters.ChoiceFilter):
show_field("ChoiceFilter", fieldname, v, cls) pass
elif issubclass(type(v), django_filters.BooleanFilter): elif issubclass(type(field), django_filters.BooleanFilter):
create_function = True should_create_function = True
attr_type = bool | None attr_type = bool | None
elif issubclass(type(v), django_filters.UUIDFilter): elif issubclass(type(field), django_filters.UUIDFilter):
create_function = True should_create_function = True
attr_type = str | None attr_type = str | None
elif issubclass(type(v), django_filters.CharFilter): elif issubclass(type(field), django_filters.CharFilter):
# looks like only used by 'q' # looks like only used by 'q'
create_function = True should_create_function = True
attr_type = str | None attr_type = str | None
else:
show_field("unknown type!", fieldname, v, cls)
create_attribute_and_function(cls, fieldname, attr_type, create_function) if attr_type is None:
raise NotImplementedError(f"GraphQL Filter field unknown: {fieldname}: {field}")
create_attribute_and_function(cls, fieldname, attr_type, should_create_function)
return cls return cls