Chore: Add generic type params and update our baselines (#12566)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Trenton H
2026-04-13 14:12:59 -07:00
committed by GitHub
parent b27d10646e
commit 3b6edcdd8e
12 changed files with 6642 additions and 7772 deletions
+1
View File
@@ -165,6 +165,7 @@ jobs:
contents: read contents: read
env: env:
DEFAULT_PYTHON: "3.12" DEFAULT_PYTHON: "3.12"
PAPERLESS_SECRET_KEY: "ci-typing-not-a-real-secret"
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+2
View File
@@ -88,6 +88,7 @@ jobs:
uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt
- name: Compile messages - name: Compile messages
env: env:
PAPERLESS_SECRET_KEY: "ci-release-not-a-real-secret"
PYTHON_VERSION: ${{ steps.setup-python.outputs.python-version }} PYTHON_VERSION: ${{ steps.setup-python.outputs.python-version }}
run: | run: |
cd src/ cd src/
@@ -96,6 +97,7 @@ jobs:
manage.py compilemessages manage.py compilemessages
- name: Collect static files - name: Collect static files
env: env:
PAPERLESS_SECRET_KEY: "ci-release-not-a-real-secret"
PYTHON_VERSION: ${{ steps.setup-python.outputs.python-version }} PYTHON_VERSION: ${{ steps.setup-python.outputs.python-version }}
run: | run: |
cd src/ cd src/
+2
View File
@@ -36,6 +36,8 @@ jobs:
--group dev \ --group dev \
--frozen --frozen
- name: Generate backend translation strings - name: Generate backend translation strings
env:
PAPERLESS_SECRET_KEY: "ci-translate-not-a-real-secret"
run: cd src/ && uv run manage.py makemessages -l en_US -i "samples*" run: cd src/ && uv run manage.py makemessages -l en_US -i "samples*"
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
+3
View File
@@ -79,6 +79,7 @@ virtualenv
/docker-compose.env /docker-compose.env
/docker-compose.yml /docker-compose.yml
.ruff_cache/ .ruff_cache/
.mypy_cache/
# Used for development # Used for development
scripts/import-for-development scripts/import-for-development
@@ -111,4 +112,6 @@ celerybeat-schedule*
# ignore pnpm package store folder created when setting up the devcontainer # ignore pnpm package store folder created when setting up the devcontainer
.pnpm-store/ .pnpm-store/
# Git worktree local folder
.worktrees .worktrees
+1064 -894
View File
File diff suppressed because it is too large Load Diff
+5498 -6818
View File
File diff suppressed because one or more lines are too long
+22 -20
View File
@@ -100,7 +100,7 @@ logger = logging.getLogger("paperless.serializers")
# https://www.django-rest-framework.org/api-guide/serializers/#example # https://www.django-rest-framework.org/api-guide/serializers/#example
class DynamicFieldsModelSerializer(serializers.ModelSerializer): class DynamicFieldsModelSerializer(serializers.ModelSerializer[Any]):
""" """
A ModelSerializer that takes an additional `fields` argument that A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed. controls which fields should be displayed.
@@ -121,7 +121,7 @@ class DynamicFieldsModelSerializer(serializers.ModelSerializer):
self.fields.pop(field_name) self.fields.pop(field_name)
class MatchingModelSerializer(serializers.ModelSerializer): class MatchingModelSerializer(serializers.ModelSerializer[Any]):
document_count = serializers.IntegerField(read_only=True) document_count = serializers.IntegerField(read_only=True)
def get_slug(self, obj) -> str: def get_slug(self, obj) -> str:
@@ -261,7 +261,7 @@ class SetPermissionsSerializer(serializers.DictField):
class OwnedObjectSerializer( class OwnedObjectSerializer(
SerializerWithPerms, SerializerWithPerms,
serializers.ModelSerializer, serializers.ModelSerializer[Any],
SetPermissionsMixin, SetPermissionsMixin,
): ):
def __init__(self, *args, **kwargs) -> None: def __init__(self, *args, **kwargs) -> None:
@@ -469,7 +469,7 @@ class OwnedObjectSerializer(
return super().update(instance, validated_data) return super().update(instance, validated_data)
class OwnedObjectListSerializer(serializers.ListSerializer): class OwnedObjectListSerializer(serializers.ListSerializer[Any]):
def to_representation(self, documents): def to_representation(self, documents):
self.child.context["shared_object_pks"] = self.child.get_shared_object_pks( self.child.context["shared_object_pks"] = self.child.get_shared_object_pks(
documents, documents,
@@ -682,27 +682,27 @@ class TagSerializer(MatchingModelSerializer, OwnedObjectSerializer):
return super().validate(attrs) return super().validate(attrs)
class CorrespondentField(serializers.PrimaryKeyRelatedField): class CorrespondentField(serializers.PrimaryKeyRelatedField[Correspondent]):
def get_queryset(self): def get_queryset(self):
return Correspondent.objects.all() return Correspondent.objects.all()
class TagsField(serializers.PrimaryKeyRelatedField): class TagsField(serializers.PrimaryKeyRelatedField[Tag]):
def get_queryset(self): def get_queryset(self):
return Tag.objects.all() return Tag.objects.all()
class DocumentTypeField(serializers.PrimaryKeyRelatedField): class DocumentTypeField(serializers.PrimaryKeyRelatedField[DocumentType]):
def get_queryset(self): def get_queryset(self):
return DocumentType.objects.all() return DocumentType.objects.all()
class StoragePathField(serializers.PrimaryKeyRelatedField): class StoragePathField(serializers.PrimaryKeyRelatedField[StoragePath]):
def get_queryset(self): def get_queryset(self):
return StoragePath.objects.all() return StoragePath.objects.all()
class CustomFieldSerializer(serializers.ModelSerializer): class CustomFieldSerializer(serializers.ModelSerializer[CustomField]):
data_type = serializers.ChoiceField( data_type = serializers.ChoiceField(
choices=CustomField.FieldDataType, choices=CustomField.FieldDataType,
read_only=False, read_only=False,
@@ -816,7 +816,7 @@ def validate_documentlink_targets(user, doc_ids):
) )
class CustomFieldInstanceSerializer(serializers.ModelSerializer): class CustomFieldInstanceSerializer(serializers.ModelSerializer[CustomFieldInstance]):
field = serializers.PrimaryKeyRelatedField(queryset=CustomField.objects.all()) field = serializers.PrimaryKeyRelatedField(queryset=CustomField.objects.all())
value = ReadWriteSerializerMethodField(allow_null=True) value = ReadWriteSerializerMethodField(allow_null=True)
@@ -922,14 +922,14 @@ class CustomFieldInstanceSerializer(serializers.ModelSerializer):
] ]
class BasicUserSerializer(serializers.ModelSerializer): class BasicUserSerializer(serializers.ModelSerializer[User]):
# Different than paperless.serializers.UserSerializer # Different than paperless.serializers.UserSerializer
class Meta: class Meta:
model = User model = User
fields = ["id", "username", "first_name", "last_name"] fields = ["id", "username", "first_name", "last_name"]
class NotesSerializer(serializers.ModelSerializer): class NotesSerializer(serializers.ModelSerializer[Note]):
user = BasicUserSerializer(read_only=True) user = BasicUserSerializer(read_only=True)
class Meta: class Meta:
@@ -1256,7 +1256,7 @@ class DocumentSerializer(
list_serializer_class = OwnedObjectListSerializer list_serializer_class = OwnedObjectListSerializer
class SearchResultListSerializer(serializers.ListSerializer): class SearchResultListSerializer(serializers.ListSerializer[Document]):
def to_representation(self, hits): def to_representation(self, hits):
document_ids = [hit["id"] for hit in hits] document_ids = [hit["id"] for hit in hits]
# Fetch all Document objects in the list in one SQL query. # Fetch all Document objects in the list in one SQL query.
@@ -1313,7 +1313,7 @@ class SearchResultSerializer(DocumentSerializer):
list_serializer_class = SearchResultListSerializer list_serializer_class = SearchResultListSerializer
class SavedViewFilterRuleSerializer(serializers.ModelSerializer): class SavedViewFilterRuleSerializer(serializers.ModelSerializer[SavedViewFilterRule]):
class Meta: class Meta:
model = SavedViewFilterRule model = SavedViewFilterRule
fields = ["rule_type", "value"] fields = ["rule_type", "value"]
@@ -2401,7 +2401,7 @@ class StoragePathSerializer(MatchingModelSerializer, OwnedObjectSerializer):
return super().update(instance, validated_data) return super().update(instance, validated_data)
class UiSettingsViewSerializer(serializers.ModelSerializer): class UiSettingsViewSerializer(serializers.ModelSerializer[UiSettings]):
settings = serializers.DictField(required=False, allow_null=True) settings = serializers.DictField(required=False, allow_null=True)
class Meta: class Meta:
@@ -2760,7 +2760,7 @@ class BulkEditObjectsSerializer(SerializerWithPerms, SetPermissionsMixin):
return attrs return attrs
class WorkflowTriggerSerializer(serializers.ModelSerializer): class WorkflowTriggerSerializer(serializers.ModelSerializer[WorkflowTrigger]):
id = serializers.IntegerField(required=False, allow_null=True) id = serializers.IntegerField(required=False, allow_null=True)
sources = fields.MultipleChoiceField( sources = fields.MultipleChoiceField(
choices=WorkflowTrigger.DocumentSourceChoices.choices, choices=WorkflowTrigger.DocumentSourceChoices.choices,
@@ -2870,7 +2870,7 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer):
return super().update(instance, validated_data) return super().update(instance, validated_data)
class WorkflowActionEmailSerializer(serializers.ModelSerializer): class WorkflowActionEmailSerializer(serializers.ModelSerializer[WorkflowActionEmail]):
id = serializers.IntegerField(allow_null=True, required=False) id = serializers.IntegerField(allow_null=True, required=False)
class Meta: class Meta:
@@ -2884,7 +2884,9 @@ class WorkflowActionEmailSerializer(serializers.ModelSerializer):
] ]
class WorkflowActionWebhookSerializer(serializers.ModelSerializer): class WorkflowActionWebhookSerializer(
serializers.ModelSerializer[WorkflowActionWebhook],
):
id = serializers.IntegerField(allow_null=True, required=False) id = serializers.IntegerField(allow_null=True, required=False)
def validate_url(self, url): def validate_url(self, url):
@@ -2905,7 +2907,7 @@ class WorkflowActionWebhookSerializer(serializers.ModelSerializer):
] ]
class WorkflowActionSerializer(serializers.ModelSerializer): class WorkflowActionSerializer(serializers.ModelSerializer[WorkflowAction]):
id = serializers.IntegerField(required=False, allow_null=True) id = serializers.IntegerField(required=False, allow_null=True)
assign_correspondent = CorrespondentField(allow_null=True, required=False) assign_correspondent = CorrespondentField(allow_null=True, required=False)
assign_tags = TagsField(many=True, allow_null=True, required=False) assign_tags = TagsField(many=True, allow_null=True, required=False)
@@ -3027,7 +3029,7 @@ class WorkflowActionSerializer(serializers.ModelSerializer):
return attrs return attrs
class WorkflowSerializer(serializers.ModelSerializer): class WorkflowSerializer(serializers.ModelSerializer[Workflow]):
order = serializers.IntegerField(required=False) order = serializers.IntegerField(required=False)
triggers = WorkflowTriggerSerializer(many=True) triggers = WorkflowTriggerSerializer(many=True)
+28 -22
View File
@@ -291,7 +291,7 @@ class IndexView(TemplateView):
return context return context
class PassUserMixin(GenericAPIView): class PassUserMixin(GenericAPIView[Any]):
""" """
Pass a user object to serializer Pass a user object to serializer
""" """
@@ -457,7 +457,10 @@ class PermissionsAwareDocumentCountMixin(BulkPermissionMixin, PassUserMixin):
@extend_schema_view(**generate_object_with_permissions_schema(CorrespondentSerializer)) @extend_schema_view(**generate_object_with_permissions_schema(CorrespondentSerializer))
class CorrespondentViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet): class CorrespondentViewSet(
PermissionsAwareDocumentCountMixin,
ModelViewSet[Correspondent],
):
model = Correspondent model = Correspondent
queryset = Correspondent.objects.select_related("owner").order_by(Lower("name")) queryset = Correspondent.objects.select_related("owner").order_by(Lower("name"))
@@ -494,7 +497,7 @@ class CorrespondentViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet):
@extend_schema_view(**generate_object_with_permissions_schema(TagSerializer)) @extend_schema_view(**generate_object_with_permissions_schema(TagSerializer))
class TagViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet): class TagViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet[Tag]):
model = Tag model = Tag
serializer_class = TagSerializer serializer_class = TagSerializer
document_count_through = Document.tags.through document_count_through = Document.tags.through
@@ -573,7 +576,10 @@ class TagViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet):
@extend_schema_view(**generate_object_with_permissions_schema(DocumentTypeSerializer)) @extend_schema_view(**generate_object_with_permissions_schema(DocumentTypeSerializer))
class DocumentTypeViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet): class DocumentTypeViewSet(
PermissionsAwareDocumentCountMixin,
ModelViewSet[DocumentType],
):
model = DocumentType model = DocumentType
queryset = DocumentType.objects.select_related("owner").order_by(Lower("name")) queryset = DocumentType.objects.select_related("owner").order_by(Lower("name"))
@@ -808,7 +814,7 @@ class DocumentViewSet(
UpdateModelMixin, UpdateModelMixin,
DestroyModelMixin, DestroyModelMixin,
ListModelMixin, ListModelMixin,
GenericViewSet, GenericViewSet[Document],
): ):
model = Document model = Document
queryset = Document.objects.all() queryset = Document.objects.all()
@@ -1955,7 +1961,7 @@ class ChatStreamingSerializer(serializers.Serializer):
], ],
name="dispatch", name="dispatch",
) )
class ChatStreamingView(GenericAPIView): class ChatStreamingView(GenericAPIView[Any]):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
serializer_class = ChatStreamingSerializer serializer_class = ChatStreamingSerializer
@@ -2281,7 +2287,7 @@ class LogViewSet(ViewSet):
@extend_schema_view(**generate_object_with_permissions_schema(SavedViewSerializer)) @extend_schema_view(**generate_object_with_permissions_schema(SavedViewSerializer))
class SavedViewViewSet(BulkPermissionMixin, PassUserMixin, ModelViewSet): class SavedViewViewSet(BulkPermissionMixin, PassUserMixin, ModelViewSet[SavedView]):
model = SavedView model = SavedView
queryset = SavedView.objects.select_related("owner").prefetch_related( queryset = SavedView.objects.select_related("owner").prefetch_related(
@@ -2759,7 +2765,7 @@ class RemovePasswordDocumentsView(DocumentOperationPermissionMixin):
}, },
), ),
) )
class PostDocumentView(GenericAPIView): class PostDocumentView(GenericAPIView[Any]):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
serializer_class = PostDocumentSerializer serializer_class = PostDocumentSerializer
parser_classes = (parsers.MultiPartParser,) parser_classes = (parsers.MultiPartParser,)
@@ -2880,7 +2886,7 @@ class PostDocumentView(GenericAPIView):
}, },
), ),
) )
class SelectionDataView(GenericAPIView): class SelectionDataView(GenericAPIView[Any]):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
serializer_class = DocumentListSerializer serializer_class = DocumentListSerializer
parser_classes = (parsers.MultiPartParser, parsers.JSONParser) parser_classes = (parsers.MultiPartParser, parsers.JSONParser)
@@ -2984,7 +2990,7 @@ class SelectionDataView(GenericAPIView):
}, },
), ),
) )
class SearchAutoCompleteView(GenericAPIView): class SearchAutoCompleteView(GenericAPIView[Any]):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
def get(self, request, format=None): def get(self, request, format=None):
@@ -3265,7 +3271,7 @@ class GlobalSearchView(PassUserMixin):
}, },
), ),
) )
class StatisticsView(GenericAPIView): class StatisticsView(GenericAPIView[Any]):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
def get(self, request, format=None): def get(self, request, format=None):
@@ -3367,7 +3373,7 @@ class StatisticsView(GenericAPIView):
) )
class BulkDownloadView(DocumentSelectionMixin, GenericAPIView): class BulkDownloadView(DocumentSelectionMixin, GenericAPIView[Any]):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
serializer_class = BulkDownloadSerializer serializer_class = BulkDownloadSerializer
parser_classes = (parsers.JSONParser,) parser_classes = (parsers.JSONParser,)
@@ -3420,7 +3426,7 @@ class BulkDownloadView(DocumentSelectionMixin, GenericAPIView):
@extend_schema_view(**generate_object_with_permissions_schema(StoragePathSerializer)) @extend_schema_view(**generate_object_with_permissions_schema(StoragePathSerializer))
class StoragePathViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet): class StoragePathViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet[StoragePath]):
model = StoragePath model = StoragePath
queryset = StoragePath.objects.select_related("owner").order_by( queryset = StoragePath.objects.select_related("owner").order_by(
@@ -3484,7 +3490,7 @@ class StoragePathViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet):
return Response(result) return Response(result)
class UiSettingsView(GenericAPIView): class UiSettingsView(GenericAPIView[Any]):
queryset = UiSettings.objects.all() queryset = UiSettings.objects.all()
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = UiSettingsViewSerializer serializer_class = UiSettingsViewSerializer
@@ -3582,7 +3588,7 @@ class UiSettingsView(GenericAPIView):
}, },
), ),
) )
class RemoteVersionView(GenericAPIView): class RemoteVersionView(GenericAPIView[Any]):
cache_key = "remote_version_view_latest_release" cache_key = "remote_version_view_latest_release"
def get(self, request, format=None): def get(self, request, format=None):
@@ -3659,7 +3665,7 @@ class RemoteVersionView(GenericAPIView):
), ),
], ],
) )
class TasksViewSet(ReadOnlyModelViewSet): class TasksViewSet(ReadOnlyModelViewSet[PaperlessTask]):
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = TasksViewSerializer serializer_class = TasksViewSerializer
filter_backends = ( filter_backends = (
@@ -3733,7 +3739,7 @@ class TasksViewSet(ReadOnlyModelViewSet):
) )
class ShareLinkViewSet(ModelViewSet, PassUserMixin): class ShareLinkViewSet(PassUserMixin, ModelViewSet[ShareLink]):
model = ShareLink model = ShareLink
queryset = ShareLink.objects.all() queryset = ShareLink.objects.all()
@@ -3750,7 +3756,7 @@ class ShareLinkViewSet(ModelViewSet, PassUserMixin):
ordering_fields = ("created", "expiration", "document") ordering_fields = ("created", "expiration", "document")
class ShareLinkBundleViewSet(ModelViewSet, PassUserMixin): class ShareLinkBundleViewSet(PassUserMixin, ModelViewSet[ShareLinkBundle]):
model = ShareLinkBundle model = ShareLinkBundle
queryset = ShareLinkBundle.objects.all() queryset = ShareLinkBundle.objects.all()
@@ -4107,7 +4113,7 @@ class BulkEditObjectsView(PassUserMixin):
return Response({"result": "OK"}) return Response({"result": "OK"})
class WorkflowTriggerViewSet(ModelViewSet): class WorkflowTriggerViewSet(ModelViewSet[WorkflowTrigger]):
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = WorkflowTriggerSerializer serializer_class = WorkflowTriggerSerializer
@@ -4125,7 +4131,7 @@ class WorkflowTriggerViewSet(ModelViewSet):
return super().partial_update(request, *args, **kwargs) return super().partial_update(request, *args, **kwargs)
class WorkflowActionViewSet(ModelViewSet): class WorkflowActionViewSet(ModelViewSet[WorkflowAction]):
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = WorkflowActionSerializer serializer_class = WorkflowActionSerializer
@@ -4150,7 +4156,7 @@ class WorkflowActionViewSet(ModelViewSet):
return super().partial_update(request, *args, **kwargs) return super().partial_update(request, *args, **kwargs)
class WorkflowViewSet(ModelViewSet): class WorkflowViewSet(ModelViewSet[Workflow]):
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = WorkflowSerializer serializer_class = WorkflowSerializer
@@ -4168,7 +4174,7 @@ class WorkflowViewSet(ModelViewSet):
) )
class CustomFieldViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet): class CustomFieldViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet[CustomField]):
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = CustomFieldSerializer serializer_class = CustomFieldSerializer
+7 -5
View File
@@ -74,7 +74,7 @@ class PaperlessAuthTokenSerializer(AuthTokenSerializer):
return attrs return attrs
class UserSerializer(PasswordValidationMixin, serializers.ModelSerializer): class UserSerializer(PasswordValidationMixin, serializers.ModelSerializer[User]):
password = ObfuscatedPasswordField(required=False) password = ObfuscatedPasswordField(required=False)
user_permissions = serializers.SlugRelatedField( user_permissions = serializers.SlugRelatedField(
many=True, many=True,
@@ -142,7 +142,7 @@ class UserSerializer(PasswordValidationMixin, serializers.ModelSerializer):
return user return user
class GroupSerializer(serializers.ModelSerializer): class GroupSerializer(serializers.ModelSerializer[Group]):
permissions = serializers.SlugRelatedField( permissions = serializers.SlugRelatedField(
many=True, many=True,
queryset=Permission.objects.exclude(content_type__app_label="admin"), queryset=Permission.objects.exclude(content_type__app_label="admin"),
@@ -158,7 +158,7 @@ class GroupSerializer(serializers.ModelSerializer):
) )
class SocialAccountSerializer(serializers.ModelSerializer): class SocialAccountSerializer(serializers.ModelSerializer[SocialAccount]):
name = serializers.SerializerMethodField() name = serializers.SerializerMethodField()
class Meta: class Meta:
@@ -176,7 +176,7 @@ class SocialAccountSerializer(serializers.ModelSerializer):
return "Unknown App" return "Unknown App"
class ProfileSerializer(PasswordValidationMixin, serializers.ModelSerializer): class ProfileSerializer(PasswordValidationMixin, serializers.ModelSerializer[User]):
email = serializers.EmailField(allow_blank=True, required=False) email = serializers.EmailField(allow_blank=True, required=False)
password = ObfuscatedPasswordField(required=False, allow_null=False) password = ObfuscatedPasswordField(required=False, allow_null=False)
auth_token = serializers.SlugRelatedField(read_only=True, slug_field="key") auth_token = serializers.SlugRelatedField(read_only=True, slug_field="key")
@@ -209,7 +209,9 @@ class ProfileSerializer(PasswordValidationMixin, serializers.ModelSerializer):
) )
class ApplicationConfigurationSerializer(serializers.ModelSerializer): class ApplicationConfigurationSerializer(
serializers.ModelSerializer[ApplicationConfiguration],
):
user_args = serializers.JSONField(binary=True, allow_null=True) user_args = serializers.JSONField(binary=True, allow_null=True)
barcode_tag_mapping = serializers.JSONField(binary=True, allow_null=True) barcode_tag_mapping = serializers.JSONField(binary=True, allow_null=True)
llm_api_key = ObfuscatedPasswordField( llm_api_key = ObfuscatedPasswordField(
+9 -8
View File
@@ -1,5 +1,6 @@
from collections import OrderedDict from collections import OrderedDict
from pathlib import Path from pathlib import Path
from typing import Any
from allauth.mfa import signals from allauth.mfa import signals
from allauth.mfa.adapter import get_adapter as get_mfa_adapter from allauth.mfa.adapter import get_adapter as get_mfa_adapter
@@ -114,7 +115,7 @@ class FaviconView(View):
return HttpResponseNotFound("favicon.ico not found") return HttpResponseNotFound("favicon.ico not found")
class UserViewSet(ModelViewSet): class UserViewSet(ModelViewSet[User]):
_BOOL_NOT_PROVIDED = object() _BOOL_NOT_PROVIDED = object()
model = User model = User
@@ -216,7 +217,7 @@ class UserViewSet(ModelViewSet):
return HttpResponseNotFound("TOTP not found") return HttpResponseNotFound("TOTP not found")
class GroupViewSet(ModelViewSet): class GroupViewSet(ModelViewSet[Group]):
model = Group model = Group
queryset = Group.objects.order_by(Lower("name")) queryset = Group.objects.order_by(Lower("name"))
@@ -229,7 +230,7 @@ class GroupViewSet(ModelViewSet):
ordering_fields = ("name",) ordering_fields = ("name",)
class ProfileView(GenericAPIView): class ProfileView(GenericAPIView[Any]):
""" """
User profile view, only available when logged in User profile view, only available when logged in
""" """
@@ -288,7 +289,7 @@ class ProfileView(GenericAPIView):
}, },
), ),
) )
class TOTPView(GenericAPIView): class TOTPView(GenericAPIView[Any]):
""" """
TOTP views TOTP views
""" """
@@ -368,7 +369,7 @@ class TOTPView(GenericAPIView):
}, },
), ),
) )
class GenerateAuthTokenView(GenericAPIView): class GenerateAuthTokenView(GenericAPIView[Any]):
""" """
Generates (or re-generates) an auth token, requires a logged in user Generates (or re-generates) an auth token, requires a logged in user
unlike the default DRF endpoint unlike the default DRF endpoint
@@ -397,7 +398,7 @@ class GenerateAuthTokenView(GenericAPIView):
}, },
), ),
) )
class ApplicationConfigurationViewSet(ModelViewSet): class ApplicationConfigurationViewSet(ModelViewSet[ApplicationConfiguration]):
model = ApplicationConfiguration model = ApplicationConfiguration
queryset = ApplicationConfiguration.objects queryset = ApplicationConfiguration.objects
@@ -450,7 +451,7 @@ class ApplicationConfigurationViewSet(ModelViewSet):
}, },
), ),
) )
class DisconnectSocialAccountView(GenericAPIView): class DisconnectSocialAccountView(GenericAPIView[Any]):
""" """
Disconnects a social account provider from the user account Disconnects a social account provider from the user account
""" """
@@ -476,7 +477,7 @@ class DisconnectSocialAccountView(GenericAPIView):
}, },
), ),
) )
class SocialAccountProvidersView(GenericAPIView): class SocialAccountProvidersView(GenericAPIView[Any]):
""" """
List of social account providers List of social account providers
""" """
+1 -1
View File
@@ -57,7 +57,7 @@ class MailAccountSerializer(OwnedObjectSerializer):
return instance return instance
class AccountField(serializers.PrimaryKeyRelatedField): class AccountField(serializers.PrimaryKeyRelatedField[MailAccount]):
def get_queryset(self): def get_queryset(self):
return MailAccount.objects.all().order_by("-id") return MailAccount.objects.all().order_by("-id")
+5 -4
View File
@@ -1,6 +1,7 @@
import datetime import datetime
import logging import logging
from datetime import timedelta from datetime import timedelta
from typing import Any
from django.http import HttpResponseBadRequest from django.http import HttpResponseBadRequest
from django.http import HttpResponseForbidden from django.http import HttpResponseForbidden
@@ -65,7 +66,7 @@ from paperless_mail.tasks import process_mail_accounts
}, },
), ),
) )
class MailAccountViewSet(ModelViewSet, PassUserMixin): class MailAccountViewSet(PassUserMixin, ModelViewSet[MailAccount]):
model = MailAccount model = MailAccount
queryset = MailAccount.objects.all().order_by("pk") queryset = MailAccount.objects.all().order_by("pk")
@@ -159,7 +160,7 @@ class MailAccountViewSet(ModelViewSet, PassUserMixin):
return Response({"result": "OK"}) return Response({"result": "OK"})
class ProcessedMailViewSet(ReadOnlyModelViewSet, PassUserMixin): class ProcessedMailViewSet(PassUserMixin, ReadOnlyModelViewSet[ProcessedMail]):
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = ProcessedMailSerializer serializer_class = ProcessedMailSerializer
pagination_class = StandardPagination pagination_class = StandardPagination
@@ -187,7 +188,7 @@ class ProcessedMailViewSet(ReadOnlyModelViewSet, PassUserMixin):
return Response({"result": "OK", "deleted_mail_ids": mail_ids}) return Response({"result": "OK", "deleted_mail_ids": mail_ids})
class MailRuleViewSet(ModelViewSet, PassUserMixin): class MailRuleViewSet(PassUserMixin, ModelViewSet[MailRule]):
model = MailRule model = MailRule
queryset = MailRule.objects.all().order_by("order") queryset = MailRule.objects.all().order_by("order")
@@ -203,7 +204,7 @@ class MailRuleViewSet(ModelViewSet, PassUserMixin):
responses={200: None}, responses={200: None},
), ),
) )
class OauthCallbackView(GenericAPIView): class OauthCallbackView(GenericAPIView[Any]):
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
def get(self, request, format=None): def get(self, request, format=None):