From f46090076d800b2bd67e0e835d9db8c429079fc2 Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Mon, 15 Jun 2026 18:01:04 +0200 Subject: [PATCH] refactor(graphql): Update filter lookups for strawberry-django 0.86 Update strawberry-graphql-django to 0.86.1 and remove redundant type parameters from StrFilterLookup, DateFilterLookup, TimeFilterLookup, and DatetimeFilterLookup annotations across model-backed GraphQL filters. Add NetBox-local JSON date, time, and datetime lookup input types to preserve the previous string-backed JSON filter schema without relying on deprecated upstream generic lookup annotations. These local types keep the legacy GraphQL type names and date/time sub-lookup fields intact. Fixes #22353 --- netbox/circuits/graphql/filters.py | 29 +++-- netbox/core/graphql/filter_mixins.py | 5 +- netbox/core/graphql/filters.py | 31 +++-- netbox/core/tests/test_api.py | 46 ++++++- netbox/dcim/graphql/filter_mixins.py | 12 +- netbox/dcim/graphql/filters.py | 82 ++++++------- netbox/extras/graphql/filters.py | 113 +++++++++--------- netbox/ipam/graphql/filters.py | 41 ++++--- netbox/netbox/graphql/filter_lookups.py | 53 ++++++-- netbox/netbox/graphql/filter_mixins.py | 5 +- netbox/netbox/graphql/filters.py | 18 +-- netbox/netbox/tests/test_graphql.py | 27 ++++- netbox/tenancy/graphql/filters.py | 16 +-- netbox/users/graphql/filters.py | 25 ++-- .../virtualization/graphql/filter_mixins.py | 4 +- netbox/virtualization/graphql/filters.py | 6 +- netbox/vpn/graphql/filters.py | 18 +-- netbox/wireless/graphql/filter_mixins.py | 2 +- netbox/wireless/graphql/filters.py | 4 +- requirements.txt | 2 +- 20 files changed, 319 insertions(+), 220 deletions(-) diff --git a/netbox/circuits/graphql/filters.py b/netbox/circuits/graphql/filters.py index 94ec9fec2..238b488ac 100644 --- a/netbox/circuits/graphql/filters.py +++ b/netbox/circuits/graphql/filters.py @@ -1,4 +1,3 @@ -from datetime import date from typing import TYPE_CHECKING, Annotated import strawberry @@ -62,9 +61,9 @@ class CircuitTerminationFilter( upstream_speed: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - xconnect_id: StrFilterLookup[str] | None = strawberry_django.filter_field() - pp_info: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + xconnect_id: StrFilterLookup | None = strawberry_django.filter_field() + pp_info: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() # Cached relations _provider_network: Annotated['ProviderNetworkFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( @@ -92,7 +91,7 @@ class CircuitFilter( TenancyFilterMixin, PrimaryModelFilter ): - cid: StrFilterLookup[str] | None = strawberry_django.filter_field() + cid: StrFilterLookup | None = strawberry_django.filter_field() provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -108,8 +107,8 @@ class CircuitFilter( status: BaseFilterLookup[Annotated['CircuitStatusEnum', strawberry.lazy('circuits.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - install_date: DateFilterLookup[date] | None = strawberry_django.filter_field() - termination_date: DateFilterLookup[date] | None = strawberry_django.filter_field() + install_date: DateFilterLookup | None = strawberry_django.filter_field() + termination_date: DateFilterLookup | None = strawberry_django.filter_field() commit_rate: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -145,8 +144,8 @@ class CircuitGroupAssignmentFilter(CustomFieldsFilterMixin, TagsFilterMixin, Cha @strawberry_django.filter_type(models.Provider, lookups=True) class ProviderFilter(ContactFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() asns: Annotated['ASNFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() circuits: Annotated['CircuitFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( strawberry_django.filter_field() @@ -159,18 +158,18 @@ class ProviderAccountFilter(ContactFilterMixin, PrimaryModelFilter): strawberry_django.filter_field() ) provider_id: ID | None = strawberry_django.filter_field() - account: StrFilterLookup[str] | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + account: StrFilterLookup | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.ProviderNetwork, lookups=True) class ProviderNetworkFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( strawberry_django.filter_field() ) provider_id: ID | None = strawberry_django.filter_field() - service_id: StrFilterLookup[str] | None = strawberry_django.filter_field() + service_id: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.VirtualCircuitType, lookups=True) @@ -180,7 +179,7 @@ class VirtualCircuitTypeFilter(CircuitTypeFilterMixin, OrganizationalModelFilter @strawberry_django.filter_type(models.VirtualCircuit, lookups=True) class VirtualCircuitFilter(TenancyFilterMixin, PrimaryModelFilter): - cid: StrFilterLookup[str] | None = strawberry_django.filter_field() + cid: StrFilterLookup | None = strawberry_django.filter_field() provider_network: Annotated['ProviderNetworkFilter', strawberry.lazy('circuits.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -218,4 +217,4 @@ class VirtualCircuitTerminationFilter(CustomFieldsFilterMixin, TagsFilterMixin, strawberry_django.filter_field() ) interface_id: ID | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/core/graphql/filter_mixins.py b/netbox/core/graphql/filter_mixins.py index c094ecb24..96c4b7c29 100644 --- a/netbox/core/graphql/filter_mixins.py +++ b/netbox/core/graphql/filter_mixins.py @@ -1,5 +1,4 @@ from dataclasses import dataclass -from datetime import datetime from typing import TYPE_CHECKING, Annotated import strawberry @@ -20,5 +19,5 @@ class ChangeLoggingMixin: changelog: Annotated['ObjectChangeFilter', strawberry.lazy('core.graphql.filters')] | None = ( strawberry_django.filter_field() ) - created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() - last_updated: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + created: DatetimeFilterLookup | None = strawberry_django.filter_field() + last_updated: DatetimeFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/core/graphql/filters.py b/netbox/core/graphql/filters.py index 3424c5737..05f4803e4 100644 --- a/netbox/core/graphql/filters.py +++ b/netbox/core/graphql/filters.py @@ -1,4 +1,3 @@ -from datetime import datetime from typing import TYPE_CHECKING, Annotated import strawberry @@ -26,33 +25,33 @@ __all__ = ( @strawberry_django.filter_type(models.DataFile, lookups=True) class DataFileFilter(BaseModelFilter): - created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() - last_updated: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + created: DatetimeFilterLookup | None = strawberry_django.filter_field() + last_updated: DatetimeFilterLookup | None = strawberry_django.filter_field() source: Annotated['DataSourceFilter', strawberry.lazy('core.graphql.filters')] | None = ( strawberry_django.filter_field() ) source_id: ID | None = strawberry_django.filter_field() - path: StrFilterLookup[str] | None = strawberry_django.filter_field() + path: StrFilterLookup | None = strawberry_django.filter_field() size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - hash: StrFilterLookup[str] | None = strawberry_django.filter_field() + hash: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.DataSource, lookups=True) class DataSourceFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - type: StrFilterLookup[str] | None = strawberry_django.filter_field() - source_url: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + type: StrFilterLookup | None = strawberry_django.filter_field() + source_url: StrFilterLookup | None = strawberry_django.filter_field() status: ( BaseFilterLookup[Annotated['DataSourceStatusEnum', strawberry.lazy('core.graphql.enums')]] | None ) = strawberry_django.filter_field() enabled: FilterLookup[bool] | None = strawberry_django.filter_field() - ignore_rules: StrFilterLookup[str] | None = strawberry_django.filter_field() + ignore_rules: StrFilterLookup | None = strawberry_django.filter_field() parameters: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - last_synced: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + last_synced: DatetimeFilterLookup | None = strawberry_django.filter_field() datafiles: Annotated['DataFileFilter', strawberry.lazy('core.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -60,10 +59,10 @@ class DataSourceFilter(PrimaryModelFilter): @strawberry_django.filter_type(models.ObjectChange, lookups=True) class ObjectChangeFilter(BaseModelFilter): - time: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + time: DatetimeFilterLookup | None = strawberry_django.filter_field() user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() - user_name: StrFilterLookup[str] | None = strawberry_django.filter_field() - request_id: StrFilterLookup[str] | None = strawberry_django.filter_field() + user_name: StrFilterLookup | None = strawberry_django.filter_field() + request_id: StrFilterLookup | None = strawberry_django.filter_field() action: ( BaseFilterLookup[Annotated['ObjectChangeActionEnum', strawberry.lazy('core.graphql.enums')]] | None ) = strawberry_django.filter_field() @@ -76,7 +75,7 @@ class ObjectChangeFilter(BaseModelFilter): strawberry_django.filter_field() ) related_object_id: ID | None = strawberry_django.filter_field() - object_repr: StrFilterLookup[str] | None = strawberry_django.filter_field() + object_repr: StrFilterLookup | None = strawberry_django.filter_field() prechange_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -87,5 +86,5 @@ class ObjectChangeFilter(BaseModelFilter): @strawberry_django.filter_type(DjangoContentType, lookups=True) class ContentTypeFilter(BaseModelFilter): - app_label: StrFilterLookup[str] | None = strawberry_django.filter_field() - model: StrFilterLookup[str] | None = strawberry_django.filter_field() + app_label: StrFilterLookup | None = strawberry_django.filter_field() + model: StrFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/core/tests/test_api.py b/netbox/core/tests/test_api.py index 2a159f6bd..81f16e3e7 100644 --- a/netbox/core/tests/test_api.py +++ b/netbox/core/tests/test_api.py @@ -12,7 +12,7 @@ from rq.registry import FailedJobRegistry, StartedJobRegistry from users.constants import TOKEN_PREFIX from users.models import Token -from utilities.testing import APITestCase, APIViewTestCases, TestCase +from utilities.testing import APITestCase, APIViewTestCases, GraphQLQueryTest, TestCase from utilities.testing.mixins import RQQueueTestMixin from utilities.testing.utils import disable_logging @@ -39,12 +39,49 @@ class DataSourceTestCase(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): data_sources = ( - DataSource(name='Data Source 1', type='local', source_url='file:///var/tmp/source1/'), + DataSource( + name='Data Source 1', type='local', source_url='file:///var/tmp/source1/', + parameters={ + 'sync_date': '2024-01-01', + 'sync_datetime': '2024-01-01T12:30:00+00:00', + 'sync_time': '12:30:00', + }, + ), DataSource(name='Data Source 2', type='local', source_url='file:///var/tmp/source2/'), DataSource(name='Data Source 3', type='local', source_url='file:///var/tmp/source3/'), ) DataSource.objects.bulk_create(data_sources) + cls.graphql_query_tests = ( + GraphQLQueryTest( + name='parameters_json_date_lookup', + query=( + '{ data_source_list(filters: {parameters: ' + '{path: "sync_date", lookup: {date_lookup: {exact: "2024-01-01"}}}}) ' + '{ id } }' + ), + assert_result=cls.assert_only_source_1, + ), + GraphQLQueryTest( + name='parameters_json_datetime_lookup', + query=( + '{ data_source_list(filters: {parameters: ' + '{path: "sync_datetime", lookup: {datetime_lookup: {exact: "2024-01-01T12:30:00+00:00"}}}}) ' + '{ id } }' + ), + assert_result=cls.assert_only_source_1, + ), + GraphQLQueryTest( + name='parameters_json_time_lookup', + query=( + '{ data_source_list(filters: {parameters: ' + '{path: "sync_time", lookup: {time_lookup: {exact: "12:30:00"}}}}) ' + '{ id } }' + ), + assert_result=cls.assert_only_source_1, + ), + ) + cls.create_data = [ { 'name': 'Data Source 4', @@ -63,6 +100,11 @@ class DataSourceTestCase(APIViewTestCases.APIViewTestCase): }, ] + def assert_only_source_1(self, data): + """The JSON lookup returns exactly the source carrying the matching value.""" + ids = sorted(result['id'] for result in data['data_source_list']) + self.assertEqual(ids, [str(DataSource.objects.get(name='Data Source 1').pk)]) + class DataFileTestCase( APIViewTestCases.GetObjectViewTestCase, diff --git a/netbox/dcim/graphql/filter_mixins.py b/netbox/dcim/graphql/filter_mixins.py index 07fa34616..fb5a21a0b 100644 --- a/netbox/dcim/graphql/filter_mixins.py +++ b/netbox/dcim/graphql/filter_mixins.py @@ -66,9 +66,9 @@ class ComponentModelFilterMixin: ) device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() device_id: ID | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - label: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + label: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() @dataclass @@ -96,9 +96,9 @@ class ComponentTemplateFilterMixin: strawberry_django.filter_field() ) device_type_id: ID | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - label: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + label: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() @dataclass diff --git a/netbox/dcim/graphql/filters.py b/netbox/dcim/graphql/filters.py index 02fb3ef64..09ba07acd 100644 --- a/netbox/dcim/graphql/filters.py +++ b/netbox/dcim/graphql/filters.py @@ -116,7 +116,7 @@ __all__ = ( @strawberry_django.filter_type(models.CableBundle, lookups=True) class CableBundleFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.Cable, lookups=True) @@ -127,7 +127,7 @@ class CableFilter(TenancyFilterMixin, PrimaryModelFilter): status: BaseFilterLookup[Annotated['LinkStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - label: StrFilterLookup[str] | None = strawberry_django.filter_field() + label: StrFilterLookup | None = strawberry_django.filter_field() color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -223,9 +223,9 @@ class DeviceFilter( platform: Annotated['PlatformFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - serial: StrFilterLookup[str] | None = strawberry_django.filter_field() - asset_tag: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + serial: StrFilterLookup | None = strawberry_django.filter_field() + asset_tag: StrFilterLookup | None = strawberry_django.filter_field() site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() site_id: ID | None = strawberry_django.filter_field() location: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -353,7 +353,7 @@ class InventoryItemTemplateFilter(ComponentTemplateFilterMixin, ChangeLoggedMode strawberry_django.filter_field() ) manufacturer_id: ID | None = strawberry_django.filter_field() - part_id: StrFilterLookup[str] | None = strawberry_django.filter_field() + part_id: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.DeviceRole, lookups=True) @@ -370,13 +370,13 @@ class DeviceTypeFilter(ImageAttachmentFilterMixin, WeightFilterMixin, PrimaryMod strawberry_django.filter_field() ) manufacturer_id: ID | None = strawberry_django.filter_field() - model: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + model: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() default_platform: Annotated['PlatformFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) default_platform_id: ID | None = strawberry_django.filter_field() - part_number: StrFilterLookup[str] | None = strawberry_django.filter_field() + part_number: StrFilterLookup | None = strawberry_django.filter_field() instances: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -493,7 +493,7 @@ class PortTemplateMappingFilter(BaseModelFilter): @strawberry_django.filter_type(models.MACAddress, lookups=True) class MACAddressFilter(PrimaryModelFilter): - mac_address: StrFilterLookup[str] | None = strawberry_django.filter_field() + mac_address: StrFilterLookup | None = strawberry_django.filter_field() assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -539,7 +539,7 @@ class InterfaceFilter( duplex: BaseFilterLookup[Annotated['InterfaceDuplexEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - wwn: StrFilterLookup[str] | None = strawberry_django.filter_field() + wwn: StrFilterLookup | None = strawberry_django.filter_field() parent: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -659,9 +659,9 @@ class InventoryItemFilter(ComponentModelFilterMixin, NetBoxModelFilter): strawberry_django.filter_field() ) manufacturer_id: ID | None = strawberry_django.filter_field() - part_id: StrFilterLookup[str] | None = strawberry_django.filter_field() - serial: StrFilterLookup[str] | None = strawberry_django.filter_field() - asset_tag: StrFilterLookup[str] | None = strawberry_django.filter_field() + part_id: StrFilterLookup | None = strawberry_django.filter_field() + serial: StrFilterLookup | None = strawberry_django.filter_field() + asset_tag: StrFilterLookup | None = strawberry_django.filter_field() discovered: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -679,7 +679,7 @@ class LocationFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilt status: BaseFilterLookup[Annotated['LocationStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - facility: StrFilterLookup[str] | None = strawberry_django.filter_field() + facility: StrFilterLookup | None = strawberry_django.filter_field() prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -708,8 +708,8 @@ class ModuleFilter(ConfigContextFilterMixin, PrimaryModelFilter): status: BaseFilterLookup[Annotated['ModuleStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - serial: StrFilterLookup[str] | None = strawberry_django.filter_field() - asset_tag: StrFilterLookup[str] | None = strawberry_django.filter_field() + serial: StrFilterLookup | None = strawberry_django.filter_field() + asset_tag: StrFilterLookup | None = strawberry_django.filter_field() consoleports: Annotated['ConsolePortFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field(name='console_ports') ) @@ -748,19 +748,19 @@ class ModuleBayFilter(ModularComponentFilterMixin, NetBoxModelFilter): strawberry_django.filter_field() ) parent_id: ID | None = strawberry_django.filter_field() - position: StrFilterLookup[str] | None = strawberry_django.filter_field() + position: StrFilterLookup | None = strawberry_django.filter_field() enabled: FilterLookup[bool] | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.ModuleBayTemplate, lookups=True) class ModuleBayTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter): - position: StrFilterLookup[str] | None = strawberry_django.filter_field() + position: StrFilterLookup | None = strawberry_django.filter_field() enabled: FilterLookup[bool] | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.ModuleTypeProfile, lookups=True) class ModuleTypeProfileFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.ModuleType, lookups=True) @@ -773,8 +773,8 @@ class ModuleTypeFilter(ImageAttachmentFilterMixin, WeightFilterMixin, PrimaryMod strawberry_django.filter_field() ) profile_id: ID | None = strawberry_django.filter_field() - model: StrFilterLookup[str] | None = strawberry_django.filter_field() - part_number: StrFilterLookup[str] | None = strawberry_django.filter_field() + model: StrFilterLookup | None = strawberry_django.filter_field() + part_number: StrFilterLookup | None = strawberry_django.filter_field() instances: Annotated['ModuleFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -831,7 +831,7 @@ class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryM power_panel_id: ID | None = strawberry_django.filter_field() rack: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() rack_id: ID | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['PowerFeedStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -902,7 +902,7 @@ class PowerPanelFilter(ContactFilterMixin, ImageAttachmentFilterMixin, PrimaryMo location_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.PowerPort, lookups=True) @@ -940,8 +940,8 @@ class RackTypeFilter(ImageAttachmentFilterMixin, RackFilterMixin, WeightFilterMi strawberry_django.filter_field() ) manufacturer_id: ID | None = strawberry_django.filter_field() - model: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + model: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() racks: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() rack_count: ComparisonFilterLookup[int] | None = strawberry_django.filter_field() @@ -962,8 +962,8 @@ class RackFilter( strawberry_django.filter_field() ) rack_type_id: ID | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - facility_id: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + facility_id: StrFilterLookup | None = strawberry_django.filter_field() site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() site_id: ID | None = strawberry_django.filter_field() location: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( @@ -981,8 +981,8 @@ class RackFilter( ) role: Annotated['RackRoleFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() role_id: ID | None = strawberry_django.filter_field() - serial: StrFilterLookup[str] | None = strawberry_django.filter_field() - asset_tag: StrFilterLookup[str] | None = strawberry_django.filter_field() + serial: StrFilterLookup | None = strawberry_django.filter_field() + asset_tag: StrFilterLookup | None = strawberry_django.filter_field() airflow: BaseFilterLookup[Annotated['RackAirflowEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -1006,7 +1006,7 @@ class RackReservationFilter(TenancyFilterMixin, PrimaryModelFilter): unit_count: ComparisonFilterLookup[int] | None = strawberry_django.filter_field() user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() user_id: ID | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['RackReservationStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -1057,8 +1057,8 @@ class RegionFilter(ContactFilterMixin, NestedGroupModelFilter): @strawberry_django.filter_type(models.Site, lookups=True) class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['SiteStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -1072,11 +1072,11 @@ class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMi group_id: Annotated['TreeNodeFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - facility: StrFilterLookup[str] | None = strawberry_django.filter_field() + facility: StrFilterLookup | None = strawberry_django.filter_field() asns: Annotated['ASNFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() - time_zone: StrFilterLookup[str] | None = strawberry_django.filter_field() - physical_address: StrFilterLookup[str] | None = strawberry_django.filter_field() - shipping_address: StrFilterLookup[str] | None = strawberry_django.filter_field() + time_zone: StrFilterLookup | None = strawberry_django.filter_field() + physical_address: StrFilterLookup | None = strawberry_django.filter_field() + shipping_address: StrFilterLookup | None = strawberry_django.filter_field() latitude: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -1105,8 +1105,8 @@ class SiteGroupFilter(ContactFilterMixin, NestedGroupModelFilter): class VirtualChassisFilter(PrimaryModelFilter): master: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() master_id: ID | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - domain: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + domain: StrFilterLookup | None = strawberry_django.filter_field() members: ( Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None ) = strawberry_django.filter_field() @@ -1117,7 +1117,7 @@ class VirtualChassisFilter(PrimaryModelFilter): class VirtualDeviceContextFilter(TenancyFilterMixin, PrimaryModelFilter): device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field() device_id: ID | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() status: ( BaseFilterLookup[Annotated['VirtualDeviceContextStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None ) = ( @@ -1134,7 +1134,7 @@ class VirtualDeviceContextFilter(TenancyFilterMixin, PrimaryModelFilter): strawberry_django.filter_field() ) primary_ip6_id: ID | None = strawberry_django.filter_field() - comments: StrFilterLookup[str] | None = strawberry_django.filter_field() + comments: StrFilterLookup | None = strawberry_django.filter_field() interfaces: ( Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None ) = strawberry_django.filter_field() diff --git a/netbox/extras/graphql/filters.py b/netbox/extras/graphql/filters.py index 2479d46d2..5b6e2eab6 100644 --- a/netbox/extras/graphql/filters.py +++ b/netbox/extras/graphql/filters.py @@ -1,4 +1,3 @@ -from datetime import datetime from typing import TYPE_CHECKING, Annotated import strawberry @@ -55,11 +54,11 @@ __all__ = ( @strawberry_django.filter_type(models.ConfigContext, lookups=True) class ConfigContextFilter(SyncedDataFilterMixin, ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() is_active: FilterLookup[bool] | None = strawberry_django.filter_field() regions: Annotated['RegionFilter', strawberry.lazy('dcim.graphql.filters')] | None = ( strawberry_django.filter_field() @@ -112,22 +111,22 @@ class ConfigContextFilter(SyncedDataFilterMixin, ChangeLoggedModelFilter): @strawberry_django.filter_type(models.ConfigContextProfile, lookups=True) class ConfigContextProfileFilter(SyncedDataFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() tags: Annotated['TagFilter', strawberry.lazy('extras.graphql.filters')] | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.ConfigTemplate, lookups=True) class ConfigTemplateFilter(SyncedDataFilterMixin, ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() - template_code: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() + template_code: StrFilterLookup | None = strawberry_django.filter_field() environment_params: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - mime_type: StrFilterLookup[str] | None = strawberry_django.filter_field() - file_name: StrFilterLookup[str] | None = strawberry_django.filter_field() - file_extension: StrFilterLookup[str] | None = strawberry_django.filter_field() + mime_type: StrFilterLookup | None = strawberry_django.filter_field() + file_name: StrFilterLookup | None = strawberry_django.filter_field() + file_extension: StrFilterLookup | None = strawberry_django.filter_field() as_attachment: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -142,10 +141,10 @@ class CustomFieldFilter(ChangeLoggedModelFilter): related_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( strawberry_django.filter_field() ) - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - label: StrFilterLookup[str] | None = strawberry_django.filter_field() - group_name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + label: StrFilterLookup | None = strawberry_django.filter_field() + group_name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() required: FilterLookup[bool] | None = strawberry_django.filter_field() unique: FilterLookup[bool] | None = strawberry_django.filter_field() search_weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -171,7 +170,7 @@ class CustomFieldFilter(ChangeLoggedModelFilter): validation_maximum: Annotated['FloatLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - validation_regex: StrFilterLookup[str] | None = strawberry_django.filter_field() + validation_regex: StrFilterLookup | None = strawberry_django.filter_field() choice_set: Annotated['CustomFieldChoiceSetFilter', strawberry.lazy('extras.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -187,13 +186,13 @@ class CustomFieldFilter(ChangeLoggedModelFilter): strawberry_django.filter_field() ) is_cloneable: FilterLookup[bool] | None = strawberry_django.filter_field() - comments: StrFilterLookup[str] | None = strawberry_django.filter_field() + comments: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.CustomFieldChoiceSet, lookups=True) class CustomFieldChoiceSetFilter(ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() base_choices: ( BaseFilterLookup[Annotated['CustomFieldChoiceSetBaseEnum', strawberry.lazy('extras.graphql.enums')]] | None ) = ( @@ -234,14 +233,14 @@ class CustomFieldChoiceSetFilter(ChangeLoggedModelFilter): @strawberry_django.filter_type(models.CustomLink, lookups=True) class CustomLinkFilter(ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() enabled: FilterLookup[bool] | None = strawberry_django.filter_field() - link_text: StrFilterLookup[str] | None = strawberry_django.filter_field() - link_url: StrFilterLookup[str] | None = strawberry_django.filter_field() + link_text: StrFilterLookup | None = strawberry_django.filter_field() + link_url: StrFilterLookup | None = strawberry_django.filter_field() weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - group_name: StrFilterLookup[str] | None = strawberry_django.filter_field() + group_name: StrFilterLookup | None = strawberry_django.filter_field() button_class: ( BaseFilterLookup[Annotated['CustomLinkButtonClassEnum', strawberry.lazy('extras.graphql.enums')]] | None ) = ( @@ -252,15 +251,15 @@ class CustomLinkFilter(ChangeLoggedModelFilter): @strawberry_django.filter_type(models.ExportTemplate, lookups=True) class ExportTemplateFilter(SyncedDataFilterMixin, ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() - template_code: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() + template_code: StrFilterLookup | None = strawberry_django.filter_field() environment_params: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - mime_type: StrFilterLookup[str] | None = strawberry_django.filter_field() - file_name: StrFilterLookup[str] | None = strawberry_django.filter_field() - file_extension: StrFilterLookup[str] | None = strawberry_django.filter_field() + mime_type: StrFilterLookup | None = strawberry_django.filter_field() + file_name: StrFilterLookup | None = strawberry_django.filter_field() + file_extension: StrFilterLookup | None = strawberry_django.filter_field() as_attachment: FilterLookup[bool] | None = strawberry_django.filter_field() @@ -276,7 +275,7 @@ class ImageAttachmentFilter(ChangeLoggedModelFilter): image_width: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.JournalEntry, lookups=True) @@ -292,13 +291,13 @@ class JournalEntryFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedM kind: BaseFilterLookup[Annotated['JournalEntryKindEnum', strawberry.lazy('extras.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - comments: StrFilterLookup[str] | None = strawberry_django.filter_field() + comments: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.Notification, lookups=True) class NotificationFilter(BaseModelFilter): - created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() - read: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + created: DatetimeFilterLookup | None = strawberry_django.filter_field() + read: DatetimeFilterLookup | None = strawberry_django.filter_field() user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() user_id: ID | None = strawberry_django.filter_field() object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( @@ -306,23 +305,23 @@ class NotificationFilter(BaseModelFilter): ) object_type_id: ID | None = strawberry_django.filter_field() object_id: ID | None = strawberry_django.filter_field() - object_repr: StrFilterLookup[str] | None = strawberry_django.filter_field() - event_type: StrFilterLookup[str] | None = strawberry_django.filter_field() + object_repr: StrFilterLookup | None = strawberry_django.filter_field() + event_type: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.NotificationGroup, lookups=True) class NotificationGroupFilter(ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() groups: Annotated['GroupFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() users: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.SavedFilter, lookups=True) class SavedFilterFilter(ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() user_id: ID | None = strawberry_django.filter_field() weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -337,7 +336,7 @@ class SavedFilterFilter(ChangeLoggedModelFilter): @strawberry_django.filter_type(models.Subscription, lookups=True) class SubscriptionFilter(BaseModelFilter): - created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + created: DatetimeFilterLookup | None = strawberry_django.filter_field() user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() user_id: ID | None = strawberry_django.filter_field() object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( @@ -349,8 +348,8 @@ class SubscriptionFilter(BaseModelFilter): @strawberry_django.filter_type(models.TableConfig, lookups=True) class TableConfigFilter(ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() user_id: ID | None = strawberry_django.filter_field() weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -362,30 +361,30 @@ class TableConfigFilter(ChangeLoggedModelFilter): @strawberry_django.filter_type(models.Tag, lookups=True) class TagFilter(ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.Webhook, lookups=True) class WebhookFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() - payload_url: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() + payload_url: StrFilterLookup | None = strawberry_django.filter_field() http_method: ( BaseFilterLookup[Annotated['WebhookHttpMethodEnum', strawberry.lazy('extras.graphql.enums')]] | None ) = ( strawberry_django.filter_field() ) - http_content_type: StrFilterLookup[str] | None = strawberry_django.filter_field() - additional_headers: StrFilterLookup[str] | None = strawberry_django.filter_field() - body_template: StrFilterLookup[str] | None = strawberry_django.filter_field() - secret: StrFilterLookup[str] | None = strawberry_django.filter_field() + http_content_type: StrFilterLookup | None = strawberry_django.filter_field() + additional_headers: StrFilterLookup | None = strawberry_django.filter_field() + body_template: StrFilterLookup | None = strawberry_django.filter_field() + secret: StrFilterLookup | None = strawberry_django.filter_field() ssl_verification: FilterLookup[bool] | None = strawberry_django.filter_field() - ca_file_path: StrFilterLookup[str] | None = strawberry_django.filter_field() + ca_file_path: StrFilterLookup | None = strawberry_django.filter_field() events: Annotated['EventRuleFilter', strawberry.lazy('extras.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -393,8 +392,8 @@ class WebhookFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelF @strawberry_django.filter_type(models.EventRule, lookups=True) class EventRuleFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() event_types: Annotated['StringArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -413,4 +412,4 @@ class EventRuleFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedMode action_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - comments: StrFilterLookup[str] | None = strawberry_django.filter_field() + comments: StrFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/ipam/graphql/filters.py b/netbox/ipam/graphql/filters.py index f3c6637fa..7d16c0fe6 100644 --- a/netbox/ipam/graphql/filters.py +++ b/netbox/ipam/graphql/filters.py @@ -1,4 +1,3 @@ -from datetime import date from typing import TYPE_CHECKING, Annotated import netaddr @@ -72,8 +71,8 @@ class ASNFilter(TenancyFilterMixin, PrimaryModelFilter): @strawberry_django.filter_type(models.ASNRange, lookups=True) class ASNRangeFilter(TenancyFilterMixin, OrganizationalModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() rir_id: ID | None = strawberry_django.filter_field() start: Annotated['BigIntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( @@ -86,10 +85,10 @@ class ASNRangeFilter(TenancyFilterMixin, OrganizationalModelFilter): @strawberry_django.filter_type(models.Aggregate, lookups=True) class AggregateFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter): - prefix: StrFilterLookup[str] | None = strawberry_django.filter_field() + prefix: StrFilterLookup | None = strawberry_django.filter_field() rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() rir_id: ID | None = strawberry_django.filter_field() - date_added: DateFilterLookup[date] | None = strawberry_django.filter_field() + date_added: DateFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_field() def contains(self, value: list[str], prefix) -> Q: @@ -122,14 +121,14 @@ class FHRPGroupFilter(PrimaryModelFilter): group_id: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() protocol: BaseFilterLookup[Annotated['FHRPGroupProtocolEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) auth_type: BaseFilterLookup[Annotated['FHRPGroupAuthTypeEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) - auth_key: StrFilterLookup[str] | None = strawberry_django.filter_field() + auth_key: StrFilterLookup | None = strawberry_django.filter_field() ip_addresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -140,7 +139,7 @@ class FHRPGroupAssignmentFilter(ChangeLoggedModelFilter): interface_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = ( strawberry_django.filter_field() ) - interface_id: StrFilterLookup[str] | None = strawberry_django.filter_field() + interface_id: StrFilterLookup | None = strawberry_django.filter_field() group: Annotated['FHRPGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -176,7 +175,7 @@ class FHRPGroupAssignmentFilter(ChangeLoggedModelFilter): @strawberry_django.filter_type(models.IPAddress, lookups=True) class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter): - address: StrFilterLookup[str] | None = strawberry_django.filter_field() + address: StrFilterLookup | None = strawberry_django.filter_field() vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() vrf_id: ID | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['IPAddressStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( @@ -197,7 +196,7 @@ class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter strawberry_django.filter_field() ) nat_outside_id: ID | None = strawberry_django.filter_field() - dns_name: StrFilterLookup[str] | None = strawberry_django.filter_field() + dns_name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_field() def assigned(self, value: bool, prefix) -> Q: @@ -227,8 +226,8 @@ class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter @strawberry_django.filter_type(models.IPRange, lookups=True) class IPRangeFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter): - start_address: StrFilterLookup[str] | None = strawberry_django.filter_field() - end_address: StrFilterLookup[str] | None = strawberry_django.filter_field() + start_address: StrFilterLookup | None = strawberry_django.filter_field() + end_address: StrFilterLookup | None = strawberry_django.filter_field() size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -281,7 +280,7 @@ class IPRangeFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter): @strawberry_django.filter_type(models.Prefix, lookups=True) class PrefixFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, PrimaryModelFilter): - prefix: StrFilterLookup[str] | None = strawberry_django.filter_field() + prefix: StrFilterLookup | None = strawberry_django.filter_field() vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() vrf_id: ID | None = strawberry_django.filter_field() vlan: Annotated['VLANFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() @@ -330,7 +329,7 @@ class RoleFilter(OrganizationalModelFilter): @strawberry_django.filter_type(models.RouteTarget, lookups=True) class RouteTargetFilter(TenancyFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() importing_vrfs: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -347,7 +346,7 @@ class RouteTargetFilter(TenancyFilterMixin, PrimaryModelFilter): @strawberry_django.filter_type(models.Service, lookups=True) class ServiceFilter(ContactFilterMixin, ServiceFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() ip_addresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -359,7 +358,7 @@ class ServiceFilter(ContactFilterMixin, ServiceFilterMixin, PrimaryModelFilter): @strawberry_django.filter_type(models.ServiceTemplate, lookups=True) class ServiceTemplateFilter(ServiceFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.VLAN, lookups=True) @@ -373,7 +372,7 @@ class VLANFilter(TenancyFilterMixin, PrimaryModelFilter): vid: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['VLANStatusEnum', strawberry.lazy('ipam.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -404,7 +403,7 @@ class VLANGroupFilter(ScopedFilterMixin, OrganizationalModelFilter): @strawberry_django.filter_type(models.VLANTranslationPolicy, lookups=True) class VLANTranslationPolicyFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.VLANTranslationRule, lookups=True) @@ -413,7 +412,7 @@ class VLANTranslationRuleFilter(NetBoxModelFilter): strawberry_django.filter_field() ) policy_id: ID | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() local_vid: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) @@ -424,8 +423,8 @@ class VLANTranslationRuleFilter(NetBoxModelFilter): @strawberry_django.filter_type(models.VRF, lookups=True) class VRFFilter(TenancyFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - rd: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + rd: StrFilterLookup | None = strawberry_django.filter_field() enforce_unique: FilterLookup[bool] | None = strawberry_django.filter_field() import_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( strawberry_django.filter_field() diff --git a/netbox/netbox/graphql/filter_lookups.py b/netbox/netbox/graphql/filter_lookups.py index 243dfb4e8..d3da1239e 100644 --- a/netbox/netbox/graphql/filter_lookups.py +++ b/netbox/netbox/graphql/filter_lookups.py @@ -11,12 +11,9 @@ from strawberry.directive import DirectiveValue from strawberry.types import Info from strawberry_django import ( ComparisonFilterLookup, - DateFilterLookup, - DatetimeFilterLookup, FilterLookup, RangeLookup, StrFilterLookup, - TimeFilterLookup, process_filters, ) @@ -39,16 +36,58 @@ T = TypeVar('T') SKIP_MSG = 'Filter will be skipped on `null` value' +# These JSON lookup types intentionally mirror the legacy DateFilterLookup[str], +# TimeFilterLookup[str], and DatetimeFilterLookup[str] schema. JSON values are +# string-backed, so the concrete strawberry-django date/time lookup classes +# (which now ignore type parameters and warn) are deliberately not used here. +@strawberry.input(name='StrDateFilterLookup') +class JSONDateFilterLookup(ComparisonFilterLookup[str]): + year: ComparisonFilterLookup[int] | None = strawberry.UNSET + month: ComparisonFilterLookup[int] | None = strawberry.UNSET + day: ComparisonFilterLookup[int] | None = strawberry.UNSET + week_day: ComparisonFilterLookup[int] | None = strawberry.UNSET + iso_week_day: ComparisonFilterLookup[int] | None = strawberry.UNSET + week: ComparisonFilterLookup[int] | None = strawberry.UNSET + iso_year: ComparisonFilterLookup[int] | None = strawberry.UNSET + quarter: ComparisonFilterLookup[int] | None = strawberry.UNSET + + +@strawberry.input(name='StrTimeFilterLookup') +class JSONTimeFilterLookup(ComparisonFilterLookup[str]): + hour: ComparisonFilterLookup[int] | None = strawberry.UNSET + minute: ComparisonFilterLookup[int] | None = strawberry.UNSET + second: ComparisonFilterLookup[int] | None = strawberry.UNSET + date: ComparisonFilterLookup[int] | None = strawberry.UNSET + time: ComparisonFilterLookup[int] | None = strawberry.UNSET + + +@strawberry.input(name='StrDatetimeFilterLookup') +class JSONDatetimeFilterLookup(ComparisonFilterLookup[str]): + year: ComparisonFilterLookup[int] | None = strawberry.UNSET + month: ComparisonFilterLookup[int] | None = strawberry.UNSET + day: ComparisonFilterLookup[int] | None = strawberry.UNSET + week_day: ComparisonFilterLookup[int] | None = strawberry.UNSET + iso_week_day: ComparisonFilterLookup[int] | None = strawberry.UNSET + week: ComparisonFilterLookup[int] | None = strawberry.UNSET + iso_year: ComparisonFilterLookup[int] | None = strawberry.UNSET + quarter: ComparisonFilterLookup[int] | None = strawberry.UNSET + hour: ComparisonFilterLookup[int] | None = strawberry.UNSET + minute: ComparisonFilterLookup[int] | None = strawberry.UNSET + second: ComparisonFilterLookup[int] | None = strawberry.UNSET + date: ComparisonFilterLookup[int] | None = strawberry.UNSET + time: ComparisonFilterLookup[int] | None = strawberry.UNSET + + @strawberry.input(one_of=True, description='Lookup for JSON field. Only one of the lookup fields can be set.') class JSONLookup: - string_lookup: StrFilterLookup[str] | None = strawberry_django.filter_field() + string_lookup: StrFilterLookup | None = strawberry_django.filter_field() int_range_lookup: RangeLookup[int] | None = strawberry_django.filter_field() int_comparison_lookup: ComparisonFilterLookup[int] | None = strawberry_django.filter_field() float_range_lookup: RangeLookup[float] | None = strawberry_django.filter_field() float_comparison_lookup: ComparisonFilterLookup[float] | None = strawberry_django.filter_field() - date_lookup: DateFilterLookup[str] | None = strawberry_django.filter_field() - datetime_lookup: DatetimeFilterLookup[str] | None = strawberry_django.filter_field() - time_lookup: TimeFilterLookup[str] | None = strawberry_django.filter_field() + date_lookup: JSONDateFilterLookup | None = strawberry_django.filter_field() + datetime_lookup: JSONDatetimeFilterLookup | None = strawberry_django.filter_field() + time_lookup: JSONTimeFilterLookup | None = strawberry_django.filter_field() boolean_lookup: FilterLookup[bool] | None = strawberry_django.filter_field() def get_filter(self): diff --git a/netbox/netbox/graphql/filter_mixins.py b/netbox/netbox/graphql/filter_mixins.py index 94b836f06..c33e3e8b9 100644 --- a/netbox/netbox/graphql/filter_mixins.py +++ b/netbox/netbox/graphql/filter_mixins.py @@ -1,5 +1,4 @@ from dataclasses import dataclass -from datetime import datetime from typing import TYPE_CHECKING, Annotated, TypeVar import strawberry @@ -48,9 +47,9 @@ class SyncedDataFilterMixin: strawberry_django.filter_field() ) data_file_id: FilterLookup[int] | None = strawberry_django.filter_field() - data_path: StrFilterLookup[str] | None = strawberry_django.filter_field() + data_path: StrFilterLookup | None = strawberry_django.filter_field() auto_sync_enabled: FilterLookup[bool] | None = strawberry_django.filter_field() - data_synced: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + data_synced: DatetimeFilterLookup | None = strawberry_django.filter_field() @dataclass diff --git a/netbox/netbox/graphql/filters.py b/netbox/netbox/graphql/filters.py index a372d7bc0..c6241e226 100644 --- a/netbox/netbox/graphql/filters.py +++ b/netbox/netbox/graphql/filters.py @@ -42,21 +42,21 @@ class NetBoxModelFilter( @dataclass class NestedGroupModelFilter(NetBoxModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() parent_id: ID | None = strawberry_django.filter_field() @dataclass class OrganizationalModelFilter(NetBoxModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() - comments: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() + comments: StrFilterLookup | None = strawberry_django.filter_field() @dataclass class PrimaryModelFilter(NetBoxModelFilter): - description: StrFilterLookup[str] | None = strawberry_django.filter_field() - comments: StrFilterLookup[str] | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() + comments: StrFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/netbox/tests/test_graphql.py b/netbox/netbox/tests/test_graphql.py index e14d9c7ff..0b711348b 100644 --- a/netbox/netbox/tests/test_graphql.py +++ b/netbox/netbox/tests/test_graphql.py @@ -1,4 +1,5 @@ import json +import re import strawberry from django.contrib.contenttypes.models import ContentType @@ -12,7 +13,7 @@ from dcim.choices import LocationStatusChoices from dcim.models import Device, DeviceRole, DeviceType, Location, Manufacturer, Site, VirtualChassis from extras.models import TableConfig, Tag from netbox.graphql.scalars import BigInt, BigIntScalar -from netbox.graphql.schema import Query, get_schema_extensions +from netbox.graphql.schema import Query, get_schema_extensions, schema from utilities.tables import get_table_for_model from utilities.testing import APITestCase, TestCase, disable_warnings @@ -90,6 +91,30 @@ class GraphQLTestCase(TestCase): with disable_warnings('django.request'): self.assertHttpStatus(response, 302) # Redirect to login page + def test_json_lookup_schema_is_string_backed(self): + """JSONLookup date/time lookups keep the legacy string-backed input types and fields.""" + sdl = schema.as_str() + + def input_block(name): + match = re.search(rf'^input {re.escape(name)}\b.*?^\}}', sdl, re.DOTALL | re.MULTILINE) + self.assertIsNotNone(match, f'{name} not found in schema') + return match.group(0) + + # JSONLookup points at the legacy string-backed lookup type names + json_lookup = input_block('JSONLookup') + self.assertIn('date_lookup: StrDateFilterLookup', json_lookup) + self.assertIn('datetime_lookup: StrDatetimeFilterLookup', json_lookup) + self.assertIn('time_lookup: StrTimeFilterLookup', json_lookup) + + # Value fields are string-backed, not Date/DateTime/Time scalars + self.assertIn('exact: String', input_block('StrDateFilterLookup')) + + # Legacy date/time sub-lookups remain integer comparison lookups + for name in ('StrTimeFilterLookup', 'StrDatetimeFilterLookup'): + block = input_block(name) + self.assertIn('date: IntComparisonFilterLookup', block) + self.assertIn('time: IntComparisonFilterLookup', block) + class GraphQLAPITestCase(APITestCase): diff --git a/netbox/tenancy/graphql/filters.py b/netbox/tenancy/graphql/filters.py index 7b340c4fc..0a570c980 100644 --- a/netbox/tenancy/graphql/filters.py +++ b/netbox/tenancy/graphql/filters.py @@ -60,8 +60,8 @@ __all__ = ( @strawberry_django.filter_type(models.Tenant, lookups=True) class TenantFilter(ContactFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() group: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -153,12 +153,12 @@ class TenantGroupFilter(OrganizationalModelFilter): @strawberry_django.filter_type(models.Contact, lookups=True) class ContactFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - title: StrFilterLookup[str] | None = strawberry_django.filter_field() - phone: StrFilterLookup[str] | None = strawberry_django.filter_field() - email: StrFilterLookup[str] | None = strawberry_django.filter_field() - address: StrFilterLookup[str] | None = strawberry_django.filter_field() - link: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + title: StrFilterLookup | None = strawberry_django.filter_field() + phone: StrFilterLookup | None = strawberry_django.filter_field() + email: StrFilterLookup | None = strawberry_django.filter_field() + address: StrFilterLookup | None = strawberry_django.filter_field() + link: StrFilterLookup | None = strawberry_django.filter_field() groups: Annotated['ContactGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = ( strawberry_django.filter_field() ) diff --git a/netbox/users/graphql/filters.py b/netbox/users/graphql/filters.py index c3d6d6f25..6ff40597c 100644 --- a/netbox/users/graphql/filters.py +++ b/netbox/users/graphql/filters.py @@ -1,4 +1,3 @@ -from datetime import datetime from typing import Annotated import strawberry @@ -18,27 +17,27 @@ __all__ = ( @strawberry_django.filter_type(models.Group, lookups=True) class GroupFilter(BaseModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.User, lookups=True) class UserFilter(BaseModelFilter): - username: StrFilterLookup[str] | None = strawberry_django.filter_field() - first_name: StrFilterLookup[str] | None = strawberry_django.filter_field() - last_name: StrFilterLookup[str] | None = strawberry_django.filter_field() - email: StrFilterLookup[str] | None = strawberry_django.filter_field() + username: StrFilterLookup | None = strawberry_django.filter_field() + first_name: StrFilterLookup | None = strawberry_django.filter_field() + last_name: StrFilterLookup | None = strawberry_django.filter_field() + email: StrFilterLookup | None = strawberry_django.filter_field() is_superuser: FilterLookup[bool] | None = strawberry_django.filter_field() is_active: FilterLookup[bool] | None = strawberry_django.filter_field() - date_joined: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() - last_login: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field() + date_joined: DatetimeFilterLookup | None = strawberry_django.filter_field() + last_login: DatetimeFilterLookup | None = strawberry_django.filter_field() groups: Annotated['GroupFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.Owner, lookups=True) class OwnerFilter(BaseModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() group: Annotated['OwnerGroupFilter', strawberry.lazy('users.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -50,5 +49,5 @@ class OwnerFilter(BaseModelFilter): @strawberry_django.filter_type(models.OwnerGroup, lookups=True) class OwnerGroupFilter(BaseModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/virtualization/graphql/filter_mixins.py b/netbox/virtualization/graphql/filter_mixins.py index c1ff60568..5318b4bad 100644 --- a/netbox/virtualization/graphql/filter_mixins.py +++ b/netbox/virtualization/graphql/filter_mixins.py @@ -20,5 +20,5 @@ class VMComponentFilterMixin: strawberry_django.filter_field() ) virtual_machine_id: ID | None = strawberry_django.filter_field() - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - description: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + description: StrFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/virtualization/graphql/filters.py b/netbox/virtualization/graphql/filters.py index 4605c4424..c3f62fa1c 100644 --- a/netbox/virtualization/graphql/filters.py +++ b/netbox/virtualization/graphql/filters.py @@ -40,7 +40,7 @@ __all__ = ( @strawberry_django.filter_type(models.Cluster, lookups=True) class ClusterFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() type: Annotated['ClusterTypeFilter', strawberry.lazy('virtualization.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -96,7 +96,7 @@ class VirtualMachineFilter( TenancyFilterMixin, PrimaryModelFilter, ): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() virtual_machine_type: ( Annotated['VirtualMachineTypeFilter', strawberry.lazy('virtualization.graphql.filters')] | None ) = strawberry_django.filter_field() @@ -138,7 +138,7 @@ class VirtualMachineFilter( disk: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) - serial: StrFilterLookup[str] | None = strawberry_django.filter_field() + serial: StrFilterLookup | None = strawberry_django.filter_field() interface_count: FilterLookup[int] | None = strawberry_django.filter_field() virtual_disk_count: FilterLookup[int] | None = strawberry_django.filter_field() interfaces: Annotated['VMInterfaceFilter', strawberry.lazy('virtualization.graphql.filters')] | None = ( diff --git a/netbox/vpn/graphql/filters.py b/netbox/vpn/graphql/filters.py index 6b0f89f52..9b068859c 100644 --- a/netbox/vpn/graphql/filters.py +++ b/netbox/vpn/graphql/filters.py @@ -63,7 +63,7 @@ class TunnelTerminationFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLo @strawberry_django.filter_type(models.Tunnel, lookups=True) class TunnelFilter(TenancyFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['TunnelStatusEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -89,7 +89,7 @@ class TunnelFilter(TenancyFilterMixin, PrimaryModelFilter): @strawberry_django.filter_type(models.IKEProposal, lookups=True) class IKEProposalFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() authentication_method: ( BaseFilterLookup[Annotated['AuthenticationMethodEnum', strawberry.lazy('vpn.graphql.enums')]] | None ) = ( @@ -118,7 +118,7 @@ class IKEProposalFilter(PrimaryModelFilter): @strawberry_django.filter_type(models.IKEPolicy, lookups=True) class IKEPolicyFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() version: BaseFilterLookup[Annotated['IKEVersionEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -128,12 +128,12 @@ class IKEPolicyFilter(PrimaryModelFilter): proposals: Annotated['IKEProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) - preshared_key: StrFilterLookup[str] | None = strawberry_django.filter_field() + preshared_key: StrFilterLookup | None = strawberry_django.filter_field() @strawberry_django.filter_type(models.IPSecProposal, lookups=True) class IPSecProposalFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() encryption_algorithm: ( BaseFilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None ) = ( @@ -159,7 +159,7 @@ class IPSecProposalFilter(PrimaryModelFilter): @strawberry_django.filter_type(models.IPSecPolicy, lookups=True) class IPSecPolicyFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() proposals: Annotated['IPSecProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( strawberry_django.filter_field() ) @@ -170,7 +170,7 @@ class IPSecPolicyFilter(PrimaryModelFilter): @strawberry_django.filter_type(models.IPSecProfile, lookups=True) class IPSecProfileFilter(PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() mode: BaseFilterLookup[Annotated['IPSecModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -186,8 +186,8 @@ class IPSecProfileFilter(PrimaryModelFilter): @strawberry_django.filter_type(models.L2VPN, lookups=True) class L2VPNFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter): - name: StrFilterLookup[str] | None = strawberry_django.filter_field() - slug: StrFilterLookup[str] | None = strawberry_django.filter_field() + name: StrFilterLookup | None = strawberry_django.filter_field() + slug: StrFilterLookup | None = strawberry_django.filter_field() type: BaseFilterLookup[Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( strawberry_django.filter_field() ) diff --git a/netbox/wireless/graphql/filter_mixins.py b/netbox/wireless/graphql/filter_mixins.py index 9e928b3a5..0bad507e3 100644 --- a/netbox/wireless/graphql/filter_mixins.py +++ b/netbox/wireless/graphql/filter_mixins.py @@ -21,4 +21,4 @@ class WirelessAuthenticationFilterMixin: auth_cipher: Annotated['WirelessAuthCipherEnum', strawberry.lazy('wireless.graphql.enums')] | None = ( strawberry_django.filter_field() ) - auth_psk: StrFilterLookup[str] | None = strawberry_django.filter_field() + auth_psk: StrFilterLookup | None = strawberry_django.filter_field() diff --git a/netbox/wireless/graphql/filters.py b/netbox/wireless/graphql/filters.py index 004d169ab..3bcef7725 100644 --- a/netbox/wireless/graphql/filters.py +++ b/netbox/wireless/graphql/filters.py @@ -38,7 +38,7 @@ class WirelessLANFilter( TenancyFilterMixin, PrimaryModelFilter ): - ssid: StrFilterLookup[str] | None = strawberry_django.filter_field() + ssid: StrFilterLookup | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) @@ -65,7 +65,7 @@ class WirelessLinkFilter( strawberry_django.filter_field() ) interface_b_id: ID | None = strawberry_django.filter_field() - ssid: StrFilterLookup[str] | None = strawberry_django.filter_field() + ssid: StrFilterLookup | None = strawberry_django.filter_field() status: BaseFilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = ( strawberry_django.filter_field() ) diff --git a/requirements.txt b/requirements.txt index 374861243..61c35722f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ social-auth-app-django==5.9.0 social-auth-core==4.8.7 sorl-thumbnail==13.0.0 strawberry-graphql==0.316.0 -strawberry-graphql-django==0.85.0 +strawberry-graphql-django==0.86.1 svgwrite==1.4.3 tablib==3.9.0 tzdata==2026.2