Fix some type hints

This commit is contained in:
Sascha Ißbrücker
2025-03-09 11:30:13 +01:00
parent 4260dfce79
commit 1a1092d03a
16 changed files with 121 additions and 162 deletions

View File

@@ -19,6 +19,7 @@ from bookmarks.api.serializers import (
)
from bookmarks.models import Bookmark, BookmarkAsset, BookmarkSearch, Tag, User
from bookmarks.services import assets, bookmarks, auto_tagging, website_loader
from bookmarks.type_defs import HttpRequest
logger = logging.getLogger(__name__)
@@ -31,6 +32,7 @@ class BookmarkViewSet(
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
):
request: HttpRequest
serializer_class = BookmarkSerializer
def get_permissions(self):
@@ -73,27 +75,27 @@ class BookmarkViewSet(
}
@action(methods=["get"], detail=False)
def archived(self, request):
def archived(self, request: HttpRequest):
return self.list(request)
@action(methods=["get"], detail=False)
def shared(self, request):
def shared(self, request: HttpRequest):
return self.list(request)
@action(methods=["post"], detail=True)
def archive(self, request, pk):
def archive(self, request: HttpRequest, pk):
bookmark = self.get_object()
bookmarks.archive_bookmark(bookmark)
return Response(status=status.HTTP_204_NO_CONTENT)
@action(methods=["post"], detail=True)
def unarchive(self, request, pk):
def unarchive(self, request: HttpRequest, pk):
bookmark = self.get_object()
bookmarks.unarchive_bookmark(bookmark)
return Response(status=status.HTTP_204_NO_CONTENT)
@action(methods=["get"], detail=False)
def check(self, request):
def check(self, request: HttpRequest):
url = request.GET.get("url")
bookmark = Bookmark.objects.filter(owner=request.user, url=url).first()
existing_bookmark_data = (
@@ -124,13 +126,13 @@ class BookmarkViewSet(
)
@action(methods=["post"], detail=False)
def singlefile(self, request):
def singlefile(self, request: HttpRequest):
if settings.LD_DISABLE_ASSET_UPLOAD:
return Response(
{"error": "Asset upload is disabled."},
status=status.HTTP_403_FORBIDDEN,
)
url = request.data.get("url")
url = request.POST.get("url")
file = request.FILES.get("file")
if not url or not file:
@@ -162,6 +164,7 @@ class BookmarkAssetViewSet(
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
):
request: HttpRequest
serializer_class = BookmarkAssetSerializer
def get_queryset(self):
@@ -177,7 +180,7 @@ class BookmarkAssetViewSet(
return {"user": self.request.user}
@action(detail=True, methods=["get"], url_path="download")
def download(self, request, bookmark_id, pk):
def download(self, request: HttpRequest, bookmark_id, pk):
asset = self.get_object()
try:
file_path = os.path.join(settings.LD_ASSET_FOLDER, asset.file)
@@ -205,7 +208,7 @@ class BookmarkAssetViewSet(
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@action(methods=["post"], detail=False)
def upload(self, request, bookmark_id):
def upload(self, request: HttpRequest, bookmark_id):
if settings.LD_DISABLE_ASSET_UPLOAD:
return Response(
{"error": "Asset upload is disabled."},
@@ -242,6 +245,7 @@ class TagViewSet(
mixins.RetrieveModelMixin,
mixins.CreateModelMixin,
):
request: HttpRequest
serializer_class = TagSerializer
def get_queryset(self):
@@ -254,7 +258,7 @@ class TagViewSet(
class UserViewSet(viewsets.GenericViewSet):
@action(methods=["get"], detail=False)
def profile(self, request):
def profile(self, request: HttpRequest):
return Response(UserProfileSerializer(request.user.profile).data)

View File

@@ -22,6 +22,11 @@ class BookmarkListSerializer(ListSerializer):
return super().to_representation(data)
class EmtpyField(serializers.ReadOnlyField):
def to_representation(self, value):
return None
class BookmarkSerializer(serializers.ModelSerializer):
class Meta:
model = Bookmark
@@ -62,8 +67,8 @@ class BookmarkSerializer(serializers.ModelSerializer):
preview_image_url = serializers.SerializerMethodField()
web_archive_snapshot_url = serializers.SerializerMethodField()
# Add dummy website title and description fields for backwards compatibility but keep them empty
website_title = serializers.SerializerMethodField()
website_description = serializers.SerializerMethodField()
website_title = EmtpyField()
website_description = EmtpyField()
def get_favicon_url(self, obj: Bookmark):
if not obj.favicon_file:
@@ -87,12 +92,6 @@ class BookmarkSerializer(serializers.ModelSerializer):
return generate_fallback_webarchive_url(obj.url, obj.date_added)
def get_website_title(self, obj: Bookmark):
return None
def get_website_description(self, obj: Bookmark):
return None
def create(self, validated_data):
tag_names = validated_data.pop("tag_names", [])
tag_string = build_tag_string(tag_names)
@@ -185,9 +184,5 @@ class UserProfileSerializer(serializers.ModelSerializer):
"search_preferences",
"version",
]
read_only_fields = ["version"]
version = serializers.SerializerMethodField()
def get_version(self, obj: UserProfile):
return app_version
version = serializers.ReadOnlyField(default=app_version)

View File

@@ -1,6 +1,5 @@
from bookmarks import queries
from bookmarks.models import BookmarkSearch, Toast
from bookmarks import utils
from bookmarks.models import Toast
def toasts(request):

View File

@@ -6,7 +6,6 @@ from typing import List
from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
from django.core.validators import MinValueValidator
from django.db import models
@@ -23,7 +22,7 @@ logger = logging.getLogger(__name__)
class Tag(models.Model):
name = models.CharField(max_length=64)
date_added = models.DateTimeField()
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name
@@ -70,7 +69,7 @@ class Bookmark(models.Model):
date_added = models.DateTimeField()
date_modified = models.DateTimeField()
date_accessed = models.DateTimeField(blank=True, null=True)
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag)
@property
@@ -387,9 +386,7 @@ class UserProfile(models.Model):
(TAG_GROUPING_ALPHABETICAL, "Alphabetical"),
(TAG_GROUPING_DISABLED, "Disabled"),
]
user = models.OneToOneField(
get_user_model(), related_name="profile", on_delete=models.CASCADE
)
user = models.OneToOneField(User, related_name="profile", on_delete=models.CASCADE)
theme = models.CharField(
max_length=10, choices=THEME_CHOICES, blank=False, default=THEME_AUTO
)
@@ -497,13 +494,13 @@ class UserProfileForm(forms.ModelForm):
]
@receiver(post_save, sender=get_user_model())
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=get_user_model())
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
@@ -512,7 +509,7 @@ class Toast(models.Model):
key = models.CharField(max_length=50)
message = models.TextField()
acknowledged = models.BooleanField(default=False)
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
class FeedToken(models.Model):
@@ -522,7 +519,7 @@ class FeedToken(models.Model):
key = models.CharField(max_length=40, primary_key=True)
user = models.OneToOneField(
get_user_model(),
User,
related_name="feed_token",
on_delete=models.CASCADE,
)
@@ -556,7 +553,7 @@ class GlobalSettings(models.Model):
default=LANDING_PAGE_LOGIN,
)
guest_profile_user = models.ForeignKey(
get_user_model(), on_delete=models.SET_NULL, null=True, blank=True
User, on_delete=models.SET_NULL, null=True, blank=True
)
enable_link_prefetch = models.BooleanField(default=False, null=False)

