Просмотр исходного кода

chore(ruff): Enable RET rules and add explicit fallbacks

Adopt Ruff `RET` to improve return-flow consistency across the codebase.
Simplify control flow by removing redundant `else` blocks after
`return`, and add explicit `return None` (or equivalent) fallbacks
where appropriate to preserve existing behavior.

Fixes #21411
Martin Hauser 19 часов назад
Родитель
Сommit
ef52ac4203
77 измененных файлов с 249 добавлено и 249 удалено
  1. 2 3
      netbox/account/views.py
  2. 2 0
      netbox/circuits/models/virtual_circuits.py
  3. 7 5
      netbox/core/api/schema.py
  4. 3 3
      netbox/core/api/serializers_/object_types.py
  5. 1 2
      netbox/core/api/views.py
  6. 1 1
      netbox/core/management/commands/nbshell.py
  7. 1 0
      netbox/core/models/data.py
  8. 1 2
      netbox/core/models/files.py
  9. 1 1
      netbox/core/models/jobs.py
  10. 4 1
      netbox/core/models/object_types.py
  11. 2 0
      netbox/dcim/api/serializers_/base.py
  12. 18 16
      netbox/dcim/api/views.py
  13. 14 22
      netbox/dcim/filtersets.py
  14. 1 1
      netbox/dcim/forms/bulk_edit.py
  15. 2 4
      netbox/dcim/forms/bulk_import.py
  16. 3 3
      netbox/dcim/forms/model_forms.py
  17. 5 6
      netbox/dcim/graphql/filters.py
  18. 3 0
      netbox/dcim/graphql/gfk_mixins.py
  19. 5 3
      netbox/dcim/models/cables.py
  20. 5 5
      netbox/dcim/models/device_components.py
  21. 11 12
      netbox/dcim/models/devices.py
  22. 1 0
      netbox/dcim/models/mixins.py
  23. 3 4
      netbox/dcim/svg/cables.py
  24. 2 4
      netbox/extras/api/serializers_/scripts.py
  25. 1 1
      netbox/extras/dashboard/widgets.py
  26. 1 0
      netbox/extras/forms/bulk_import.py
  27. 1 0
      netbox/extras/forms/model_forms.py
  28. 1 2
      netbox/extras/lookups.py
  29. 1 2
      netbox/extras/models/mixins.py
  30. 1 2
      netbox/extras/models/models.py
  31. 4 4
      netbox/extras/views.py
  32. 4 5
      netbox/extras/webhooks.py
  33. 3 3
      netbox/ipam/api/serializers_/ip.py
  34. 9 12
      netbox/ipam/filtersets.py
  35. 2 4
      netbox/ipam/forms/bulk_import.py
  36. 1 1
      netbox/ipam/forms/model_forms.py
  37. 1 1
      netbox/ipam/lookups.py
  38. 6 4
      netbox/ipam/models/ip.py
  39. 1 1
      netbox/ipam/views.py
  40. 3 2
      netbox/netbox/api/authentication.py
  41. 2 2
      netbox/netbox/api/fields.py
  42. 1 2
      netbox/netbox/api/pagination.py
  43. 2 3
      netbox/netbox/authentication/__init__.py
  44. 4 4
      netbox/netbox/filtersets.py
  45. 9 10
      netbox/netbox/graphql/filter_lookups.py
  46. 1 2
      netbox/netbox/graphql/types.py
  47. 1 2
      netbox/netbox/graphql/views.py
  48. 7 6
      netbox/netbox/middleware.py
  49. 2 1
      netbox/netbox/models/features.py
  50. 1 1
      netbox/netbox/object_actions.py
  51. 1 0
      netbox/netbox/search/__init__.py
  52. 1 1
      netbox/netbox/search/backends.py
  53. 6 0
      netbox/netbox/tables/columns.py
  54. 16 8
      netbox/netbox/tests/test_base_classes.py
  55. 10 12
      netbox/netbox/views/generic/bulk_views.py
  56. 3 6
      netbox/netbox/views/generic/object_views.py
  57. 1 0
      netbox/netbox/views/generic/utils.py
  58. 1 2
      netbox/users/filtersets.py
  59. 2 0
      netbox/users/models/tokens.py
  60. 8 9
      netbox/utilities/fields.py
  61. 1 1
      netbox/utilities/forms/fields/expandable.py
  62. 1 1
      netbox/utilities/forms/utils.py
  63. 1 2
      netbox/utilities/html.py
  64. 1 1
      netbox/utilities/jobs.py
  65. 1 0
      netbox/utilities/proxy.py
  66. 1 1
      netbox/utilities/query.py
  67. 1 0
      netbox/utilities/rqworker.py
  68. 4 3
      netbox/utilities/tables.py
  69. 2 3
      netbox/utilities/templatetags/builtins/filters.py
  70. 2 3
      netbox/utilities/templatetags/form_helpers.py
  71. 5 7
      netbox/utilities/templatetags/helpers.py
  72. 1 1
      netbox/utilities/testing/filtersets.py
  73. 2 3
      netbox/utilities/testing/views.py
  74. 1 2
      netbox/virtualization/forms/bulk_import.py
  75. 3 4
      netbox/virtualization/models/virtualmachines.py
  76. 3 4
      netbox/vpn/models/l2vpn.py
  77. 2 0
      ruff.toml

+ 2 - 3
netbox/account/views.py

@@ -140,9 +140,8 @@ class LoginView(View):
 
 
             return response
             return response
 
 
-        else:
-            username = form['username'].value()
-            logger.debug(f"Login form validation failed for username: {remove_linebreaks(username)}")
+        username = form['username'].value()
+        logger.debug(f"Login form validation failed for username: {remove_linebreaks(username)}")
 
 
         return render(request, self.template_name, {
         return render(request, self.template_name, {
             'form': form,
             'form': form,

+ 2 - 0
netbox/circuits/models/virtual_circuits.py

@@ -185,6 +185,8 @@ class VirtualCircuitTermination(
             return self.virtual_circuit.terminations.filter(
             return self.virtual_circuit.terminations.filter(
                 role=VirtualCircuitTerminationRoleChoices.ROLE_HUB
                 role=VirtualCircuitTerminationRoleChoices.ROLE_HUB
             )
             )
+        # Fallback for unexpected roles
+        return self.virtual_circuit.terminations.none()
 
 
     def clean(self):
     def clean(self):
         super().clean()
         super().clean()

+ 7 - 5
netbox/core/api/schema.py

@@ -39,7 +39,7 @@ class ChoiceFieldFix(OpenApiSerializerFieldExtension):
         if direction == 'request':
         if direction == 'request':
             return build_cf
             return build_cf
 
 
-        elif direction == "response":
+        if direction == "response":
             value = build_cf
             value = build_cf
             label = {
             label = {
                 **build_basic_type(OpenApiTypes.STR),
                 **build_basic_type(OpenApiTypes.STR),
@@ -53,6 +53,10 @@ class ChoiceFieldFix(OpenApiSerializerFieldExtension):
                 }
                 }
             )
             )
 
 
+        # TODO: This function should never implicitly/explicitly return `None`
+        # The fallback should be well-defined (drf-spectacular expects request/response naming).
+        return None
+
 
 
 def viewset_handles_bulk_create(view):
 def viewset_handles_bulk_create(view):
     """Check if view automatically provides list-based bulk create"""
     """Check if view automatically provides list-based bulk create"""
@@ -75,8 +79,7 @@ class NetBoxAutoSchema(AutoSchema):
     def is_bulk_action(self):
     def is_bulk_action(self):
         if hasattr(self.view, "action") and self.view.action in BULK_ACTIONS:
         if hasattr(self.view, "action") and self.view.action in BULK_ACTIONS:
             return True
             return True
-        else:
-            return False
+        return False
 
 
     def get_operation_id(self):
     def get_operation_id(self):
         """
         """
@@ -316,8 +319,7 @@ class FixSerializedPKRelatedField(OpenApiSerializerFieldExtension):
         if direction == "response":
         if direction == "response":
             component = auto_schema.resolve_serializer(self.target.serializer, direction)
             component = auto_schema.resolve_serializer(self.target.serializer, direction)
             return component.ref if component else None
             return component.ref if component else None
-        else:
-            return build_basic_type(OpenApiTypes.INT)
+        return build_basic_type(OpenApiTypes.INT)
 
 
 
 
 class FixIntegerRangeSerializerSchema(OpenApiSerializerExtension):
 class FixIntegerRangeSerializerSchema(OpenApiSerializerExtension):

+ 3 - 3
netbox/core/api/serializers_/object_types.py

@@ -34,14 +34,14 @@ class ObjectTypeSerializer(BaseModelSerializer):
     @extend_schema_field(OpenApiTypes.STR)
     @extend_schema_field(OpenApiTypes.STR)
     def get_rest_api_endpoint(self, obj):
     def get_rest_api_endpoint(self, obj):
         if not (model := obj.model_class()):
         if not (model := obj.model_class()):
-            return
+            return None
         try:
         try:
             return get_action_url(model, action='list', rest_api=True)
             return get_action_url(model, action='list', rest_api=True)
         except NoReverseMatch:
         except NoReverseMatch:
-            return
+            return None
 
 
     @extend_schema_field(OpenApiTypes.STR)
     @extend_schema_field(OpenApiTypes.STR)
     def get_description(self, obj):
     def get_description(self, obj):
         if not (model := obj.model_class()):
         if not (model := obj.model_class()):
-            return
+            return None
         return inspect.getdoc(model)
         return inspect.getdoc(model)

+ 1 - 2
netbox/core/api/views.py

@@ -285,5 +285,4 @@ class BackgroundTaskViewSet(BaseRQViewSet):
         stopped_jobs = stop_rq_job(id)
         stopped_jobs = stop_rq_job(id)
         if len(stopped_jobs) == 1:
         if len(stopped_jobs) == 1:
             return HttpResponse(status=200)
             return HttpResponse(status=200)
-        else:
-            return HttpResponse(status=204)
+        return HttpResponse(status=204)

+ 1 - 1
netbox/core/management/commands/nbshell.py

@@ -144,7 +144,7 @@ class Command(BaseCommand):
         # If Python code has been passed, execute it and exit.
         # If Python code has been passed, execute it and exit.
         if options['command']:
         if options['command']:
             exec(options['command'], namespace)
             exec(options['command'], namespace)
-            return
+            return None
 
 
         # Try to enable tab-complete
         # Try to enable tab-complete
         try:
         try:

+ 1 - 0
netbox/core/models/data.py

@@ -98,6 +98,7 @@ class DataSource(JobsMixin, PrimaryModel):
     def get_type_display(self):
     def get_type_display(self):
         if backend := registry['data_backends'].get(self.type):
         if backend := registry['data_backends'].get(self.type):
             return backend.label
             return backend.label
+        return None
 
 
     def get_status_color(self):
     def get_status_color(self):
         return DataSourceStatusChoices.colors.get(self.status)
         return DataSourceStatusChoices.colors.get(self.status)

+ 1 - 2
netbox/core/models/files.py

@@ -79,8 +79,7 @@ class ManagedFile(SyncedDataMixin, models.Model):
                 'scripts': settings.SCRIPTS_ROOT,
                 'scripts': settings.SCRIPTS_ROOT,
                 'reports': settings.REPORTS_ROOT,
                 'reports': settings.REPORTS_ROOT,
             }[self.file_root]
             }[self.file_root]
-        else:
-            return ""
+        return ""
 
 
     def sync_data(self):
     def sync_data(self):
         if self.data_file:
         if self.data_file:

+ 1 - 1
netbox/core/models/jobs.py

@@ -146,7 +146,7 @@ class Job(models.Model):
         if self.object_type:
         if self.object_type:
             if self.object_type.model == 'reportmodule':
             if self.object_type.model == 'reportmodule':
                 return reverse('extras:report_result', kwargs={'job_pk': self.pk})
                 return reverse('extras:report_result', kwargs={'job_pk': self.pk})
-            elif self.object_type.model == 'scriptmodule':
+            if self.object_type.model == 'scriptmodule':
                 return reverse('extras:script_result', kwargs={'job_pk': self.pk})
                 return reverse('extras:script_result', kwargs={'job_pk': self.pk})
         return reverse('core:job', args=[self.pk])
         return reverse('core:job', args=[self.pk])
 
 

+ 4 - 1
netbox/core/models/object_types.py

@@ -218,19 +218,22 @@ class ObjectType(ContentType):
     def app_verbose_name(self):
     def app_verbose_name(self):
         if model := self.model_class():
         if model := self.model_class():
             return model._meta.app_config.verbose_name
             return model._meta.app_config.verbose_name
+        return None
 
 
     @property
     @property
     def model_verbose_name(self):
     def model_verbose_name(self):
         if model := self.model_class():
         if model := self.model_class():
             return model._meta.verbose_name
             return model._meta.verbose_name
+        return None
 
 
     @property
     @property
     def model_verbose_name_plural(self):
     def model_verbose_name_plural(self):
         if model := self.model_class():
         if model := self.model_class():
             return model._meta.verbose_name_plural
             return model._meta.verbose_name_plural
+        return None
 
 
     @property
     @property
     def is_plugin_model(self):
     def is_plugin_model(self):
         if not (model := self.model_class()):
         if not (model := self.model_class()):
-            return  # Return null if model class is invalid
+            return None  # Return null if model class is invalid
         return isinstance(model._meta.app_config, PluginConfig)
         return isinstance(model._meta.app_config, PluginConfig)

+ 2 - 0
netbox/dcim/api/serializers_/base.py

@@ -23,6 +23,7 @@ class ConnectedEndpointsSerializer(serializers.ModelSerializer):
     def get_connected_endpoints_type(self, obj):
     def get_connected_endpoints_type(self, obj):
         if endpoints := obj.connected_endpoints:
         if endpoints := obj.connected_endpoints:
             return f'{endpoints[0]._meta.app_label}.{endpoints[0]._meta.model_name}'
             return f'{endpoints[0]._meta.app_label}.{endpoints[0]._meta.model_name}'
+        return None
 
 
     @extend_schema_field(serializers.ListField(allow_null=True))
     @extend_schema_field(serializers.ListField(allow_null=True))
     def get_connected_endpoints(self, obj):
     def get_connected_endpoints(self, obj):
@@ -33,6 +34,7 @@ class ConnectedEndpointsSerializer(serializers.ModelSerializer):
             serializer = get_serializer_for_model(endpoints[0])
             serializer = get_serializer_for_model(endpoints[0])
             context = {'request': self.context['request']}
             context = {'request': self.context['request']}
             return serializer(endpoints, nested=True, many=True, context=context).data
             return serializer(endpoints, nested=True, many=True, context=context).data
+        return None
 
 
     @extend_schema_field(serializers.BooleanField)
     @extend_schema_field(serializers.BooleanField)
     def get_connected_endpoints_reachable(self, obj):
     def get_connected_endpoints_reachable(self, obj):

+ 18 - 16
netbox/dcim/api/views.py

@@ -222,24 +222,26 @@ class RackViewSet(NetBoxModelViewSet):
             )
             )
             return HttpResponse(drawing.tostring(), content_type='image/svg+xml')
             return HttpResponse(drawing.tostring(), content_type='image/svg+xml')
 
 
