2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 11:36:44 +00:00

Clean up various schema generator warnings (#9437)

* Add default metadata model for schema generation

* Add type hints and annotations where needed for schema generation

* Bump api version

* Fix version bump
This commit is contained in:
Joe Rogers 2025-04-02 05:34:58 +02:00 committed by GitHub
parent 15933a6b3a
commit b2db0b67e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 36 additions and 7 deletions

View File

@ -18,10 +18,11 @@ from rest_framework.response import Response
from rest_framework.serializers import ValidationError
from rest_framework.views import APIView
import common.models
import InvenTree.version
import users.models
from common.settings import get_global_setting
from InvenTree import helpers
from InvenTree import helpers, ready
from InvenTree.auth_overrides import registration_enabled
from InvenTree.mixins import ListCreateAPI
from InvenTree.sso import sso_registration_enabled
@ -710,6 +711,9 @@ class MetadataView(RetrieveUpdateAPI):
"""Return the model type associated with this API instance."""
model = self.kwargs.get(self.MODEL_REF, None)
if ready.isGeneratingSchema():
model = common.models.ProjectCode
if 'lookup_field' in self.kwargs:
# Set custom lookup field (instead of default 'pk' value) if supplied
self.lookup_field = self.kwargs.pop('lookup_field')

View File

@ -1,12 +1,15 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 330
INVENTREE_API_VERSION = 331
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v331 - 2025-04-01 : https://github.com/inventree/InvenTree/pull/9437
- Set correct types on various formerly-string PK fields as well permissions
- Include metadata request and response types
v330 - 2025-03-31 : https://github.com/inventree/InvenTree/pull/9420
- Deconflict operation id between single and bulk destroy operations

View File

@ -8,6 +8,8 @@ from django.urls import include, path
from django.utils.translation import gettext_lazy as _
from django_filters import rest_framework as rest_filters
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
import build.admin
@ -103,6 +105,7 @@ class BuildFilter(rest_filters.FilterSet):
label=_('Category'),
)
@extend_schema_field(serializers.IntegerField(help_text=_('Category')))
def filter_category(self, queryset, name, category):
"""Filter by part category (including sub-categories)."""
categories = category.get_descendants(include_self=True)
@ -114,6 +117,7 @@ class BuildFilter(rest_filters.FilterSet):
method='filter_ancestor',
)
@extend_schema_field(serializers.IntegerField(help_text=_('Ancestor Build')))
def filter_ancestor(self, queryset, name, parent):
"""Filter by 'parent' build order."""
builds = parent.get_descendants(include_self=False)
@ -293,6 +297,7 @@ class BuildFilter(rest_filters.FilterSet):
label=_('Exclude Tree'),
)
@extend_schema_field(serializers.IntegerField(help_text=_('Exclude Tree')))
def filter_exclude_tree(self, queryset, name, value):
"""Filter by excluding a tree of Build objects."""
queryset = queryset.exclude(

View File

@ -6,6 +6,8 @@ from django.urls import reverse
from django.utils.translation import gettext_lazy as _
import django_q.models
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from error_report.models import Error
from flags.state import flag_state
from rest_framework import serializers
@ -28,6 +30,7 @@ from plugin import registry as plugin_registry
from users.serializers import OwnerSerializer, UserSerializer
@extend_schema_field(OpenApiTypes.STR)
class SettingsValueField(serializers.Field):
"""Custom serializer field for a settings value."""
@ -35,7 +38,7 @@ class SettingsValueField(serializers.Field):
"""Return the object instance, not the attribute value."""
return instance
def to_representation(self, instance):
def to_representation(self, instance) -> str:
"""Return the value of the setting.
Protected settings are returned as '***'
@ -47,7 +50,7 @@ class SettingsValueField(serializers.Field):
else:
return str(instance.value)
def to_internal_value(self, data):
def to_internal_value(self, data) -> str:
"""Return the internal value of the setting."""
if data is None:
return ''

View File

@ -306,7 +306,7 @@ class SupplierPartFilter(rest_filters.FilterSet):
label=_('Company'), queryset=Company.objects.all(), method='filter_company'
)
def filter_company(self, queryset, name, value):
def filter_company(self, queryset, name, value: int):
"""Filter the queryset by either manufacturer or supplier."""
return queryset.filter(
Q(manufacturer_part__manufacturer=value) | Q(supplier=value)

View File

@ -11,8 +11,11 @@ from django.http.response import JsonResponse
from django.urls import include, path, re_path
from django.utils.translation import gettext_lazy as _
import rest_framework.serializers
from django_filters import rest_framework as rest_filters
from django_ical.views import ICalFeed
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework import status
from rest_framework.response import Response
@ -289,6 +292,7 @@ class PurchaseOrderFilter(OrderFilter):
method='filter_part',
)
@extend_schema_field(rest_framework.serializers.IntegerField(help_text=_('Part')))
def filter_part(self, queryset, name, part: Part):
"""Filter by provided Part instance."""
orders = part.purchase_orders()
@ -301,6 +305,9 @@ class PurchaseOrderFilter(OrderFilter):
method='filter_supplier_part',
)
@extend_schema_field(
rest_framework.serializers.IntegerField(help_text=_('Supplier Part'))
)
def filter_supplier_part(
self, queryset, name, supplier_part: company.models.SupplierPart
):
@ -520,6 +527,9 @@ class PurchaseOrderLineItemFilter(LineItemFilter):
label=_('Internal Part'),
)
@extend_schema_field(
rest_framework.serializers.IntegerField(help_text=_('Internal Part'))
)
def filter_base_part(self, queryset, name, base_part):
"""Filter by the 'base_part' attribute.
@ -735,6 +745,7 @@ class SalesOrderFilter(OrderFilter):
queryset=Part.objects.all(), field_name='part', method='filter_part'
)
@extend_schema_field(OpenApiTypes.INT)
def filter_part(self, queryset, name, part):
"""Filter SalesOrder by selected 'part'.
@ -1108,6 +1119,7 @@ class SalesOrderAllocationFilter(rest_filters.FilterSet):
queryset=Part.objects.all(), method='filter_part', label=_('Part')
)
@extend_schema_field(rest_framework.serializers.IntegerField(help_text=_('Part')))
def filter_part(self, queryset, name, part):
"""Filter by the 'part' attribute.
@ -1335,6 +1347,7 @@ class ReturnOrderFilter(OrderFilter):
queryset=Part.objects.all(), field_name='part', method='filter_part'
)
@extend_schema_field(OpenApiTypes.INT)
def filter_part(self, queryset, name, part):
"""Filter by selected 'part'.

View File

@ -1441,6 +1441,7 @@ class PartRelatedFilter(rest_filters.FilterSet):
queryset=Part.objects.all(), method='filter_part', label=_('Part')
)
@extend_schema_field(serializers.IntegerField(help_text=_('Part')))
def filter_part(self, queryset, name, part):
"""Filter queryset to include only PartRelated objects which reference the specified part."""
return queryset.filter(Q(part_1=part) | Q(part_2=part)).distinct()

View File

@ -52,7 +52,7 @@ class GroupSerializer(InvenTreeModelSerializer):
permissions = serializers.SerializerMethodField(allow_null=True)
def get_permissions(self, group: Group):
def get_permissions(self, group: Group) -> dict:
"""Return a list of permissions associated with the group."""
return generate_permission_dict(group.permissions.all())
@ -109,7 +109,7 @@ class RoleSerializer(InvenTreeModelSerializer):
return generate_permission_dict(permissions)
def generate_permission_dict(permissions):
def generate_permission_dict(permissions) -> dict:
"""Generate a dictionary of permissions for a given set of permissions."""
perms = {}