View File

@@ -1,10 +1,9 @@
import logging
from typing import Union
from django.contrib.auth.models import User
from django.utils import timezone
from bookmarks.models import Bookmark, parse_tag_string
from bookmarks.models import Bookmark, User, parse_tag_string
from bookmarks.services import auto_tagging
from bookmarks.services import tasks
from bookmarks.services import website_loader

View File

@@ -4,7 +4,6 @@ from typing import List
import waybackpy
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
from django.db.models import Q
from huey import crontab
@@ -157,7 +156,7 @@ def schedule_bookmarks_without_favicons(user: User):
@task()
def _schedule_bookmarks_without_favicons_task(user_id: int):
user = get_user_model().objects.get(id=user_id)
user = User.objects.get(id=user_id)
bookmarks = Bookmark.objects.filter(favicon_file__exact="", owner=user)
# TODO: Implement bulk task creation
@@ -173,7 +172,7 @@ def schedule_refresh_favicons(user: User):
@task()
def _schedule_refresh_favicons_task(user_id: int):
user = get_user_model().objects.get(id=user_id)
user = User.objects.get(id=user_id)
bookmarks = Bookmark.objects.filter(owner=user)
# TODO: Implement bulk task creation
@@ -212,7 +211,7 @@ def schedule_bookmarks_without_previews(user: User):
@task()
def _schedule_bookmarks_without_previews_task(user_id: int):
user = get_user_model().objects.get(id=user_id)
user = User.objects.get(id=user_id)
bookmarks = Bookmark.objects.filter(
Q(preview_image_file__exact=""),
owner=user,

View File

@@ -10,7 +10,6 @@ from unittest import TestCase
from bs4 import BeautifulSoup
from django.conf import settings
from django.contrib.auth.models import User
from django.test import override_settings
from django.utils import timezone
from django.utils.crypto import get_random_string
@@ -18,7 +17,7 @@ from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase
from bookmarks.models import Bookmark, BookmarkAsset, Tag
from bookmarks.models import Bookmark, BookmarkAsset, Tag, User
class BookmarkFactoryMixin:

View File

@@ -138,8 +138,7 @@ class BookmarkNewViewTestCase(TestCase, BookmarkFactoryMixin):
html = response.content.decode()
self.assertInHTML(
'<input type="hidden" name="auto_close" value="true" '
'id="id_auto_close">',
'<input type="hidden" name="auto_close" value="True" id="id_auto_close">',
html,
)
@@ -148,7 +147,8 @@ class BookmarkNewViewTestCase(TestCase, BookmarkFactoryMixin):
html = response.content.decode()
self.assertInHTML(
'<input type="hidden" name="auto_close" id="id_auto_close">', html
'<input type="hidden" name="auto_close" id="id_auto_close">',
html,
)
def test_should_redirect_to_index_view(self):
@@ -264,7 +264,6 @@ class BookmarkNewViewTestCase(TestCase, BookmarkFactoryMixin):
html = response.content.decode()
self.assertInHTML(
'<input type="checkbox" name="unread" value="true" '
'id="id_unread" checked="">',
'<input type="checkbox" name="unread" id="id_unread" checked="">',
html,
)

View File

@@ -1,12 +1,10 @@
import datetime
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.test import TestCase, override_settings
from bookmarks.models import BookmarkForm, Bookmark
User = get_user_model()
from bookmarks.tests.helpers import BookmarkFactoryMixin
ENABLED_URL_VALIDATION_TEST_CASES = [
("thisisnotavalidurl", False),
@@ -29,12 +27,10 @@ DISABLED_URL_VALIDATION_TEST_CASES = [
]
class BookmarkValidationTestCase(TestCase):
class BookmarkValidationTestCase(TestCase, BookmarkFactoryMixin):
def setUp(self) -> None:
self.user = User.objects.create_user(
"testuser", "test@example.com", "password123"
)
self.get_or_create_test_user()
def test_bookmark_model_should_not_allow_missing_url(self):
bookmark = Bookmark(

View File

@@ -1,6 +1,5 @@
from unittest.mock import patch
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.utils import timezone
@@ -25,8 +24,6 @@ from bookmarks.services.bookmarks import (
)
from bookmarks.tests.helpers import BookmarkFactoryMixin
User = get_user_model()
class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
@@ -270,9 +267,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertTrue(Bookmark.objects.get(id=bookmark3.id).is_archived)
def test_archive_bookmarks_should_only_archive_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark()
bookmark2 = self.setup_bookmark()
inaccessible_bookmark = self.setup_bookmark(user=other_user)
@@ -327,9 +322,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertFalse(Bookmark.objects.get(id=bookmark3.id).is_archived)
def test_unarchive_bookmarks_should_only_unarchive_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark(is_archived=True)
bookmark2 = self.setup_bookmark(is_archived=True)
inaccessible_bookmark = self.setup_bookmark(is_archived=True, user=other_user)
@@ -382,9 +375,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertIsNone(Bookmark.objects.filter(id=bookmark3.id).first())
def test_delete_bookmarks_should_only_delete_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark()
bookmark2 = self.setup_bookmark()
inaccessible_bookmark = self.setup_bookmark(user=other_user)
@@ -508,9 +499,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertCountEqual(bookmark3.tags.all(), [tag1, tag2])
def test_tag_bookmarks_should_only_tag_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark()
bookmark2 = self.setup_bookmark()
inaccessible_bookmark = self.setup_bookmark(user=other_user)
@@ -591,9 +580,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertCountEqual(bookmark3.tags.all(), [])
def test_untag_bookmarks_should_only_tag_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
tag1 = self.setup_tag()
tag2 = self.setup_tag()
bookmark1 = self.setup_bookmark(tags=[tag1, tag2])
@@ -658,9 +645,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertFalse(Bookmark.objects.get(id=bookmark3.id).unread)
def test_mark_bookmarks_as_read_should_only_update_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark(unread=True)
bookmark2 = self.setup_bookmark(unread=True)
inaccessible_bookmark = self.setup_bookmark(unread=True, user=other_user)
@@ -715,9 +700,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertTrue(Bookmark.objects.get(id=bookmark3.id).unread)
def test_mark_bookmarks_as_unread_should_only_update_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark(unread=False)
bookmark2 = self.setup_bookmark(unread=False)
inaccessible_bookmark = self.setup_bookmark(unread=False, user=other_user)
@@ -770,9 +753,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertTrue(Bookmark.objects.get(id=bookmark3.id).shared)
def test_share_bookmarks_should_only_update_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark(shared=False)
bookmark2 = self.setup_bookmark(shared=False)
inaccessible_bookmark = self.setup_bookmark(shared=False, user=other_user)
@@ -825,9 +806,7 @@ class BookmarkServiceTestCase(TestCase, BookmarkFactoryMixin):
self.assertFalse(Bookmark.objects.get(id=bookmark3.id).shared)
def test_unshare_bookmarks_should_only_update_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
bookmark1 = self.setup_bookmark(shared=True)
bookmark2 = self.setup_bookmark(shared=True)
inaccessible_bookmark = self.setup_bookmark(shared=True, user=other_user)

View File

@@ -1,7 +1,6 @@
import operator
import datetime
import operator
from django.contrib.auth import get_user_model
from django.db.models import QuerySet
from django.test import TestCase
from django.utils import timezone
@@ -11,8 +10,6 @@ from bookmarks.models import BookmarkSearch, UserProfile
from bookmarks.tests.helpers import BookmarkFactoryMixin, random_sentence
from bookmarks.utils import unique
User = get_user_model()
class QueriesTestCase(TestCase, BookmarkFactoryMixin):
def setUp(self):
@@ -372,9 +369,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
self.assertQueryResult(query, [[bookmark1, bookmark2]])
def test_query_bookmarks_should_only_return_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
owned_bookmarks = [
self.setup_bookmark(),
self.setup_bookmark(),
@@ -389,9 +384,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
self.assertQueryResult(query, [owned_bookmarks])
def test_query_archived_bookmarks_should_only_return_user_owned_bookmarks(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
owned_bookmarks = [
self.setup_bookmark(is_archived=True),
self.setup_bookmark(is_archived=True),
@@ -828,9 +821,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
self.assertQueryResult(query, [[tag]])
def test_query_bookmark_tags_should_only_return_user_owned_tags(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
owned_bookmarks = [
self.setup_bookmark(tags=[self.setup_tag()]),
self.setup_bookmark(tags=[self.setup_tag()]),
@@ -847,9 +838,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
self.assertQueryResult(query, [self.get_tags_from_bookmarks(owned_bookmarks)])
def test_query_archived_bookmark_tags_should_only_return_user_owned_tags(self):
other_user = User.objects.create_user(
"otheruser", "otheruser@example.com", "password123"
)
other_user = self.setup_user()
owned_bookmarks = [
self.setup_bookmark(is_archived=True, tags=[self.setup_tag()]),
self.setup_bookmark(is_archived=True, tags=[self.setup_tag()]),

View File

@@ -1,21 +1,17 @@
import datetime
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.utils import timezone
from bookmarks.models import Tag
from bookmarks.services.tags import get_or_create_tag, get_or_create_tags
User = get_user_model()
from bookmarks.tests.helpers import BookmarkFactoryMixin
class TagServiceTestCase(TestCase):
class TagServiceTestCase(TestCase, BookmarkFactoryMixin):
def setUp(self) -> None:
self.user = User.objects.create_user(
"testuser", "test@example.com", "password123"
)
self.get_or_create_test_user()
def test_get_or_create_tag_should_create_new_tag(self):
get_or_create_tag("Book", self.user)

14
bookmarks/type_defs.py Normal file
View File

@@ -0,0 +1,14 @@
"""
Stuff in here is only used for type hints
"""
from django import http
from django.contrib.auth.models import AnonymousUser
from bookmarks.models import GlobalSettings, UserProfile, User
class HttpRequest(http.HttpRequest):
global_settings: GlobalSettings
user_profile: UserProfile
user: User | AnonymousUser

View File

@@ -36,12 +36,13 @@ from bookmarks.services.bookmarks import (
share_bookmarks,
unshare_bookmarks,
)
from bookmarks.type_defs import HttpRequest
from bookmarks.utils import get_safe_return_url
from bookmarks.views import contexts, partials, turbo
@login_required
def index(request):
def index(request: HttpRequest):
if request.method == "POST":
return search_action(request)
@@ -63,7 +64,7 @@ def index(request):
@login_required
def archived(request):
def archived(request: HttpRequest):
if request.method == "POST":
return search_action(request)
@@ -84,7 +85,7 @@ def archived(request):
)
def shared(request):
def shared(request: HttpRequest):
if request.method == "POST":
return search_action(request)
@@ -110,7 +111,7 @@ def shared(request):
)
def render_bookmarks_view(request, template_name, context):
def render_bookmarks_view(request: HttpRequest, template_name, context):
if turbo.is_frame(request, "details-modal"):
return render(
request,
@@ -125,7 +126,7 @@ def render_bookmarks_view(request, template_name, context):
)
def search_action(request):
def search_action(request: HttpRequest):
if "save" in request.POST:
if not request.user.is_authenticated:
return HttpResponseForbidden()
@@ -151,13 +152,8 @@ def convert_tag_string(tag_string: str):
@login_required
def new(request):
initial_url = request.GET.get("url")
initial_title = request.GET.get("title")
initial_description = request.GET.get("description")
initial_notes = request.GET.get("notes")
initial_auto_close = "auto_close" in request.GET
initial_mark_unread = request.user.profile.default_mark_unread
def new(request: HttpRequest):
initial_auto_close = True if "auto_close" in request.GET else None
if request.method == "POST":
form = BookmarkForm(request.POST)
@@ -171,19 +167,16 @@ def new(request):
else:
return HttpResponseRedirect(reverse("linkding:bookmarks.index"))
else:
form = BookmarkForm()
if initial_url:
form.initial["url"] = initial_url
if initial_title:
form.initial["title"] = initial_title
if initial_description:
form.initial["description"] = initial_description
if initial_notes:
form.initial["notes"] = initial_notes
if initial_auto_close:
form.initial["auto_close"] = "true"
if initial_mark_unread:
form.initial["unread"] = "true"
form = BookmarkForm(
initial={
"url": request.GET.get("url"),
"title": request.GET.get("title"),
"description": request.GET.get("description"),
"notes": request.GET.get("notes"),
"auto_close": initial_auto_close,
"unread": request.user_profile.default_mark_unread,
}
)
status = 422 if request.method == "POST" and not form.is_valid() else 200
context = {
@@ -196,7 +189,7 @@ def new(request):
@login_required
def edit(request, bookmark_id: int):
def edit(request: HttpRequest, bookmark_id: int):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -214,7 +207,7 @@ def edit(request, bookmark_id: int):
else:
form = BookmarkForm(instance=bookmark)
form.initial["tag_string"] = build_tag_string(bookmark.tag_names, " ")
form.fields["tag_string"].initial = build_tag_string(bookmark.tag_names, " ")
status = 422 if request.method == "POST" and not form.is_valid() else 200
context = {"form": form, "bookmark_id": bookmark_id, "return_url": return_url}
@@ -222,7 +215,7 @@ def edit(request, bookmark_id: int):
return render(request, "bookmarks/edit.html", context, status=status)
def remove(request, bookmark_id: int):
def remove(request: HttpRequest, bookmark_id: int | str):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -231,7 +224,7 @@ def remove(request, bookmark_id: int):
bookmark.delete()
def archive(request, bookmark_id: int):
def archive(request: HttpRequest, bookmark_id: int | str):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -240,7 +233,7 @@ def archive(request, bookmark_id: int):
archive_bookmark(bookmark)
def unarchive(request, bookmark_id: int):
def unarchive(request: HttpRequest, bookmark_id: int | str):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -249,7 +242,7 @@ def unarchive(request, bookmark_id: int):
unarchive_bookmark(bookmark)
def unshare(request, bookmark_id: int):
def unshare(request: HttpRequest, bookmark_id: int | str):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -259,7 +252,7 @@ def unshare(request, bookmark_id: int):
bookmark.save()
def mark_as_read(request, bookmark_id: int):
def mark_as_read(request: HttpRequest, bookmark_id: int | str):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -269,7 +262,7 @@ def mark_as_read(request, bookmark_id: int):
bookmark.save()
def create_html_snapshot(request, bookmark_id: int):
def create_html_snapshot(request: HttpRequest, bookmark_id: int | str):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -278,7 +271,7 @@ def create_html_snapshot(request, bookmark_id: int):
tasks.create_html_snapshot(bookmark)
def upload_asset(request, bookmark_id: int):
def upload_asset(request: HttpRequest, bookmark_id: int | str):
if settings.LD_DISABLE_ASSET_UPLOAD:
return HttpResponseForbidden("Asset upload is disabled")
@@ -294,7 +287,7 @@ def upload_asset(request, bookmark_id: int):
asset_actions.upload_asset(bookmark, file)
def remove_asset(request, asset_id: int):
def remove_asset(request: HttpRequest, asset_id: int | str):
try:
asset = BookmarkAsset.objects.get(pk=asset_id, bookmark__owner=request.user)
except BookmarkAsset.DoesNotExist:
@@ -303,7 +296,7 @@ def remove_asset(request, asset_id: int):
asset.delete()
def update_state(request, bookmark_id: int):
def update_state(request: HttpRequest, bookmark_id: int | str):
try:
bookmark = Bookmark.objects.get(pk=bookmark_id, owner=request.user)
except Bookmark.DoesNotExist:
@@ -316,7 +309,7 @@ def update_state(request, bookmark_id: int):
@login_required
def index_action(request):
def index_action(request: HttpRequest):
search = BookmarkSearch.from_request(request.GET)
query = queries.query_bookmarks(request.user, request.user_profile, search)
@@ -331,7 +324,7 @@ def index_action(request):
@login_required
def archived_action(request):
def archived_action(request: HttpRequest):
search = BookmarkSearch.from_request(request.GET)
query = queries.query_archived_bookmarks(request.user, request.user_profile, search)
@@ -346,7 +339,7 @@ def archived_action(request):
@login_required
def shared_action(request):
def shared_action(request: HttpRequest):
if "bulk_execute" in request.POST:
return HttpResponseBadRequest("View does not support bulk actions")
@@ -360,7 +353,7 @@ def shared_action(request):
return utils.redirect_with_query(request, reverse("linkding:bookmarks.shared"))
def handle_action(request, query: QuerySet[Bookmark] = None):
def handle_action(request: HttpRequest, query: QuerySet[Bookmark] = None):
# Single bookmark actions
if "archive" in request.POST:
return archive(request, request.POST["archive"])
@@ -421,5 +414,5 @@ def handle_action(request, query: QuerySet[Bookmark] = None):
@login_required
def close(request):
def close(request: HttpRequest):
return render(request, "bookmarks/close.html")

View File

@@ -3,7 +3,6 @@ import urllib.parse
from typing import Set, List
from django.conf import settings
from django.core.handlers.wsgi import WSGIRequest
from django.core.paginator import Paginator
from django.db import models
from django.http import Http404
@@ -20,6 +19,7 @@ from bookmarks.models import (
Tag,
)
from bookmarks.services.wayback import generate_fallback_webarchive_url
from bookmarks.type_defs import HttpRequest
CJK_RE = re.compile(r"[\u4e00-\u9fff]+")
@@ -28,7 +28,7 @@ class RequestContext:
index_view = "linkding:bookmarks.index"
action_view = "linkding:bookmarks.index.action"
def __init__(self, request: WSGIRequest):
def __init__(self, request: HttpRequest):
self.request = request
self.index_url = reverse(self.index_view)
self.action_url = reverse(self.action_view)
@@ -168,7 +168,7 @@ class BookmarkItem:
class BookmarkListContext:
request_context = RequestContext
def __init__(self, request: WSGIRequest) -> None:
def __init__(self, request: HttpRequest) -> None:
request_context = self.request_context(request)
user = request.user
user_profile = request.user_profile
@@ -305,7 +305,7 @@ class TagGroup:
class TagCloudContext:
request_context = RequestContext
def __init__(self, request: WSGIRequest) -> None:
def __init__(self, request: HttpRequest) -> None:
request_context = self.request_context(request)
user_profile = request.user_profile
@@ -381,7 +381,7 @@ class BookmarkAssetItem:
class BookmarkDetailsContext:
request_context = RequestContext
def __init__(self, request: WSGIRequest, bookmark: Bookmark):
def __init__(self, request: HttpRequest, bookmark: Bookmark):
request_context = self.request_context(request)
user = request.user
@@ -437,7 +437,7 @@ class SharedBookmarkDetailsContext(BookmarkDetailsContext):
def get_details_context(
request: WSGIRequest, context_type
request: HttpRequest, context_type
) -> BookmarkDetailsContext | None:
bookmark_id = request.GET.get("details")
if not bookmark_id:

View File

@@ -22,13 +22,14 @@ from bookmarks.models import (
)
from bookmarks.services import exporter, tasks
from bookmarks.services import importer
from bookmarks.type_defs import HttpRequest
from bookmarks.utils import app_version
logger = logging.getLogger(__name__)
@login_required
def general(request, status=200, context_overrides=None):
def general(request: HttpRequest, status=200, context_overrides=None):
enable_refresh_favicons = django_settings.LD_ENABLE_REFRESH_FAVICONS
has_snapshot_support = django_settings.LD_ENABLE_SNAPSHOTS
success_message = _find_message_with_tag(
@@ -65,7 +66,7 @@ def general(request, status=200, context_overrides=None):
@login_required
def update(request):
def update(request: HttpRequest):
if request.method == "POST":
if "update_profile" in request.POST:
return update_profile(request)
@@ -97,7 +98,7 @@ def update(request):
return HttpResponseRedirect(reverse("linkding:settings.general"))
def update_profile(request):
def update_profile(request: HttpRequest):
user = request.user
profile = user.profile
favicons_were_enabled = profile.enable_favicons
@@ -195,7 +196,7 @@ def integrations(request):
@login_required
def bookmark_import(request):
def bookmark_import(request: HttpRequest):
import_file = request.FILES.get("import_file")
import_options = importer.ImportOptions(
map_private_flag=request.POST.get("map_private_flag") == "on"
@@ -230,13 +231,13 @@ def bookmark_import(request):
@login_required
def bookmark_export(request):
def bookmark_export(request: HttpRequest):
# noinspection PyBroadException
try:
bookmarks = Bookmark.objects.filter(owner=request.user)
# Prefetch tags to prevent n+1 queries
prefetch_related_objects(bookmarks, "tags")
file_content = exporter.export_netscape_html(bookmarks)
file_content = exporter.export_netscape_html(list(bookmarks))
response = HttpResponse(content_type="text/plain; charset=UTF-8")
response["Content-Disposition"] = 'attachment; filename="bookmarks.html"'