-        else:
-            # Return a JSON representation of the rack units in the elevation
-            elevation = rack.get_rack_units(
-                face=data['face'],
-                user=request.user,
-                exclude=data['exclude'],
-                expand_devices=data['expand_devices']
-            )
+        # Return a JSON representation of the rack units in the elevation
+        elevation = rack.get_rack_units(
+            face=data['face'],
+            user=request.user,
+            exclude=data['exclude'],
+            expand_devices=data['expand_devices']
+        )
+
+        # Enable filtering rack units by ID
+        if q := data['q']:
+            q = q.lower()
+            elevation = [u for u in elevation if q in str(u['id']) or q in str(u['name']).lower()]
 
 
-            # Enable filtering rack units by ID
-            if q := data['q']:
-                q = q.lower()
-                elevation = [u for u in elevation if q in str(u['id']) or q in str(u['name']).lower()]
+        page = self.paginate_queryset(elevation)
+        if page is not None:
+            rack_units = serializers.RackUnitSerializer(page, many=True, context={'request': request})
+            return self.get_paginated_response(rack_units.data)
 
 
-            page = self.paginate_queryset(elevation)
-            if page is not None:
-                rack_units = serializers.RackUnitSerializer(page, many=True, context={'request': request})
-                return self.get_paginated_response(rack_units.data)
+        # TODO: This endpoint should always return an HttpResponse/DRF Response; `None` is not a meaningful result.
+        return None
 
 
 
 
 #
 #

+ 14 - 22
netbox/dcim/filtersets.py

@@ -704,14 +704,12 @@ class DeviceTypeFilterSet(PrimaryModelFilterSet):
     def _has_front_image(self, queryset, name, value):
     def _has_front_image(self, queryset, name, value):
         if value:
         if value:
             return queryset.exclude(front_image='')
             return queryset.exclude(front_image='')
-        else:
-            return queryset.filter(front_image='')
+        return queryset.filter(front_image='')
 
 
     def _has_rear_image(self, queryset, name, value):
     def _has_rear_image(self, queryset, name, value):
         if value:
         if value:
             return queryset.exclude(rear_image='')
             return queryset.exclude(rear_image='')
-        else:
-            return queryset.filter(rear_image='')
+        return queryset.filter(rear_image='')
 
 
     def _console_ports(self, queryset, name, value):
     def _console_ports(self, queryset, name, value):
         return queryset.exclude(consoleporttemplates__isnull=value)
         return queryset.exclude(consoleporttemplates__isnull=value)
@@ -1855,8 +1853,7 @@ class CabledObjectFilterSet(django_filters.FilterSet):
     def filter_occupied(self, queryset, name, value):
     def filter_occupied(self, queryset, name, value):
         if value:
         if value:
             return queryset.filter(Q(cable__isnull=False) | Q(mark_connected=True))
             return queryset.filter(Q(cable__isnull=False) | Q(mark_connected=True))
-        else:
-            return queryset.filter(cable__isnull=True, mark_connected=False)
+        return queryset.filter(cable__isnull=True, mark_connected=False)
 
 
 
 
 class PathEndpointFilterSet(django_filters.FilterSet):
 class PathEndpointFilterSet(django_filters.FilterSet):
@@ -1867,8 +1864,7 @@ class PathEndpointFilterSet(django_filters.FilterSet):
     def filter_connected(self, queryset, name, value):
     def filter_connected(self, queryset, name, value):
         if value:
         if value:
             return queryset.filter(_path__is_active=True)
             return queryset.filter(_path__is_active=True)
-        else:
-            return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False))
+        return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False))
 
 
 
 
 @register_filterset
 @register_filterset
@@ -2045,8 +2041,7 @@ class MACAddressFilterSet(PrimaryModelFilterSet):
         }
         }
         if value:
         if value:
             return queryset.exclude(**params)
             return queryset.exclude(**params)
-        else:
-            return queryset.filter(**params)
+        return queryset.filter(**params)
 
 
     def filter_primary(self, queryset, name, value):
     def filter_primary(self, queryset, name, value):
         interface_mac_ids = Interface.objects.filter(primary_mac_address_id__isnull=False).values_list(
         interface_mac_ids = Interface.objects.filter(primary_mac_address_id__isnull=False).values_list(
@@ -2058,8 +2053,7 @@ class MACAddressFilterSet(PrimaryModelFilterSet):
         query = Q(pk__in=interface_mac_ids) | Q(pk__in=vminterface_mac_ids)
         query = Q(pk__in=interface_mac_ids) | Q(pk__in=vminterface_mac_ids)
         if value:
         if value:
             return queryset.filter(query)
             return queryset.filter(query)
-        else:
-            return queryset.exclude(query)
+        return queryset.exclude(query)
 
 
 
 
 class CommonInterfaceFilterSet(django_filters.FilterSet):
 class CommonInterfaceFilterSet(django_filters.FilterSet):
@@ -2302,12 +2296,11 @@ class InterfaceFilterSet(
                 Q(wireless_link__isnull=False) |
                 Q(wireless_link__isnull=False) |
                 Q(mark_connected=True)
                 Q(mark_connected=True)
             )
             )
-        else:
-            return queryset.filter(
-                cable__isnull=True,
-                wireless_link__isnull=True,
-                mark_connected=False
-            )
+        return queryset.filter(
+            cable__isnull=True,
+            wireless_link__isnull=True,
+            mark_connected=False
+        )
 
 
 
 
 @register_filterset
 @register_filterset
@@ -2677,10 +2670,9 @@ class CableFilterSet(TenancyFilterSet, PrimaryModelFilterSet):
                 .values("id")
                 .values("id")
             )
             )
             return queryset.exclude(id__in=terminated_ids)
             return queryset.exclude(id__in=terminated_ids)
-        else:
-            return queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A).filter(
-                terminations__cable_end=CableEndChoices.SIDE_B
-            )
+        return queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A).filter(
+            terminations__cable_end=CableEndChoices.SIDE_B
+        )
 
 
     def filter_by_termination_object(self, queryset, model, value):
     def filter_by_termination_object(self, queryset, model, value):
         # Filter by specific termination object(s)
         # Filter by specific termination object(s)

+ 1 - 1
netbox/dcim/forms/bulk_edit.py

@@ -1598,7 +1598,7 @@ class InterfaceBulkEditForm(
         if not self.cleaned_data['mode']:
         if not self.cleaned_data['mode']:
             if self.cleaned_data['untagged_vlan']:
             if self.cleaned_data['untagged_vlan']:
                 raise forms.ValidationError({'untagged_vlan': _("Interface mode must be specified to assign VLANs")})
                 raise forms.ValidationError({'untagged_vlan': _("Interface mode must be specified to assign VLANs")})
-            elif self.cleaned_data['tagged_vlans']:
+            if self.cleaned_data['tagged_vlans']:
                 raise forms.ValidationError({'tagged_vlans': _("Interface mode must be specified to assign VLANs")})
                 raise forms.ValidationError({'tagged_vlans': _("Interface mode must be specified to assign VLANs")})
 
 
         # Untagged interfaces cannot be assigned tagged VLANs
         # Untagged interfaces cannot be assigned tagged VLANs

+ 2 - 4
netbox/dcim/forms/bulk_import.py

@@ -796,8 +796,7 @@ class ModuleImportForm(ModuleCommonForm, PrimaryModelImportForm):
         # Make sure replicate_components is True when it's not included in the uploaded data
         # Make sure replicate_components is True when it's not included in the uploaded data
         if 'replicate_components' not in self.data:
         if 'replicate_components' not in self.data:
             return True
             return True
-        else:
-            return self.cleaned_data['replicate_components']
+        return self.cleaned_data['replicate_components']
 
 
 
 
 #
 #
@@ -1079,8 +1078,7 @@ class InterfaceImportForm(OwnerCSVMixin, NetBoxModelImportForm):
         # Make sure enabled is True when it's not included in the uploaded data
         # Make sure enabled is True when it's not included in the uploaded data
         if 'enabled' not in self.data:
         if 'enabled' not in self.data:
             return True
             return True
-        else:
-            return self.cleaned_data['enabled']
+        return self.cleaned_data['enabled']
 
 
     def clean_vdcs(self):
     def clean_vdcs(self):
         for vdc in self.cleaned_data['vdcs']:
         for vdc in self.cleaned_data['vdcs']:

+ 3 - 3
netbox/dcim/forms/model_forms.py

@@ -1360,7 +1360,7 @@ class InventoryItemTemplateForm(ComponentTemplateForm):
         ]
         ]
         if len(selected_objects) > 1:
         if len(selected_objects) > 1:
             raise forms.ValidationError(_("An InventoryItem can only be assigned to a single component."))
             raise forms.ValidationError(_("An InventoryItem can only be assigned to a single component."))
-        elif selected_objects:
+        if selected_objects:
             self.instance.component = self.cleaned_data[selected_objects[0]]
             self.instance.component = self.cleaned_data[selected_objects[0]]
         else:
         else:
             self.instance.component = None
             self.instance.component = None
@@ -1846,7 +1846,7 @@ class InventoryItemForm(DeviceComponentForm):
         ]
         ]
         if len(selected_objects) > 1:
         if len(selected_objects) > 1:
             raise forms.ValidationError(_("An InventoryItem can only be assigned to a single component."))
             raise forms.ValidationError(_("An InventoryItem can only be assigned to a single component."))
-        elif selected_objects:
+        if selected_objects:
             self.instance.component = self.cleaned_data[selected_objects[0]]
             self.instance.component = self.cleaned_data[selected_objects[0]]
         else:
         else:
             self.instance.component = None
             self.instance.component = None
@@ -1981,7 +1981,7 @@ class MACAddressForm(PrimaryModelForm):
             raise forms.ValidationError({
             raise forms.ValidationError({
                 selected_objects[1]: _("A MAC address can only be assigned to a single object.")
                 selected_objects[1]: _("A MAC address can only be assigned to a single object.")
             })
             })
-        elif selected_objects:
+        if selected_objects:
             self.instance.assigned_object = self.cleaned_data[selected_objects[0]]
             self.instance.assigned_object = self.cleaned_data[selected_objects[0]]
         else:
         else:
             self.instance.assigned_object = None
             self.instance.assigned_object = None

+ 5 - 6
netbox/dcim/graphql/filters.py

@@ -486,8 +486,7 @@ class MACAddressFilter(PrimaryModelFilter):
         query = Q(**{f'{prefix}pk__in': interface_mac_ids}) | Q(**{f'{prefix}pk__in': vminterface_mac_ids})
         query = Q(**{f'{prefix}pk__in': interface_mac_ids}) | Q(**{f'{prefix}pk__in': vminterface_mac_ids})
         if value:
         if value:
             return Q(query)
             return Q(query)
-        else:
-            return ~Q(query)
+        return ~Q(query)
 
 
 
 
 @strawberry_django.filter_type(models.Interface, lookups=True)
 @strawberry_django.filter_type(models.Interface, lookups=True)
@@ -571,8 +570,7 @@ class InterfaceFilter(
     def connected(self, queryset, value: bool, prefix: str):
     def connected(self, queryset, value: bool, prefix: str):
         if value is True:
         if value is True:
             return queryset, Q(**{f"{prefix}_path__is_active": True})
             return queryset, Q(**{f"{prefix}_path__is_active": True})
-        else:
-            return queryset, Q(**{f"{prefix}_path__isnull": True}) | Q(**{f"{prefix}_path__is_active": False})
+        return queryset, Q(**{f"{prefix}_path__isnull": True}) | Q(**{f"{prefix}_path__is_active": False})
 
 
     @strawberry_django.filter_field
     @strawberry_django.filter_field
     def kind(
     def kind(
@@ -583,10 +581,11 @@ class InterfaceFilter(
     ):
     ):
         if value == InterfaceKindEnum.KIND_PHYSICAL:
         if value == InterfaceKindEnum.KIND_PHYSICAL:
             return queryset, ~Q(**{f"{prefix}type__in": NONCONNECTABLE_IFACE_TYPES})
             return queryset, ~Q(**{f"{prefix}type__in": NONCONNECTABLE_IFACE_TYPES})
-        elif value == InterfaceKindEnum.KIND_VIRTUAL:
+        if value == InterfaceKindEnum.KIND_VIRTUAL:
             return queryset, Q(**{f"{prefix}type__in": VIRTUAL_IFACE_TYPES})
             return queryset, Q(**{f"{prefix}type__in": VIRTUAL_IFACE_TYPES})
-        elif value == InterfaceKindEnum.KIND_WIRELESS:
+        if value == InterfaceKindEnum.KIND_WIRELESS:
             return queryset, Q(**{f"{prefix}type__in": WIRELESS_IFACE_TYPES})
             return queryset, Q(**{f"{prefix}type__in": WIRELESS_IFACE_TYPES})
+        return queryset, Q()
 
 
 
 
 @strawberry_django.filter_type(models.InterfaceTemplate, lookups=True)
 @strawberry_django.filter_type(models.InterfaceTemplate, lookups=True)

+ 3 - 0
netbox/dcim/graphql/gfk_mixins.py

@@ -66,6 +66,7 @@ class InventoryItemTemplateComponentType:
             return PowerPortTemplateType
             return PowerPortTemplateType
         if type(instance) is RearPortTemplate:
         if type(instance) is RearPortTemplate:
             return RearPortTemplateType
             return RearPortTemplateType
+        return None
 
 
 
 
 class InventoryItemComponentType:
 class InventoryItemComponentType:
@@ -96,6 +97,7 @@ class InventoryItemComponentType:
             return PowerPortType
             return PowerPortType
         if type(instance) is RearPort:
         if type(instance) is RearPort:
             return RearPortType
             return RearPortType
+        return None
 
 
 
 
 class ConnectedEndpointType:
 class ConnectedEndpointType:
@@ -135,3 +137,4 @@ class ConnectedEndpointType:
             return ProviderNetworkType
             return ProviderNetworkType
         if type(instance) is RearPort:
         if type(instance) is RearPort:
             return RearPortType
             return RearPortType
+        return None

+ 5 - 3
netbox/dcim/models/cables.py

@@ -673,12 +673,14 @@ class CablePath(models.Model):
         if self.path:
         if self.path:
             ct_id, _ = decompile_path_node(self.path[0][0])
             ct_id, _ = decompile_path_node(self.path[0][0])
             return ContentType.objects.get_for_id(ct_id)
             return ContentType.objects.get_for_id(ct_id)
+        return None
 
 
     @property
     @property
     def destination_type(self):
     def destination_type(self):
         if self.is_complete:
         if self.is_complete:
             ct_id, _ = decompile_path_node(self.path[-1][0])
             ct_id, _ = decompile_path_node(self.path[-1][0])
             return ContentType.objects.get_for_id(ct_id)
             return ContentType.objects.get_for_id(ct_id)
+        return None
 
 
     @property
     @property
     def _path_decompiled(self):
     def _path_decompiled(self):
@@ -921,7 +923,7 @@ class CablePath(models.Model):
 
 
                 if not circuit_terminations.exists():
                 if not circuit_terminations.exists():
                     break
                     break
-                elif all([ct._provider_network for ct in circuit_terminations]):
+                if all([ct._provider_network for ct in circuit_terminations]):
                     # Circuit terminates to a ProviderNetwork
                     # Circuit terminates to a ProviderNetwork
                     path.extend([
                     path.extend([
                         [object_to_path_node(ct) for ct in circuit_terminations],
                         [object_to_path_node(ct) for ct in circuit_terminations],
@@ -929,14 +931,14 @@ class CablePath(models.Model):
                     ])
                     ])
                     is_complete = True
                     is_complete = True
                     break
                     break
-                elif all([ct.termination and not ct.cable for ct in circuit_terminations]):
+                if all([ct.termination and not ct.cable for ct in circuit_terminations]):
                     # Circuit terminates to a Region/Site/etc.
                     # Circuit terminates to a Region/Site/etc.
                     path.extend([
                     path.extend([
                         [object_to_path_node(ct) for ct in circuit_terminations],
                         [object_to_path_node(ct) for ct in circuit_terminations],
                         [object_to_path_node(ct.termination) for ct in circuit_terminations],
                         [object_to_path_node(ct.termination) for ct in circuit_terminations],
                     ])
                     ])
                     break
                     break
-                elif any([ct.cable in links for ct in circuit_terminations]):
+                if any([ct.cable in links for ct in circuit_terminations]):
                     # No valid path
                     # No valid path
                     is_split = True
                     is_split = True
                     break
                     break

+ 5 - 5
netbox/dcim/models/device_components.py

@@ -731,6 +731,7 @@ class BaseInterface(models.Model):
     def mac_address(self):
     def mac_address(self):
         if self.primary_mac_address:
         if self.primary_mac_address:
             return self.primary_mac_address.mac_address
             return self.primary_mac_address.mac_address
+        return None
 
 
 
 
 class Interface(
 class Interface(
@@ -943,7 +944,7 @@ class Interface(
                         "The selected parent interface ({interface}) belongs to a different device ({device})"
                         "The selected parent interface ({interface}) belongs to a different device ({device})"
                     ).format(interface=self.parent, device=self.parent.device)
                     ).format(interface=self.parent, device=self.parent.device)
                 })
                 })
-            elif self.parent.device.virtual_chassis != self.device.virtual_chassis:
+            if self.parent.device.virtual_chassis != self.device.virtual_chassis:
                 raise ValidationError({
                 raise ValidationError({
                     'parent': _(
                     'parent': _(
                         "The selected parent interface ({interface}) belongs to {device}, which is not part of "
                         "The selected parent interface ({interface}) belongs to {device}, which is not part of "
@@ -965,7 +966,7 @@ class Interface(
                         "The selected bridge interface ({bridge}) belongs to a different device ({device})."
                         "The selected bridge interface ({bridge}) belongs to a different device ({device})."
                     ).format(bridge=self.bridge, device=self.bridge.device)
                     ).format(bridge=self.bridge, device=self.bridge.device)
                 })
                 })
-            elif self.bridge.device.virtual_chassis != self.device.virtual_chassis:
+            if self.bridge.device.virtual_chassis != self.device.virtual_chassis:
                 raise ValidationError({
                 raise ValidationError({
                     'bridge': _(
                     'bridge': _(
                         "The selected bridge interface ({interface}) belongs to {device}, which is not part of virtual "
                         "The selected bridge interface ({interface}) belongs to {device}, which is not part of virtual "
@@ -993,7 +994,7 @@ class Interface(
                         "The selected LAG interface ({lag}) belongs to a different device ({device})."
                         "The selected LAG interface ({lag}) belongs to a different device ({device})."
                     ).format(lag=self.lag, device=self.lag.device)
                     ).format(lag=self.lag, device=self.lag.device)
                 })
                 })
-            elif self.lag.device.virtual_chassis != self.device.virtual_chassis:
+            if self.lag.device.virtual_chassis != self.device.virtual_chassis:
                 raise ValidationError({
                 raise ValidationError({
                     'lag': _(
                     'lag': _(
                         "The selected LAG interface ({lag}) belongs to {device}, which is not part of virtual chassis "
                         "The selected LAG interface ({lag}) belongs to {device}, which is not part of virtual chassis "
@@ -1085,8 +1086,7 @@ class Interface(
             # Return the opposite side of the attached wireless link
             # Return the opposite side of the attached wireless link
             if self.wireless_link.interface_a == self:
             if self.wireless_link.interface_a == self:
                 return [self.wireless_link.interface_b]
                 return [self.wireless_link.interface_b]
-            else:
-                return [self.wireless_link.interface_a]
+            return [self.wireless_link.interface_a]
         return []
         return []
 
 
     @property
     @property

+ 11 - 12
netbox/dcim/models/devices.py

@@ -762,11 +762,11 @@ class Device(
     def __str__(self):
     def __str__(self):
         if self.label and self.asset_tag:
         if self.label and self.asset_tag:
             return f'{self.label} ({self.asset_tag})'
             return f'{self.label} ({self.asset_tag})'
-        elif self.label:
+        if self.label:
             return self.label
             return self.label
-        elif self.device_type and self.asset_tag:
+        if self.device_type and self.asset_tag:
             return f'{self.device_type.manufacturer} {self.device_type.model} ({self.asset_tag})'
             return f'{self.device_type.manufacturer} {self.device_type.model} ({self.asset_tag})'
-        elif self.device_type:
+        if self.device_type:
             return f'{self.device_type.manufacturer} {self.device_type.model} ({self.pk})'
             return f'{self.device_type.manufacturer} {self.device_type.model} ({self.pk})'
         return super().__str__()
         return super().__str__()
 
 
@@ -1046,6 +1046,7 @@ class Device(
             return self.name
             return self.name
         if self.virtual_chassis:
         if self.virtual_chassis:
             return f'{self.virtual_chassis.name}:{self.vc_position}'
             return f'{self.virtual_chassis.name}:{self.vc_position}'
+        return None
 
 
     @property
     @property
     def identifier(self):
     def identifier(self):
@@ -1058,12 +1059,11 @@ class Device(
     def primary_ip(self):
     def primary_ip(self):
         if ConfigItem('PREFER_IPV4')() and self.primary_ip4:
         if ConfigItem('PREFER_IPV4')() and self.primary_ip4:
             return self.primary_ip4
             return self.primary_ip4
-        elif self.primary_ip6:
+        if self.primary_ip6:
             return self.primary_ip6
             return self.primary_ip6
-        elif self.primary_ip4:
+        if self.primary_ip4:
             return self.primary_ip4
             return self.primary_ip4
-        else:
-            return None
+        return None
 
 
     @property
     @property
     def interfaces_count(self):
     def interfaces_count(self):
@@ -1278,12 +1278,11 @@ class VirtualDeviceContext(PrimaryModel):
     def primary_ip(self):
     def primary_ip(self):
         if ConfigItem('PREFER_IPV4')() and self.primary_ip4:
         if ConfigItem('PREFER_IPV4')() and self.primary_ip4:
             return self.primary_ip4
             return self.primary_ip4
-        elif self.primary_ip6:
+        if self.primary_ip6:
             return self.primary_ip6
             return self.primary_ip6
-        elif self.primary_ip4:
+        if self.primary_ip4:
             return self.primary_ip4
             return self.primary_ip4
-        else:
-            return None
+        return None
 
 
     def clean(self):
     def clean(self):
         super().clean()
         super().clean()
@@ -1369,7 +1368,7 @@ class MACAddress(PrimaryModel):
                     raise ValidationError(
                     raise ValidationError(
                         _("Cannot unassign MAC Address while it is designated as the primary MAC for an object")
                         _("Cannot unassign MAC Address while it is designated as the primary MAC for an object")
                     )
                     )
-                elif original_assigned_object != assigned_object:
+                if original_assigned_object != assigned_object:
                     raise ValidationError(
                     raise ValidationError(
                         _("Cannot reassign MAC Address while it is designated as the primary MAC for an object")
                         _("Cannot reassign MAC Address while it is designated as the primary MAC for an object")
                     )
                     )

+ 1 - 0
netbox/dcim/models/mixins.py

@@ -35,6 +35,7 @@ class RenderConfigMixin(models.Model):
             return self.role.config_template
             return self.role.config_template
         if self.platform and self.platform.config_template:
         if self.platform and self.platform.config_template:
             return self.platform.config_template
             return self.platform.config_template
+        return None
 
 
 
 
 class CachedScopeMixin(models.Model):
 class CachedScopeMixin(models.Model):

+ 3 - 4
netbox/dcim/svg/cables.py

@@ -190,11 +190,10 @@ class CableTraceSVG:
         if hasattr(instance, 'role'):
         if hasattr(instance, 'role'):
             # Device
             # Device
             return instance.role.color
             return instance.role.color
-        elif instance._meta.model_name == 'circuit' and instance.type.color:
+        if instance._meta.model_name == 'circuit' and instance.type.color:
             return instance.type.color
             return instance.type.color
-        else:
-            # Other parent object
-            return 'e0e0e0'
+        # Other parent object
+        return 'e0e0e0'
 
 
     def draw_parent_objects(self, obj_list):
     def draw_parent_objects(self, obj_list):
         """
         """

+ 2 - 4
netbox/extras/api/serializers_/scripts.py

@@ -32,8 +32,7 @@ class ScriptSerializer(ValidatedModelSerializer):
             return {
             return {
                 k: v.__class__.__name__ for k, v in obj.python_class()._get_vars().items()
                 k: v.__class__.__name__ for k, v in obj.python_class()._get_vars().items()
             }
             }
-        else:
-            return {}
+        return {}
 
 
     @extend_schema_field(serializers.CharField())
     @extend_schema_field(serializers.CharField())
     def get_display(self, obj):
     def get_display(self, obj):
@@ -43,8 +42,7 @@ class ScriptSerializer(ValidatedModelSerializer):
     def get_description(self, obj):
     def get_description(self, obj):
         if obj.python_class:
         if obj.python_class:
             return obj.python_class().description
             return obj.python_class().description
-        else:
-            return None
+        return None
 
 
 
 
 class ScriptDetailSerializer(ScriptSerializer):
 class ScriptDetailSerializer(ScriptSerializer):

+ 1 - 1
netbox/extras/dashboard/widgets.py

@@ -278,7 +278,7 @@ class ObjectListWidget(DashboardWidget):
         model = ObjectType.objects.get_by_natural_key(app_label, model_name).model_class()
         model = ObjectType.objects.get_by_natural_key(app_label, model_name).model_class()
         if not model:
         if not model:
             logger.debug(f"Dashboard Widget model_class not found: {app_label}:{model_name}")
             logger.debug(f"Dashboard Widget model_class not found: {app_label}:{model_name}")
-            return
+            return None
 
 
         # Evaluate user's permission. Note that this controls only whether the HTMX element is
         # Evaluate user's permission. Note that this controls only whether the HTMX element is
         # embedded on the page: The view itself will also evaluate permissions separately.
         # embedded on the page: The view itself will also evaluate permissions separately.

+ 1 - 0
netbox/extras/forms/bulk_import.py

@@ -117,6 +117,7 @@ class CustomFieldChoiceSetImportForm(OwnerCSVMixin, CSVModelForm):
                     value, label = line, line
                     value, label = line, line
                 data.append((value, label))
                 data.append((value, label))
             return data
             return data
+        return None
 
 
 
 
 class CustomLinkImportForm(OwnerCSVMixin, CSVModelForm):
 class CustomLinkImportForm(OwnerCSVMixin, CSVModelForm):

+ 1 - 0
netbox/extras/forms/model_forms.py

@@ -390,6 +390,7 @@ class TableConfigForm(forms.ModelForm):
             return columns.split(',') if type(columns) is str else columns
             return columns.split(',') if type(columns) is str else columns
         if self.instance is not None:
         if self.instance is not None:
             return self.instance.columns
             return self.instance.columns
+        return None
 
 
 
 
 class BookmarkForm(forms.ModelForm):
 class BookmarkForm(forms.ModelForm):

+ 1 - 2
netbox/extras/lookups.py

@@ -45,8 +45,7 @@ class Empty(Lookup):
         sql, params = compiler.compile(self.lhs)
         sql, params = compiler.compile(self.lhs)
         if self.rhs:
         if self.rhs:
             return f"CAST(LENGTH({sql}) AS BOOLEAN) IS NOT TRUE", params
             return f"CAST(LENGTH({sql}) AS BOOLEAN) IS NOT TRUE", params
-        else:
-            return f"CAST(LENGTH({sql}) AS BOOLEAN) IS TRUE", params
+        return f"CAST(LENGTH({sql}) AS BOOLEAN) IS TRUE", params
 
 
 
 
 class JSONEmpty(Lookup):
 class JSONEmpty(Lookup):

+ 1 - 2
netbox/extras/models/mixins.py

@@ -58,8 +58,7 @@ class PythonModuleMixin:
         if name == '__init__':
         if name == '__init__':
             # File is a package
             # File is a package
             return os.path.basename(path)
             return os.path.basename(path)
-        else:
-            return name
+        return name
 
 
     def get_module(self):
     def get_module(self):
         """
         """

+ 1 - 2
netbox/extras/models/models.py

@@ -291,8 +291,7 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, OwnerMixin, Ch
         """
         """
         if self.body_template:
         if self.body_template:
             return render_jinja2(self.body_template, context)
             return render_jinja2(self.body_template, context)
-        else:
-            return json.dumps(context, cls=JSONEncoder)
+        return json.dumps(context, cls=JSONEncoder)
 
 
     def render_payload_url(self, context):
     def render_payload_url(self, context):
         """
         """

+ 4 - 4
netbox/extras/views.py

@@ -1470,10 +1470,9 @@ class BaseScriptView(generic.ObjectView):
     def get_object(self, **kwargs):
     def get_object(self, **kwargs):
         if pk := kwargs.get('pk', False):
         if pk := kwargs.get('pk', False):
             return get_object_or_404(self.queryset, pk=pk)
             return get_object_or_404(self.queryset, pk=pk)
-        elif (module := kwargs.get('module')) and (name := kwargs.get('name', False)):
+        if (module := kwargs.get('module')) and (name := kwargs.get('name', False)):
             return get_object_or_404(self.queryset, module__file_path=f'{module}.py', name=name)
             return get_object_or_404(self.queryset, module__file_path=f'{module}.py', name=name)
-        else:
-            raise Http404
+        raise Http404
 
 
     def _get_script_class(self, script):
     def _get_script_class(self, script):
         """
         """
@@ -1481,6 +1480,7 @@ class BaseScriptView(generic.ObjectView):
         """
         """
         if script_class := script.python_class:
         if script_class := script.python_class:
             return script_class()
             return script_class()
+        return None
 
 
 
 
 class ScriptView(BaseScriptView):
 class ScriptView(BaseScriptView):
@@ -1674,7 +1674,7 @@ class ScriptResultView(TableMixin, generic.ObjectView):
             response['Content-Disposition'] = f'attachment; filename="{filename}"'
             response['Content-Disposition'] = f'attachment; filename="{filename}"'
             return response
             return response
 
 
-        elif job.completed:
+        if job.completed:
             table = self.get_table(job, request, bulk_actions=False)
             table = self.get_table(job, request, bulk_actions=False)
 
 
         log_threshold = request.GET.get('log_threshold', LogLevelChoices.LOG_INFO)
         log_threshold = request.GET.get('log_threshold', LogLevelChoices.LOG_INFO)

+ 4 - 5
netbox/extras/webhooks.py

@@ -124,8 +124,7 @@ def send_webhook(event_rule, object_type, event_type, data, timestamp, username,
     if 200 <= response.status_code <= 299:
     if 200 <= response.status_code <= 299:
         logger.info(f"Request succeeded; response status {response.status_code}")
         logger.info(f"Request succeeded; response status {response.status_code}")
         return f"Status {response.status_code} returned, webhook successfully processed."
         return f"Status {response.status_code} returned, webhook successfully processed."
-    else:
-        logger.warning(f"Request failed; response status {response.status_code}: {response.content}")
-        raise requests.exceptions.RequestException(
-            f"Status {response.status_code} returned with content '{response.content}', webhook FAILED to process."
-        )
+    logger.warning(f"Request failed; response status {response.status_code}: {response.content}")
+    raise requests.exceptions.RequestException(
+        f"Status {response.status_code} returned with content '{response.content}', webhook FAILED to process."
+    )

+ 3 - 3
netbox/ipam/api/serializers_/ip.py

@@ -95,7 +95,7 @@ class PrefixLengthSerializer(serializers.Serializer):
             raise serializers.ValidationError({
             raise serializers.ValidationError({
                 'prefix_length': 'Invalid prefix length ({}) for IPv4'.format(requested_prefix)
                 'prefix_length': 'Invalid prefix length ({}) for IPv4'.format(requested_prefix)
             })
             })
-        elif prefix.family == 6 and requested_prefix > 128:
+        if prefix.family == 6 and requested_prefix > 128:
             raise serializers.ValidationError({
             raise serializers.ValidationError({
                 'prefix_length': 'Invalid prefix length ({}) for IPv6'.format(requested_prefix)
                 'prefix_length': 'Invalid prefix length ({}) for IPv6'.format(requested_prefix)
             })
             })
@@ -174,11 +174,11 @@ class AvailableIPRequestSerializer(serializers.Serializer):
                     parent.mask_length
                     parent.mask_length
                 )
                 )
             })
             })
-        elif parent.family == 4 and prefix_length > 32:
+        if parent.family == 4 and prefix_length > 32:
             raise serializers.ValidationError({
             raise serializers.ValidationError({
                 'prefix_length': 'Invalid prefix length ({}) for IPv6'.format(prefix_length)
                 'prefix_length': 'Invalid prefix length ({}) for IPv6'.format(prefix_length)
             })
             })
-        elif parent.family == 6 and prefix_length > 128:
+        if parent.family == 6 and prefix_length > 128:
             raise serializers.ValidationError({
             raise serializers.ValidationError({
                 'prefix_length': 'Invalid prefix length ({}) for IPv4'.format(prefix_length)
                 'prefix_length': 'Invalid prefix length ({}) for IPv4'.format(prefix_length)
             })
             })

+ 9 - 12
netbox/ipam/filtersets.py

@@ -473,8 +473,7 @@ class PrefixFilterSet(PrimaryModelFilterSet, ScopedFilterSet, TenancyFilterSet,
             if '/' in value:
             if '/' in value:
                 return queryset.filter(prefix__net_contains_or_equals=str(netaddr.IPNetwork(value).cidr))
                 return queryset.filter(prefix__net_contains_or_equals=str(netaddr.IPNetwork(value).cidr))
             # Searching by IP address
             # Searching by IP address
-            else:
-                return queryset.filter(prefix__net_contains=str(netaddr.IPAddress(value)))
+            return queryset.filter(prefix__net_contains=str(netaddr.IPAddress(value)))
         except (AddrFormatError, ValueError):
         except (AddrFormatError, ValueError):
             return queryset.none()
             return queryset.none()
 
 
@@ -809,11 +808,10 @@ class IPAddressFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFi
                 assigned_object_type__in=content_types,
                 assigned_object_type__in=content_types,
                 assigned_object_id__isnull=False
                 assigned_object_id__isnull=False
             )
             )
-        else:
-            return queryset.exclude(
-                assigned_object_type__in=content_types,
-                assigned_object_id__isnull=False
-            )
+        return queryset.exclude(
+            assigned_object_type__in=content_types,
+            assigned_object_id__isnull=False
+        )
 
 
     def _assigned(self, queryset, name, value):
     def _assigned(self, queryset, name, value):
         if value:
         if value:
@@ -821,11 +819,10 @@ class IPAddressFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFi
                 assigned_object_type__isnull=True,
                 assigned_object_type__isnull=True,
                 assigned_object_id__isnull=True
                 assigned_object_id__isnull=True
             )
             )
-        else:
-            return queryset.filter(
-                assigned_object_type__isnull=True,
-                assigned_object_id__isnull=True
-            )
+        return queryset.filter(
+            assigned_object_type__isnull=True,
+            assigned_object_id__isnull=True
+        )
 
 
 
 
 @register_filterset
 @register_filterset

+ 2 - 4
netbox/ipam/forms/bulk_import.py

@@ -372,15 +372,13 @@ class IPAddressImportForm(PrimaryModelImportForm):
         # Make sure is_primary is None when it's not included in the uploaded data
         # Make sure is_primary is None when it's not included in the uploaded data
         if 'is_primary' not in self.data:
         if 'is_primary' not in self.data:
             return None
             return None
-        else:
-            return self.cleaned_data['is_primary']
+        return self.cleaned_data['is_primary']
 
 
     def clean_is_oob(self):
     def clean_is_oob(self):
         # Make sure is_oob is None when it's not included in the uploaded data
         # Make sure is_oob is None when it's not included in the uploaded data
         if 'is_oob' not in self.data:
         if 'is_oob' not in self.data:
             return None
             return None
-        else:
-            return self.cleaned_data['is_oob']
+        return self.cleaned_data['is_oob']
 
 
     def clean(self):
     def clean(self):
         super().clean()
         super().clean()

+ 1 - 1
netbox/ipam/forms/model_forms.py

@@ -392,7 +392,7 @@ class IPAddressForm(TenancyForm, PrimaryModelForm):
             raise forms.ValidationError({
             raise forms.ValidationError({
                 selected_objects[1]: _("An IP address can only be assigned to a single object.")
                 selected_objects[1]: _("An IP address can only be assigned to a single object.")
             })
             })
-        elif selected_objects:
+        if selected_objects:
             assigned_object = self.cleaned_data[selected_objects[0]]
             assigned_object = self.cleaned_data[selected_objects[0]]
             if self.instance.pk and self.instance.assigned_object and assigned_object != self.instance.assigned_object:
             if self.instance.pk and self.instance.assigned_object and assigned_object != self.instance.assigned_object:
                 if self.cleaned_data['primary_for_parent']:
                 if self.cleaned_data['primary_for_parent']:

+ 1 - 1
netbox/ipam/lookups.py

@@ -122,7 +122,7 @@ class NetIn(Lookup):
 
 
         if with_mask and not without_mask:
         if with_mask and not without_mask:
             return address_in_clause, with_mask
             return address_in_clause, with_mask
-        elif not with_mask and without_mask:
+        if not with_mask and without_mask:
             return host_in_clause, without_mask
             return host_in_clause, without_mask
 
 
         in_clause = '({}) OR ({})'.format(address_in_clause, host_in_clause)
         in_clause = '({}) OR ({})'.format(address_in_clause, host_in_clause)

+ 6 - 4
netbox/ipam/models/ip.py

@@ -167,6 +167,7 @@ class Aggregate(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel):
     def ipv6_full(self):
     def ipv6_full(self):
         if self.prefix and self.prefix.version == 6:
         if self.prefix and self.prefix.version == 6:
             return netaddr.IPAddress(self.prefix).format(netaddr.ipv6_full)
             return netaddr.IPAddress(self.prefix).format(netaddr.ipv6_full)
+        return None
 
 
     def get_child_prefixes(self):
     def get_child_prefixes(self):
         """
         """
@@ -344,6 +345,7 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, CachedScopeMixin, Primary
     def ipv6_full(self):
     def ipv6_full(self):
         if self.prefix and self.prefix.version == 6:
         if self.prefix and self.prefix.version == 6:
             return netaddr.IPAddress(self.prefix).format(netaddr.ipv6_full)
             return netaddr.IPAddress(self.prefix).format(netaddr.ipv6_full)
+        return None
 
 
     @property
     @property
     def depth(self):
     def depth(self):
@@ -395,8 +397,7 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, CachedScopeMixin, Primary
         """
         """
         if self.vrf is None and self.status == PrefixStatusChoices.STATUS_CONTAINER:
         if self.vrf is None and self.status == PrefixStatusChoices.STATUS_CONTAINER:
             return Prefix.objects.filter(prefix__net_contained=str(self.prefix))
             return Prefix.objects.filter(prefix__net_contained=str(self.prefix))
-        else:
-            return Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf)
+        return Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf)
 
 
     def get_child_ranges(self, **kwargs):
     def get_child_ranges(self, **kwargs):
         """
         """
@@ -416,8 +417,7 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, CachedScopeMixin, Primary
         """
         """
         if self.vrf is None and self.status == PrefixStatusChoices.STATUS_CONTAINER:
         if self.vrf is None and self.status == PrefixStatusChoices.STATUS_CONTAINER:
             return IPAddress.objects.filter(address__net_host_contained=str(self.prefix))
             return IPAddress.objects.filter(address__net_host_contained=str(self.prefix))
-        else:
-            return IPAddress.objects.filter(address__net_host_contained=str(self.prefix), vrf=self.vrf)
+        return IPAddress.objects.filter(address__net_host_contained=str(self.prefix), vrf=self.vrf)
 
 
     def get_available_ips(self):
     def get_available_ips(self):
         """
         """
@@ -827,6 +827,7 @@ class IPAddress(ContactsMixin, PrimaryModel):
     def ipv6_full(self):
     def ipv6_full(self):
         if self.address and self.address.version == 6:
         if self.address and self.address.version == 6:
             return netaddr.IPAddress(self.address).format(netaddr.ipv6_full)
             return netaddr.IPAddress(self.address).format(netaddr.ipv6_full)
+        return None
 
 
     def get_duplicates(self):
     def get_duplicates(self):
         return IPAddress.objects.filter(
         return IPAddress.objects.filter(
@@ -852,6 +853,7 @@ class IPAddress(ContactsMixin, PrimaryModel):
                 ])
                 ])
                 if available_ips:
                 if available_ips:
                     return next(iter(available_ips))
                     return next(iter(available_ips))
+        return None
 
 
     def get_related_ips(self):
     def get_related_ips(self):
         """
         """

+ 1 - 1
netbox/ipam/views.py

@@ -923,7 +923,7 @@ class IPAddressEditView(generic.ObjectEditView):
     def get_extra_addanother_params(self, request):
     def get_extra_addanother_params(self, request):
         if 'interface' in request.GET:
         if 'interface' in request.GET:
             return {'interface': request.GET['interface']}
             return {'interface': request.GET['interface']}
-        elif 'vminterface' in request.GET:
+        if 'vminterface' in request.GET:
             return {'vminterface': request.GET['vminterface']}
             return {'vminterface': request.GET['vminterface']}
         return {}
         return {}
 
 

+ 3 - 2
netbox/netbox/api/authentication.py

@@ -25,10 +25,10 @@ class TokenAuthentication(BaseAuthentication):
     def authenticate(self, request):
     def authenticate(self, request):
         # Authorization header is not present; ignore
         # Authorization header is not present; ignore
         if not (auth := get_authorization_header(request).split()):
         if not (auth := get_authorization_header(request).split()):
-            return
+            return None
         # Unrecognized header; ignore
         # Unrecognized header; ignore
         if auth[0].lower() not in (V1_KEYWORD.lower().encode(), V2_KEYWORD.lower().encode()):
         if auth[0].lower() not in (V1_KEYWORD.lower().encode(), V2_KEYWORD.lower().encode()):
-            return
+            return None
         # Check for extraneous token content
         # Check for extraneous token content
         if len(auth) != 2:
         if len(auth) != 2:
             raise exceptions.AuthenticationFailed(
             raise exceptions.AuthenticationFailed(
@@ -150,6 +150,7 @@ class TokenPermissions(DjangoObjectPermissions):
         # If token authentication is in use, verify that the token allows write operations (for unsafe methods).
         # If token authentication is in use, verify that the token allows write operations (for unsafe methods).
         if request.method in SAFE_METHODS or request.auth.write_enabled:
         if request.method in SAFE_METHODS or request.auth.write_enabled:
             return True
             return True
+        return False
 
 
     def has_permission(self, request, view):
     def has_permission(self, request, view):
 
 

+ 2 - 2
netbox/netbox/api/fields.py

@@ -47,8 +47,7 @@ class ChoiceField(serializers.Field):
         if data is None:
         if data is None:
             if self.allow_null:
             if self.allow_null:
                 return True, None
                 return True, None
-            else:
-                data = ''
+            data = ''
         return super().validate_empty_values(data)
         return super().validate_empty_values(data)
 
 
     def to_representation(self, obj):
     def to_representation(self, obj):
@@ -59,6 +58,7 @@ class ChoiceField(serializers.Field):
                 'value': obj,
                 'value': obj,
                 'label': self._choices.get(obj, ''),
                 'label': self._choices.get(obj, ''),
             }
             }
+        return None
 
 
     def to_internal_value(self, data):
     def to_internal_value(self, data):
         if data == '':
         if data == '':

+ 1 - 2
netbox/netbox/api/pagination.py

@@ -40,8 +40,7 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
 
 
         if self.limit:
         if self.limit:
             return list(queryset[self.offset:self.offset + self.limit])
             return list(queryset[self.offset:self.offset + self.limit])
-        else:
-            return list(queryset[self.offset:])
+        return list(queryset[self.offset:])
 
 
     def get_limit(self, request):
     def get_limit(self, request):
         max_limit = self.default_limit
         max_limit = self.default_limit

+ 2 - 3
netbox/netbox/authentication/__init__.py

@@ -211,7 +211,7 @@ class RemoteUserBackend(_RemoteUserBackend):
         logger.debug(
         logger.debug(
             f"trying to authenticate {remote_user} with groups {remote_groups}")
             f"trying to authenticate {remote_user} with groups {remote_groups}")
         if not remote_user:
         if not remote_user:
-            return
+            return None
         user = None
         user = None
         username = self.clean_username(remote_user)
         username = self.clean_username(remote_user)
 
 
@@ -235,8 +235,7 @@ class RemoteUserBackend(_RemoteUserBackend):
                     return self.configure_groups(user, remote_groups)
                     return self.configure_groups(user, remote_groups)
             else:
             else:
                 return user
                 return user
-        else:
-            return None
+        return None
 
 
     def _is_superuser(self, user):
     def _is_superuser(self, user):
         logger = logging.getLogger('netbox.auth.RemoteUserBackend')
         logger = logging.getLogger('netbox.auth.RemoteUserBackend')

+ 4 - 4
netbox/netbox/filtersets.py

@@ -138,13 +138,13 @@ class BaseFilterSet(django_filters.FilterSet):
         )):
         )):
             return FILTER_NUMERIC_BASED_LOOKUP_MAP
             return FILTER_NUMERIC_BASED_LOOKUP_MAP
 
 
-        elif isinstance(existing_filter, (
+        if isinstance(existing_filter, (
             filters.TreeNodeMultipleChoiceFilter,
             filters.TreeNodeMultipleChoiceFilter,
         )):
         )):
             # TreeNodeMultipleChoiceFilter only support negation but must maintain the `in` lookup expression
             # TreeNodeMultipleChoiceFilter only support negation but must maintain the `in` lookup expression
             return FILTER_TREENODE_NEGATION_LOOKUP_MAP
             return FILTER_TREENODE_NEGATION_LOOKUP_MAP
 
 
-        elif isinstance(existing_filter, (
+        if isinstance(existing_filter, (
             django_filters.ModelChoiceFilter,
             django_filters.ModelChoiceFilter,
             django_filters.ModelMultipleChoiceFilter,
             django_filters.ModelMultipleChoiceFilter,
             TagFilter
             TagFilter
@@ -152,7 +152,7 @@ class BaseFilterSet(django_filters.FilterSet):
             # These filter types support only negation
             # These filter types support only negation
             return FILTER_NEGATION_LOOKUP_MAP
             return FILTER_NEGATION_LOOKUP_MAP
 
 
-        elif isinstance(existing_filter, (
+        if isinstance(existing_filter, (
             django_filters.filters.CharFilter,
             django_filters.filters.CharFilter,
             django_filters.ChoiceFilter,
             django_filters.ChoiceFilter,
             django_filters.MultipleChoiceFilter,
             django_filters.MultipleChoiceFilter,
@@ -387,7 +387,7 @@ class AttributeFiltersMixin:
 
 
     def _get_field_lookup(self, key):
     def _get_field_lookup(self, key):
         if not key.startswith(self.attribute_filter_prefix):
         if not key.startswith(self.attribute_filter_prefix):
-            return
+            return None
         lookup = key.split(self.attribute_filter_prefix, 1)[1]  # Strip prefix
         lookup = key.split(self.attribute_filter_prefix, 1)[1]  # Strip prefix
         return f'{self.attributes_field_name}__{lookup}'
         return f'{self.attributes_field_name}__{lookup}'
 
 

+ 9 - 10
netbox/netbox/graphql/filter_lookups.py

@@ -186,12 +186,11 @@ class TreeNodeFilter:
         # Handle different relationship types
         # Handle different relationship types
         if isinstance(model_field, (ManyToManyField, ManyToManyRel)):
         if isinstance(model_field, (ManyToManyField, ManyToManyRel)):
             return queryset, Q(**{f'{model_field_name}__in': related_model.objects.filter(q_filter)})
             return queryset, Q(**{f'{model_field_name}__in': related_model.objects.filter(q_filter)})
-        elif isinstance(model_field, ForeignKey):
+        if isinstance(model_field, ForeignKey):
             return queryset, Q(**{f'{model_field_name}__{k}': v for k, v in q_filter.children})
             return queryset, Q(**{f'{model_field_name}__{k}': v for k, v in q_filter.children})
-        elif isinstance(model_field, ManyToOneRel):
+        if isinstance(model_field, ManyToOneRel):
             return queryset, Q(**{f'{model_field_name}__in': related_model.objects.filter(q_filter)})
             return queryset, Q(**{f'{model_field_name}__in': related_model.objects.filter(q_filter)})
-        else:
-            return queryset, Q(**{f'{model_field_name}__{k}': v for k, v in q_filter.children})
+        return queryset, Q(**{f'{model_field_name}__{k}': v for k, v in q_filter.children})
 
 
 
 
 def generate_tree_node_q_filter(model_class, filter_value: TreeNodeFilter) -> Q:
 def generate_tree_node_q_filter(model_class, filter_value: TreeNodeFilter) -> Q:
@@ -205,17 +204,17 @@ def generate_tree_node_q_filter(model_class, filter_value: TreeNodeFilter) -> Q:
 
 
     if filter_value.match_type == TreeNodeMatch.EXACT:
     if filter_value.match_type == TreeNodeMatch.EXACT:
         return Q(id=filter_value.id)
         return Q(id=filter_value.id)
-    elif filter_value.match_type == TreeNodeMatch.DESCENDANTS:
+    if filter_value.match_type == TreeNodeMatch.DESCENDANTS:
         return Q(tree_id=node.tree_id, lft__gt=node.lft, rght__lt=node.rght)
         return Q(tree_id=node.tree_id, lft__gt=node.lft, rght__lt=node.rght)
-    elif filter_value.match_type == TreeNodeMatch.SELF_AND_DESCENDANTS:
+    if filter_value.match_type == TreeNodeMatch.SELF_AND_DESCENDANTS:
         return Q(tree_id=node.tree_id, lft__gte=node.lft, rght__lte=node.rght)
         return Q(tree_id=node.tree_id, lft__gte=node.lft, rght__lte=node.rght)
-    elif filter_value.match_type == TreeNodeMatch.CHILDREN:
+    if filter_value.match_type == TreeNodeMatch.CHILDREN:
         return Q(tree_id=node.tree_id, level=node.level + 1, lft__gt=node.lft, rght__lt=node.rght)
         return Q(tree_id=node.tree_id, level=node.level + 1, lft__gt=node.lft, rght__lt=node.rght)
-    elif filter_value.match_type == TreeNodeMatch.SIBLINGS:
+    if filter_value.match_type == TreeNodeMatch.SIBLINGS:
         return Q(tree_id=node.tree_id, level=node.level, parent=node.parent) & ~Q(id=node.id)
         return Q(tree_id=node.tree_id, level=node.level, parent=node.parent) & ~Q(id=node.id)
-    elif filter_value.match_type == TreeNodeMatch.ANCESTORS:
+    if filter_value.match_type == TreeNodeMatch.ANCESTORS:
         return Q(tree_id=node.tree_id, lft__lt=node.lft, rght__gt=node.rght)
         return Q(tree_id=node.tree_id, lft__lt=node.lft, rght__gt=node.rght)
-    elif filter_value.match_type == TreeNodeMatch.PARENT:
+    if filter_value.match_type == TreeNodeMatch.PARENT:
         return Q(id=node.parent_id) if node.parent_id else Q(pk__in=[])
         return Q(id=node.parent_id) if node.parent_id else Q(pk__in=[])
     return Q()
     return Q()
 
 

+ 1 - 2
netbox/netbox/graphql/types.py

@@ -34,8 +34,7 @@ class BaseObjectType:
         # Enforce object permissions on the queryset
         # Enforce object permissions on the queryset
         if hasattr(queryset, 'restrict'):
         if hasattr(queryset, 'restrict'):
             return queryset.restrict(info.context.request.user, 'view')
             return queryset.restrict(info.context.request.user, 'view')
-        else:
-            return queryset
+        return queryset
 
 
     @strawberry_django.field
     @strawberry_django.field
     def display(self) -> str:
     def display(self) -> str:

+ 1 - 2
netbox/netbox/graphql/views.py

@@ -37,7 +37,6 @@ class NetBoxGraphQLView(GraphQLView):
         if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
         if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
             if request.accepts("text/html"):
             if request.accepts("text/html"):
                 return redirect_to_login(reverse('graphql'))
                 return redirect_to_login(reverse('graphql'))
-            else:
-                return HttpResponseForbidden("No credentials provided.")
+            return HttpResponseForbidden("No credentials provided.")
 
 
         return super().dispatch(request, *args, **kwargs)
         return super().dispatch(request, *args, **kwargs)

+ 7 - 6
netbox/netbox/middleware.py

@@ -71,7 +71,7 @@ class CoreMiddleware:
         """
         """
         # Don't catch exceptions when in debug mode
         # Don't catch exceptions when in debug mode
         if settings.DEBUG:
         if settings.DEBUG:
-            return
+            return None
 
 
         # Cleanly handle exceptions that occur from REST API requests
         # Cleanly handle exceptions that occur from REST API requests
         if is_api_request(request):
         if is_api_request(request):
@@ -79,7 +79,7 @@ class CoreMiddleware:
 
 
         # Ignore Http404s (defer to Django's built-in 404 handling)
         # Ignore Http404s (defer to Django's built-in 404 handling)
         if isinstance(exception, Http404):
         if isinstance(exception, Http404):
-            return
+            return None
 
 
         # Determine the type of exception. If it's a common issue, return a custom error page with instructions.
         # Determine the type of exception. If it's a common issue, return a custom error page with instructions.
         custom_template = None
         custom_template = None
@@ -93,6 +93,7 @@ class CoreMiddleware:
         # Return a custom error message, or fall back to Django's default 500 error handling
         # Return a custom error message, or fall back to Django's default 500 error handling
         if custom_template:
         if custom_template:
             return handler_500(request, template_name=custom_template)
             return handler_500(request, template_name=custom_template)
+        return None
 
 
 
 
 class RemoteUserMiddleware(RemoteUserMiddleware_):
 class RemoteUserMiddleware(RemoteUserMiddleware_):
@@ -139,10 +140,9 @@ class RemoteUserMiddleware(RemoteUserMiddleware_):
         if request.user.is_authenticated:
         if request.user.is_authenticated:
             if request.user.get_username() == self.clean_username(username, request):
             if request.user.get_username() == self.clean_username(username, request):
                 return self.get_response(request)
                 return self.get_response(request)
-            else:
-                # An authenticated user is associated with the request, but
-                # it does not match the authorized user in the header.
-                self._remove_invalid_user(request)
+            # An authenticated user is associated with the request, but
+            # it does not match the authorized user in the header.
+            self._remove_invalid_user(request)
 
 
         # We are seeing this user for the first time in this session, attempt
         # We are seeing this user for the first time in this session, attempt
         # to authenticate the user.
         # to authenticate the user.
@@ -250,3 +250,4 @@ class MaintenanceModeMiddleware:
 
 
             messages.error(request, error_message)
             messages.error(request, error_message)
             return HttpResponseRedirect(request.path_info)
             return HttpResponseRedirect(request.path_info)
+        return None

+ 2 - 1
netbox/netbox/models/features.py

@@ -246,7 +246,7 @@ class CustomFieldsMixin(models.Model):
             # Skip hidden fields if 'omit_hidden' is True
             # Skip hidden fields if 'omit_hidden' is True
             if omit_hidden and field.ui_visible == CustomFieldUIVisibleChoices.HIDDEN:
             if omit_hidden and field.ui_visible == CustomFieldUIVisibleChoices.HIDDEN:
                 continue
                 continue
-            elif omit_hidden and field.ui_visible == CustomFieldUIVisibleChoices.IF_SET and not value:
+            if omit_hidden and field.ui_visible == CustomFieldUIVisibleChoices.IF_SET and not value:
                 continue
                 continue
 
 
             data[field] = field.deserialize(value)
             data[field] = field.deserialize(value)
@@ -611,6 +611,7 @@ class SyncedDataMixin(models.Model):
                 return DataFile.objects.get(source=self.data_source, path=self.data_path)
                 return DataFile.objects.get(source=self.data_source, path=self.data_path)
             except DataFile.DoesNotExist:
             except DataFile.DoesNotExist:
                 pass
                 pass
+        return None
 
 
     def sync(self, save=False):
     def sync(self, save=False):
         """
         """

+ 1 - 1
netbox/netbox/object_actions.py

@@ -49,7 +49,7 @@ class ObjectAction:
         try:
         try:
             return get_action_url(obj, action=cls.name, kwargs=kwargs)
             return get_action_url(obj, action=cls.name, kwargs=kwargs)
         except NoReverseMatch:
         except NoReverseMatch:
-            return
+            return None
 
 
     @classmethod
     @classmethod
     def get_url_params(cls, context):
     def get_url_params(cls, context):

+ 1 - 0
netbox/netbox/search/__init__.py

@@ -84,6 +84,7 @@ class SearchIndex:
         """
         """
         if value := getattr(instance, field_name):
         if value := getattr(instance, field_name):
             return str(value)
             return str(value)
+        return None
 
 
     @classmethod
     @classmethod
     def get_category(cls):
     def get_category(cls):

+ 1 - 1
netbox/netbox/search/backends.py

@@ -248,7 +248,7 @@ class CachedValueSearchBackend(SearchBackend):
         try:
         try:
             get_indexer(instance)
             get_indexer(instance)
         except KeyError:
         except KeyError:
-            return
+            return None
 
 
         ct = ContentType.objects.get_for_model(instance)
         ct = ContentType.objects.get_for_model(instance)
         qs = CachedValue.objects.filter(object_type=ct, object_id=instance.pk)
         qs = CachedValue.objects.filter(object_type=ct, object_id=instance.pk)

+ 6 - 0
netbox/netbox/tables/columns.py

@@ -61,15 +61,18 @@ class DateColumn(tables.Column):
     def render(self, value):
     def render(self, value):
         if value:
         if value:
             return value.isoformat()
             return value.isoformat()
+        return None
 
 
     def value(self, value):
     def value(self, value):
         if value:
         if value:
             return value.isoformat()
             return value.isoformat()
+        return None
 
 
     @classmethod
     @classmethod
     def from_field(cls, field, **kwargs):
     def from_field(cls, field, **kwargs):
         if isinstance(field, DateField):
         if isinstance(field, DateField):
             return cls(**kwargs)
             return cls(**kwargs)
+        return None
 
 
 
 
 @library.register
 @library.register
@@ -89,15 +92,18 @@ class DateTimeColumn(tables.Column):
             current_tz = zoneinfo.ZoneInfo(settings.TIME_ZONE)
             current_tz = zoneinfo.ZoneInfo(settings.TIME_ZONE)
             value = value.astimezone(current_tz)
             value = value.astimezone(current_tz)
             return f"{value.date().isoformat()} {value.time().isoformat(timespec=self.timespec)}"
             return f"{value.date().isoformat()} {value.time().isoformat(timespec=self.timespec)}"
+        return None
 
 
     def value(self, value):
     def value(self, value):
         if value:
         if value:
             return value.isoformat()
             return value.isoformat()
+        return None
 
 
     @classmethod
     @classmethod
     def from_field(cls, field, **kwargs):
     def from_field(cls, field, **kwargs):
         if isinstance(field, DateTimeField):
         if isinstance(field, DateTimeField):
             return cls(**kwargs)
             return cls(**kwargs)
+        return None
 
 
 
 
 class DurationColumn(tables.Column):
 class DurationColumn(tables.Column):

+ 16 - 8
netbox/netbox/tests/test_base_classes.py

@@ -70,7 +70,7 @@ class FormClassesTestCase(TestCase):
         Return the base form class for creating/editing the given model.
         Return the base form class for creating/editing the given model.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryModelForm
             return PrimaryModelForm
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -79,6 +79,7 @@ class FormClassesTestCase(TestCase):
             return NestedGroupModelForm
             return NestedGroupModelForm
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxModelForm
             return NetBoxModelForm
+        return None
 
 
     @staticmethod
     @staticmethod
     def get_bulk_edit_form_base_class(model):
     def get_bulk_edit_form_base_class(model):
@@ -86,7 +87,7 @@ class FormClassesTestCase(TestCase):
         Return the base form class for bulk editing the given model.
         Return the base form class for bulk editing the given model.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryModelBulkEditForm
             return PrimaryModelBulkEditForm
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -95,6 +96,7 @@ class FormClassesTestCase(TestCase):
             return NestedGroupModelBulkEditForm
             return NestedGroupModelBulkEditForm
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxModelBulkEditForm
             return NetBoxModelBulkEditForm
+        return None
 
 
     @staticmethod
     @staticmethod
     def get_import_form_base_class(model):
     def get_import_form_base_class(model):
@@ -102,7 +104,7 @@ class FormClassesTestCase(TestCase):
         Return the base form class for importing the given model.
         Return the base form class for importing the given model.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryModelImportForm
             return PrimaryModelImportForm
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -111,6 +113,7 @@ class FormClassesTestCase(TestCase):
             return NestedGroupModelImportForm
             return NestedGroupModelImportForm
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxModelImportForm
             return NetBoxModelImportForm
+        return None
 
 
     @staticmethod
     @staticmethod
     def get_filterset_form_base_class(model):
     def get_filterset_form_base_class(model):
@@ -118,7 +121,7 @@ class FormClassesTestCase(TestCase):
         Return the base form class for the given model's FilterSet.
         Return the base form class for the given model's FilterSet.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryModelFilterSetForm
             return PrimaryModelFilterSetForm
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -127,6 +130,7 @@ class FormClassesTestCase(TestCase):
             return NestedGroupModelFilterSetForm
             return NestedGroupModelFilterSetForm
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxModelFilterSetForm
             return NetBoxModelFilterSetForm
+        return None
 
 
     def test_model_form_base_classes(self):
     def test_model_form_base_classes(self):
         """
         """
@@ -182,7 +186,7 @@ class FilterSetClassesTestCase(TestCase):
         Return the base FilterSet class for the given model.
         Return the base FilterSet class for the given model.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryModelFilterSet
             return PrimaryModelFilterSet
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -191,6 +195,7 @@ class FilterSetClassesTestCase(TestCase):
             return NestedGroupModelFilterSet
             return NestedGroupModelFilterSet
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxModelFilterSet
             return NetBoxModelFilterSet
+        return None
 
 
     def test_model_filterset_base_classes(self):
     def test_model_filterset_base_classes(self):
         """
         """
@@ -222,7 +227,7 @@ class TableClassesTestCase(TestCase):
         Return the base table class for the given model.
         Return the base table class for the given model.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryModelTable
             return PrimaryModelTable
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -231,6 +236,7 @@ class TableClassesTestCase(TestCase):
             return NestedGroupModelTable
             return NestedGroupModelTable
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxTable
             return NetBoxTable
+        return None
 
 
     def test_model_table_base_classes(self):
     def test_model_table_base_classes(self):
         """
         """
@@ -266,7 +272,7 @@ class SerializerClassesTestCase(TestCase):
         Return the base serializer class for the given model.
         Return the base serializer class for the given model.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryModelSerializer
             return PrimaryModelSerializer
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -275,6 +281,7 @@ class SerializerClassesTestCase(TestCase):
             return NestedGroupModelSerializer
             return NestedGroupModelSerializer
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxModelSerializer
             return NetBoxModelSerializer
+        return None
 
 
     def test_model_serializer_base_classes(self):
     def test_model_serializer_base_classes(self):
         """
         """
@@ -306,7 +313,7 @@ class GraphQLTypeClassesTestCase(TestCase):
         Return the base GraphQL type for the given model.
         Return the base GraphQL type for the given model.
         """
         """
         if model._meta.app_label == 'dummy_plugin':
         if model._meta.app_label == 'dummy_plugin':
-            return
+            return None
         if issubclass(model, PrimaryModel):
         if issubclass(model, PrimaryModel):
             return PrimaryObjectType
             return PrimaryObjectType
         if issubclass(model, OrganizationalModel):
         if issubclass(model, OrganizationalModel):
@@ -315,6 +322,7 @@ class GraphQLTypeClassesTestCase(TestCase):
             return NestedGroupObjectType
             return NestedGroupObjectType
         if issubclass(model, NetBoxModel):
         if issubclass(model, NetBoxModel):
             return NetBoxObjectType
             return NetBoxObjectType
+        return None
 
 
     def test_model_type_base_classes(self):
     def test_model_type_base_classes(self):
         """
         """

+ 10 - 12
netbox/netbox/views/generic/bulk_views.py

@@ -169,22 +169,21 @@ class ObjectListView(BaseMultiObjectView, ActionsMixin, TableMixin):
                 return self.export_table(table, columns, delimiter=delimiter)
                 return self.export_table(table, columns, delimiter=delimiter)
 
 
             # Render an ExportTemplate
             # Render an ExportTemplate
-            elif request.GET['export']:
+            if request.GET['export']:
                 template = get_object_or_404(ExportTemplate, object_types=object_type, name=request.GET['export'])
                 template = get_object_or_404(ExportTemplate, object_types=object_type, name=request.GET['export'])
                 return self.export_template(template, request)
                 return self.export_template(template, request)
 
 
             # Check for YAML export support on the model
             # Check for YAML export support on the model
-            elif hasattr(model, 'to_yaml'):
+            if hasattr(model, 'to_yaml'):
                 response = HttpResponse(self.export_yaml(), content_type='text/yaml')
                 response = HttpResponse(self.export_yaml(), content_type='text/yaml')
                 filename = 'netbox_{}.yaml'.format(self.queryset.model._meta.verbose_name_plural)
                 filename = 'netbox_{}.yaml'.format(self.queryset.model._meta.verbose_name_plural)
                 response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
                 response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
                 return response
                 return response
 
 
             # Fall back to default table/YAML export
             # Fall back to default table/YAML export
-            else:
-                table = self.get_table(self.queryset, request, has_table_actions)
-                delimiter = request.user.config.get('csv_delimiter')
-                return self.export_table(table, delimiter=delimiter)
+            table = self.get_table(self.queryset, request, has_table_actions)
+            delimiter = request.user.config.get('csv_delimiter')
+            return self.export_table(table, delimiter=delimiter)
 
 
         # Render the objects table
         # Render the objects table
         table = self.get_table(self.queryset, request, has_table_actions)
         table = self.get_table(self.queryset, request, has_table_actions)
@@ -353,7 +352,7 @@ class BulkImportView(GetReturnURLMixin, BaseMultiObjectView):
         for field in form.visible_fields():
         for field in form.visible_fields():
             if field.is_hidden:
             if field.is_hidden:
                 continue
                 continue
-            elif field.field.required:
+            if field.field.required:
                 required_fields[field.name] = field.field
                 required_fields[field.name] = field.field
             else:
             else:
                 optional_fields[field.name] = field.field
                 optional_fields[field.name] = field.field
@@ -581,7 +580,7 @@ class BulkImportView(GetReturnURLMixin, BaseMultiObjectView):
                 # Handle background job
                 # Handle background job
                 if is_background_request(request):
                 if is_background_request(request):
                     request.job.logger.info(msg)
                     request.job.logger.info(msg)
-                    return
+                    return None
 
 
                 messages.success(request, msg)
                 messages.success(request, msg)
                 return redirect(f"{redirect_url}?modified_by_request={request.id}")
                 return redirect(f"{redirect_url}?modified_by_request={request.id}")
@@ -787,7 +786,7 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView):
                     # Handle background job
                     # Handle background job
                     if is_background_request(request):
                     if is_background_request(request):
                         request.job.logger.info(msg)
                         request.job.logger.info(msg)
-                        return
+                        return None
 
 
                     messages.success(self.request, msg)
                     messages.success(self.request, msg)
                     return redirect(self.get_return_url(request))
                     return redirect(self.get_return_url(request))
@@ -1010,7 +1009,7 @@ class BulkDeleteView(GetReturnURLMixin, BaseMultiObjectView):
                     # Handle background job
                     # Handle background job
                     if is_background_request(request):
                     if is_background_request(request):
                         request.job.logger.info(msg)
                         request.job.logger.info(msg)
-                        return
+                        return None
 
 
                     messages.success(request, msg)
                     messages.success(request, msg)
 
 
@@ -1032,8 +1031,7 @@ class BulkDeleteView(GetReturnURLMixin, BaseMultiObjectView):
 
 
                 return redirect(self.get_return_url(request))
                 return redirect(self.get_return_url(request))
 
 
-            else:
-                logger.debug("Form validation failed")
+            logger.debug("Form validation failed")
 
 
         else:
         else:
             form = BulkDeleteForm(model, initial={
             form = BulkDeleteForm(model, initial={

+ 3 - 6
netbox/netbox/views/generic/object_views.py

@@ -413,8 +413,7 @@ class ObjectDeleteView(GetReturnURLMixin, BaseObjectView):
             return HttpResponse(headers={
             return HttpResponse(headers={
                 'HX-Redirect': obj.get_absolute_url(),
                 'HX-Redirect': obj.get_absolute_url(),
             })
             })
-        else:
-            return redirect(obj.get_absolute_url())
+        return redirect(obj.get_absolute_url())
 
 
     #
     #
     # Request handlers
     # Request handlers
@@ -499,8 +498,7 @@ class ObjectDeleteView(GetReturnURLMixin, BaseObjectView):
                 return redirect(return_url)
                 return redirect(return_url)
             return redirect(self.get_return_url(request, obj))
             return redirect(self.get_return_url(request, obj))
 
 
-        else:
-            logger.debug("Form validation failed")
+        logger.debug("Form validation failed")
 
 
         return render(request, self.template_name, {
         return render(request, self.template_name, {
             'object': obj,
             'object': obj,
@@ -607,8 +605,7 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
                         # Redirect user on success
                         # Redirect user on success
                         if '_addanother' in request.POST and safe_for_redirect(request.get_full_path()):
                         if '_addanother' in request.POST and safe_for_redirect(request.get_full_path()):
                             return redirect(request.get_full_path())
                             return redirect(request.get_full_path())
-                        else:
-                            return redirect(self.get_return_url(request))
+                        return redirect(self.get_return_url(request))
 
 
                 except (AbortRequest, PermissionsViolation) as e:
                 except (AbortRequest, PermissionsViolation) as e:
                     logger.debug(e.message)
                     logger.debug(e.message)

+ 1 - 0
netbox/netbox/views/generic/utils.py

@@ -11,3 +11,4 @@ def get_prerequisite_model(queryset):
             model = apps.get_model(prereq)
             model = apps.get_model(prereq)
             if not model.objects.exists():
             if not model.objects.exists():
                 return model
                 return model
+    return None

+ 1 - 2
netbox/users/filtersets.py

@@ -250,8 +250,7 @@ class ObjectPermissionFilterSet(BaseFilterSet):
         action = name.split('_')[1]
         action = name.split('_')[1]
         if value:
         if value:
             return queryset.filter(actions__contains=[action])
             return queryset.filter(actions__contains=[action])
-        else:
-            return queryset.exclude(actions__contains=[action])
+        return queryset.exclude(actions__contains=[action])
 
 
 
 
 @register_filterset
 @register_filterset

+ 2 - 0
netbox/users/models/tokens.py

@@ -209,6 +209,7 @@ class Token(models.Model):
             return 'Token '
             return 'Token '
         if self.v2:
         if self.v2:
             return f'Bearer {TOKEN_PREFIX}{self.key}.'
             return f'Bearer {TOKEN_PREFIX}{self.key}.'
+        return None
 
 
     def clean(self):
     def clean(self):
         super().clean()
         super().clean()
@@ -288,6 +289,7 @@ class Token(models.Model):
                 return False
                 return False
             digest = hmac.new(pepper.encode('utf-8'), token.encode('utf-8'), hashlib.sha256).hexdigest()
             digest = hmac.new(pepper.encode('utf-8'), token.encode('utf-8'), hashlib.sha256).hexdigest()
             return digest == self.hmac_digest
             return digest == self.hmac_digest
+        return False
 
 
     def validate_client_ip(self, client_ip):
     def validate_client_ip(self, client_ip):
         """
         """

+ 8 - 9
netbox/utilities/fields.py

@@ -133,15 +133,14 @@ class RestrictedGenericForeignKey(GenericForeignKey):
             ct_id = getattr(obj, ct_attname)
             ct_id = getattr(obj, ct_attname)
             if ct_id is None:
             if ct_id is None:
                 return None
                 return None
-            else:
-                if model := self.get_content_type(
-                    id=ct_id, using=obj._state.db
-                ).model_class():
-                    return (
-                        model._meta.pk.get_prep_value(getattr(obj, self.fk_field)),
-                        model,
-                    )
-                return None
+            if model := self.get_content_type(
+                id=ct_id, using=obj._state.db
+            ).model_class():
+                return (
+                    model._meta.pk.get_prep_value(getattr(obj, self.fk_field)),
+                    model,
+                )
+            return None
 
 
         return (
         return (
             ret_val,
             ret_val,

+ 1 - 1
netbox/utilities/forms/fields/expandable.py

@@ -50,6 +50,6 @@ class ExpandableIPAddressField(forms.CharField):
         # Hackish address family detection but it's all we have to work with
         # Hackish address family detection but it's all we have to work with
         if '.' in value and re.search(IP4_EXPANSION_PATTERN, value):
         if '.' in value and re.search(IP4_EXPANSION_PATTERN, value):
             return list(expand_ipaddress_pattern(value, 4))
             return list(expand_ipaddress_pattern(value, 4))
-        elif ':' in value and re.search(IP6_EXPANSION_PATTERN, value):
+        if ':' in value and re.search(IP6_EXPANSION_PATTERN, value):
             return list(expand_ipaddress_pattern(value, 6))
             return list(expand_ipaddress_pattern(value, 6))
         return [value]
         return [value]

+ 1 - 1
netbox/utilities/forms/utils.py

@@ -139,7 +139,7 @@ def get_field_value(form, field_name):
 
 
     if form.is_bound and field_name in form.data:
     if form.is_bound and field_name in form.data:
         if (value := form.data[field_name]) is None:
         if (value := form.data[field_name]) is None:
-            return
+            return None
         if hasattr(field, 'valid_value') and field.valid_value(value):
         if hasattr(field, 'valid_value') and field.valid_value(value):
             return value
             return value
 
 

+ 1 - 2
netbox/utilities/html.py

@@ -37,8 +37,7 @@ def foreground_color(bg_color, dark='000000', light='ffffff'):
     r, g, b = [int(bg_color[c:c + 2], 16) for c in (0, 2, 4)]
     r, g, b = [int(bg_color[c:c + 2], 16) for c in (0, 2, 4)]
     if r * 0.299 + g * 0.587 + b * 0.114 > THRESHOLD:
     if r * 0.299 + g * 0.587 + b * 0.114 > THRESHOLD:
         return dark
         return dark
-    else:
-        return light
+    return light
 
 
 
 
 def highlight(value, highlight, trim_pre=None, trim_post=None, trim_placeholder='...'):
 def highlight(value, highlight, trim_pre=None, trim_post=None, trim_placeholder='...'):

+ 1 - 1
netbox/utilities/jobs.py

@@ -25,7 +25,7 @@ def process_request_as_job(view, request, name=None):
 
 
     # Check that the request that is not already being processed as a background job (would be a loop)
     # Check that the request that is not already being processed as a background job (would be a loop)
     if is_background_request(request):
     if is_background_request(request):
-        return
+        return None
 
 
     # Create a serializable copy of the original request
     # Create a serializable copy of the original request
     request_copy = copy_safe_request(request)
     request_copy = copy_safe_request(request)

+ 1 - 0
netbox/utilities/proxy.py

@@ -54,3 +54,4 @@ def resolve_proxies(url=None, protocol=None, context=None):
         router = import_string(item) if type(item) is str else item
         router = import_string(item) if type(item) is str else item
         if proxies := router().route(url=url, protocol=protocol, context=context):
         if proxies := router().route(url=url, protocol=protocol, context=context):
             return proxies
             return proxies
+    return None

+ 1 - 1
netbox/utilities/query.py

@@ -67,7 +67,7 @@ def reapply_model_ordering(queryset: QuerySet) -> QuerySet:
     # MPTT-based models are exempt from this; use caution when annotating querysets of these models
     # MPTT-based models are exempt from this; use caution when annotating querysets of these models
     if any(isinstance(manager, TreeManager) for manager in queryset.model._meta.local_managers):
     if any(isinstance(manager, TreeManager) for manager in queryset.model._meta.local_managers):
         return queryset
         return queryset
-    elif queryset.ordered:
+    if queryset.ordered:
         return queryset
         return queryset
 
 
     ordering = queryset.model._meta.ordering
     ordering = queryset.model._meta.ordering

+ 1 - 0
netbox/utilities/rqworker.py

@@ -34,3 +34,4 @@ def get_rq_retry():
     retry_interval = get_config().RQ_RETRY_INTERVAL
     retry_interval = get_config().RQ_RETRY_INTERVAL
     if retry_max:
     if retry_max:
         return Retry(max=retry_max, interval=retry_interval)
         return Retry(max=retry_max, interval=retry_interval)
+    return None

+ 4 - 3
netbox/utilities/tables.py

@@ -33,13 +33,13 @@ def get_table_for_model(model, name=None):
     try:
     try:
         return import_string(f'{model._meta.app_label}.tables.{name}')
         return import_string(f'{model._meta.app_label}.tables.{name}')
     except ImportError:
     except ImportError:
-        return
+        return None
 
 
 
 
 def get_table_ordering(request, table):
 def get_table_ordering(request, table):
     """
     """
-    Given a request, return the prescribed table ordering, if any. This may be necessary to determine prior to rendering
-    the table itself.
+    Given a request, return the prescribed table ordering, if any.
+    This may be necessary to determine before rendering the table itself.
     """
     """
     # Check for an explicit ordering
     # Check for an explicit ordering
     if 'sort' in request.GET:
     if 'sort' in request.GET:
@@ -49,6 +49,7 @@ def get_table_ordering(request, table):
     if request.user.is_authenticated:
     if request.user.is_authenticated:
         if preference := request.user.config.get(f'tables.{table.__name__}.ordering'):
         if preference := request.user.config.get(f'tables.{table.__name__}.ordering'):
             return preference
             return preference
+    return None
 
 
 
 
 def linkify_phone(value):
 def linkify_phone(value):

+ 2 - 3
netbox/utilities/templatetags/builtins/filters.py

@@ -227,12 +227,11 @@ def isodate(value):
     if type(value) is datetime.date:
     if type(value) is datetime.date:
         text = value.isoformat()
         text = value.isoformat()
         return mark_safe(f'<span title="{naturalday(value)}">{text}</span>')
         return mark_safe(f'<span title="{naturalday(value)}">{text}</span>')
-    elif type(value) is datetime.datetime:
+    if type(value) is datetime.datetime:
         local_value = localtime(value) if value.tzinfo else value
         local_value = localtime(value) if value.tzinfo else value
         text = local_value.date().isoformat()
         text = local_value.date().isoformat()
         return mark_safe(f'<span title="{naturaltime(value)}">{text}</span>')
         return mark_safe(f'<span title="{naturaltime(value)}">{text}</span>')
-    else:
-        return ''
+    return ''
 
 
 
 
 @register.filter()
 @register.filter()

+ 2 - 3
netbox/utilities/templatetags/form_helpers.py

@@ -37,10 +37,9 @@ def widget_type(field):
     """
     """
     if hasattr(field, 'widget'):
     if hasattr(field, 'widget'):
         return field.widget.__class__.__name__.lower()
         return field.widget.__class__.__name__.lower()
-    elif hasattr(field, 'field'):
+    if hasattr(field, 'field'):
         return field.field.widget.__class__.__name__.lower()
         return field.field.widget.__class__.__name__.lower()
-    else:
-        return None
+    return None
 
 
 
 
 #
 #

+ 5 - 7
netbox/utilities/templatetags/helpers.py

@@ -199,14 +199,13 @@ def humanize_speed(speed):
         return ''
         return ''
     if speed >= 1000000000 and speed % 1000000000 == 0:
     if speed >= 1000000000 and speed % 1000000000 == 0:
         return '{} Tbps'.format(int(speed / 1000000000))
         return '{} Tbps'.format(int(speed / 1000000000))
-    elif speed >= 1000000 and speed % 1000000 == 0:
+    if speed >= 1000000 and speed % 1000000 == 0:
         return '{} Gbps'.format(int(speed / 1000000))
         return '{} Gbps'.format(int(speed / 1000000))
-    elif speed >= 1000 and speed % 1000 == 0:
+    if speed >= 1000 and speed % 1000 == 0:
         return '{} Mbps'.format(int(speed / 1000))
         return '{} Mbps'.format(int(speed / 1000))
-    elif speed >= 1000:
+    if speed >= 1000:
         return '{} Mbps'.format(float(speed) / 1000)
         return '{} Mbps'.format(float(speed) / 1000)
-    else:
-        return '{} Kbps'.format(speed)
+    return '{} Kbps'.format(speed)
 
 
 
 
 def _humanize_megabytes(mb, divisor=1000):
 def _humanize_megabytes(mb, divisor=1000):
@@ -373,8 +372,7 @@ def querystring(request, **kwargs):
     querystring = querydict.urlencode(safe='/')
     querystring = querydict.urlencode(safe='/')
     if querystring:
     if querystring:
         return '?' + querystring
         return '?' + querystring
-    else:
-        return ''
+    return ''
 
 
 
 
 @register.inclusion_tag('helpers/utilization_graph.html')
 @register.inclusion_tag('helpers/utilization_graph.html')

+ 1 - 1
netbox/utilities/testing/filtersets.py

@@ -66,7 +66,7 @@ class BaseFilterSetTests:
             return [(f'{filter_name}_id', django_filters.ModelMultipleChoiceFilter)]
             return [(f'{filter_name}_id', django_filters.ModelMultipleChoiceFilter)]
 
 
         # Many-to-many relationships (forward & backward)
         # Many-to-many relationships (forward & backward)
-        elif type(field) in (ManyToManyField, ManyToManyRel):
+        if type(field) in (ManyToManyField, ManyToManyRel):
             filter_name = self.get_m2m_filter_name(field)
             filter_name = self.get_m2m_filter_name(field)
             filter_name = self.filter_name_map.get(filter_name, filter_name)
             filter_name = self.filter_name_map.get(filter_name, filter_name)
 
 

+ 2 - 3
netbox/utilities/testing/views.py

@@ -635,10 +635,9 @@ class ViewTestCases:
                     available = ', '.join(self.csv_data.keys())
                     available = ', '.join(self.csv_data.keys())
                     raise ValueError(f"Scenario '{scenario_name}' not found in csv_data. Available: {available}")
                     raise ValueError(f"Scenario '{scenario_name}' not found in csv_data. Available: {available}")
                 return '\n'.join(self.csv_data[scenario_name])
                 return '\n'.join(self.csv_data[scenario_name])
-            elif isinstance(self.csv_data, (tuple, list)):
+            if isinstance(self.csv_data, (tuple, list)):
                 return '\n'.join(self.csv_data)
                 return '\n'.join(self.csv_data)
-            else:
-                raise TypeError(f'csv_data must be a tuple, list, or dictionary, got {type(self.csv_data)}')
+            raise TypeError(f'csv_data must be a tuple, list, or dictionary, got {type(self.csv_data)}')
 
 
         def _get_update_csv_data(self):
         def _get_update_csv_data(self):
             return self.csv_update_data, '\n'.join(self.csv_update_data)
             return self.csv_update_data, '\n'.join(self.csv_update_data)

+ 1 - 2
netbox/virtualization/forms/bulk_import.py

@@ -252,8 +252,7 @@ class VMInterfaceImportForm(OwnerCSVMixin, NetBoxModelImportForm):
         # Make sure enabled is True when it's not included in the uploaded data
         # Make sure enabled is True when it's not included in the uploaded data
         if 'enabled' not in self.data:
         if 'enabled' not in self.data:
             return True
             return True
-        else:
-            return self.cleaned_data['enabled']
+        return self.cleaned_data['enabled']
 
 
 
 
 class VirtualDiskImportForm(OwnerCSVMixin, NetBoxModelImportForm):
 class VirtualDiskImportForm(OwnerCSVMixin, NetBoxModelImportForm):

+ 3 - 4
netbox/virtualization/models/virtualmachines.py

@@ -260,12 +260,11 @@ class VirtualMachine(ContactsMixin, ImageAttachmentsMixin, RenderConfigMixin, Co
     def primary_ip(self):
     def primary_ip(self):
         if get_config().PREFER_IPV4 and self.primary_ip4:
         if get_config().PREFER_IPV4 and self.primary_ip4:
             return self.primary_ip4
             return self.primary_ip4
-        elif self.primary_ip6:
+        if self.primary_ip6:
             return self.primary_ip6
             return self.primary_ip6
-        elif self.primary_ip4:
+        if self.primary_ip4:
             return self.primary_ip4
             return self.primary_ip4
-        else:
-            return None
+        return None
 
 
 
 
 #
 #

+ 3 - 4
netbox/vpn/models/l2vpn.py

@@ -80,8 +80,7 @@ class L2VPN(ContactsMixin, PrimaryModel):
     def can_add_termination(self):
     def can_add_termination(self):
         if self.type in L2VPNTypeChoices.P2P and self.terminations.count() >= 2:
         if self.type in L2VPNTypeChoices.P2P and self.terminations.count() >= 2:
             return False
             return False
-        else:
-            return True
+        return True
 
 
 
 
 class L2VPNTermination(NetBoxModel):
 class L2VPNTermination(NetBoxModel):
@@ -151,9 +150,9 @@ class L2VPNTermination(NetBoxModel):
         obj_type = ObjectType.objects.get_for_model(self.assigned_object)
         obj_type = ObjectType.objects.get_for_model(self.assigned_object)
         if obj_type.model == 'vminterface':
         if obj_type.model == 'vminterface':
             return self.assigned_object.virtual_machine
             return self.assigned_object.virtual_machine
-        elif obj_type.model == 'interface':
+        if obj_type.model == 'interface':
             return self.assigned_object.device
             return self.assigned_object.device
-        elif obj_type.model == 'vminterface':
+        if obj_type.model == 'vminterface':
             return self.assigned_object.virtual_machine
             return self.assigned_object.virtual_machine
         return None
         return None
 
 

+ 2 - 0
ruff.toml

@@ -37,10 +37,12 @@ extend-select = [
     "E501",  # pycodestyle: line too long (enforced with `line-length` above)
     "E501",  # pycodestyle: line too long (enforced with `line-length` above)
     "W",     # pycodestyle warnings (various style warnings, often whitespace/newlines)
     "W",     # pycodestyle warnings (various style warnings, often whitespace/newlines)
     "I",     # import sorting (isort-equivalent)
     "I",     # import sorting (isort-equivalent)
+    "RET",   # return semantics (flake8-return family)
 ]
 ]
 ignore = [
 ignore = [
     "F403",  # pyflakes: `from ... import *` used; unable to detect undefined names
     "F403",  # pyflakes: `from ... import *` used; unable to detect undefined names
     "F405",  # pyflakes: name may be undefined or defined from star imports
     "F405",  # pyflakes: name may be undefined or defined from star imports
+    "RET504",  # return: unnecessary assignment before `return` (e.g., `x = expr; return x` -> `return expr`)
     "UP032", # pyupgrade: prefer f-strings over `str.format(...)`
     "UP032", # pyupgrade: prefer f-strings over `str.format(...)`
 ]
 ]
 preview = true
 preview = true