mirror of
https://github.com/FuzzyGrim/Yamtrack.git
synced 2026-04-18 12:09:33 +00:00
add django-upgrade pre-commit hook and apply fixes
This commit is contained in:
@@ -7,6 +7,11 @@ repos:
|
||||
language: system
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
- id: django-upgrade
|
||||
name: django-upgrade
|
||||
entry: django-upgrade
|
||||
language: system
|
||||
types: [python]
|
||||
- id: ruff
|
||||
name: ruff
|
||||
entry: ruff check --fix
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
coverage==7.13.3
|
||||
django-upgrade==1.30.0
|
||||
djlint==1.36.4
|
||||
fakeredis==2.33.0
|
||||
pre-commit==4.5.1
|
||||
|
||||
@@ -11,6 +11,7 @@ from app.models import (
|
||||
|
||||
|
||||
# Custom ModelAdmin classes with search functionality
|
||||
@admin.register(Item)
|
||||
class ItemAdmin(admin.ModelAdmin):
|
||||
"""Custom admin for Item model with search and filter options."""
|
||||
|
||||
@@ -26,6 +27,7 @@ class ItemAdmin(admin.ModelAdmin):
|
||||
list_filter = ["media_type", "source"]
|
||||
|
||||
|
||||
@admin.register(Episode)
|
||||
class EpisodeAdmin(admin.ModelAdmin):
|
||||
"""Custom admin for Episode model with search and filter options."""
|
||||
|
||||
@@ -42,8 +44,6 @@ class MediaAdmin(admin.ModelAdmin):
|
||||
|
||||
|
||||
# Register models with custom admin classes
|
||||
admin.site.register(Item, ItemAdmin)
|
||||
admin.site.register(Episode, EpisodeAdmin)
|
||||
|
||||
|
||||
# Auto-register remaining models
|
||||
|
||||
@@ -70,11 +70,11 @@ class Item(CalendarTriggerMixin, models.Model):
|
||||
media_id = models.CharField(max_length=20)
|
||||
source = models.CharField(
|
||||
max_length=20,
|
||||
choices=Sources.choices,
|
||||
choices=Sources,
|
||||
)
|
||||
media_type = models.CharField(
|
||||
max_length=10,
|
||||
choices=MediaTypes.choices,
|
||||
choices=MediaTypes,
|
||||
default=MediaTypes.MOVIE.value,
|
||||
)
|
||||
title = models.TextField()
|
||||
@@ -806,7 +806,7 @@ class Media(models.Model):
|
||||
progressed_at = MonitorField(monitor="progress")
|
||||
status = models.CharField(
|
||||
max_length=20,
|
||||
choices=Status.choices,
|
||||
choices=Status,
|
||||
default=Status.COMPLETED.value,
|
||||
)
|
||||
start_date = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
@@ -145,10 +145,8 @@ class HomeViewTests(TestCase):
|
||||
)
|
||||
|
||||
# Now test the load more functionality
|
||||
headers = {"HTTP_HX_REQUEST": "true"}
|
||||
response = self.client.get(
|
||||
reverse("home") + "?load_media_type=season",
|
||||
**headers,
|
||||
reverse("home") + "?load_media_type=season", headers={"hx-request": "true"}
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@@ -87,18 +87,16 @@ class MediaListViewTests(TestCase):
|
||||
|
||||
def test_media_list_htmx_request(self):
|
||||
"""Test the media list view with HTMX request."""
|
||||
headers = {"HTTP_HX_REQUEST": "true"}
|
||||
|
||||
response = self.client.get(
|
||||
reverse("medialist", args=[MediaTypes.MOVIE.value]) + "?layout=grid",
|
||||
**headers,
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "app/components/media_grid_items.html")
|
||||
|
||||
response = self.client.get(
|
||||
reverse("medialist", args=[MediaTypes.MOVIE.value]) + "?layout=table",
|
||||
**headers,
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "app/components/media_table_items.html")
|
||||
|
||||
@@ -4,6 +4,7 @@ from django.utils import timezone
|
||||
from events.models import Event
|
||||
|
||||
|
||||
@admin.register(Event)
|
||||
class EventAdmin(admin.ModelAdmin):
|
||||
"""Admin configuration for the Event model."""
|
||||
|
||||
@@ -27,6 +28,3 @@ class EventAdmin(admin.ModelAdmin):
|
||||
return timezone.localtime(obj.datetime).strftime("%Y-%m-%d %H:%M")
|
||||
except (OverflowError, ValueError):
|
||||
return "Invalid date"
|
||||
|
||||
|
||||
admin.site.register(Event, EventAdmin)
|
||||
|
||||
@@ -3,6 +3,7 @@ from django.contrib import admin
|
||||
from lists.models import CustomList, CustomListItem
|
||||
|
||||
|
||||
@admin.register(CustomList)
|
||||
class CustomListAdmin(admin.ModelAdmin):
|
||||
"""Admin configuration for CustomList model."""
|
||||
|
||||
@@ -13,20 +14,19 @@ class CustomListAdmin(admin.ModelAdmin):
|
||||
autocomplete_fields = ["collaborators"]
|
||||
filter_horizontal = ["collaborators"]
|
||||
|
||||
@admin.display(description="Number of items")
|
||||
def item_count(self, obj):
|
||||
"""Return the number of items in the list."""
|
||||
return obj.items.count()
|
||||
|
||||
item_count.short_description = "Number of items"
|
||||
|
||||
@admin.display(description="Last updated")
|
||||
def get_last_update(self, obj):
|
||||
"""Return the date of the last item added."""
|
||||
last_update = CustomListItem.objects.get_last_added_date(obj)
|
||||
return last_update or "-"
|
||||
|
||||
get_last_update.short_description = "Last updated"
|
||||
|
||||
|
||||
@admin.register(CustomListItem)
|
||||
class CustomListItemAdmin(admin.ModelAdmin):
|
||||
"""Admin configuration for CustomListItem model."""
|
||||
|
||||
@@ -37,12 +37,7 @@ class CustomListItemAdmin(admin.ModelAdmin):
|
||||
autocomplete_fields = ["item", "custom_list"]
|
||||
readonly_fields = ["date_added"]
|
||||
|
||||
@admin.display(description="Media Type")
|
||||
def get_media_type(self, obj):
|
||||
"""Return the media type of the item."""
|
||||
return obj.item.get_media_type_display()
|
||||
|
||||
get_media_type.short_description = "Media Type"
|
||||
|
||||
|
||||
admin.site.register(CustomList, CustomListAdmin)
|
||||
admin.site.register(CustomListItem, CustomListItemAdmin)
|
||||
|
||||
@@ -136,10 +136,7 @@ class ListsViewTests(TestCase):
|
||||
self.client.login(**self.credentials)
|
||||
|
||||
# Make an HTMX request
|
||||
response = self.client.get(
|
||||
reverse("lists"),
|
||||
HTTP_HX_REQUEST="true",
|
||||
)
|
||||
response = self.client.get(reverse("lists"), headers={"hx-request": "true"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "lists/components/list_grid.html")
|
||||
|
||||
@@ -496,7 +493,7 @@ class ListDetailViewTests(TestCase):
|
||||
# Make an HTMX request
|
||||
response = self.client.get(
|
||||
reverse("list_detail", args=[self.custom_list.id]),
|
||||
HTTP_HX_REQUEST="true",
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "lists/components/media_grid.html")
|
||||
|
||||
@@ -17,6 +17,7 @@ class CustomUserCreationForm(UserCreationForm):
|
||||
fields = ("username",)
|
||||
|
||||
|
||||
@admin.register(User)
|
||||
class CustomUserAdmin(UserAdmin):
|
||||
"""Custom admin interface for the User model."""
|
||||
|
||||
@@ -66,5 +67,4 @@ class CustomUserAdmin(UserAdmin):
|
||||
ordering = ("username",)
|
||||
|
||||
|
||||
admin.site.register(User, CustomUserAdmin)
|
||||
admin.site.unregister(Group)
|
||||
|
||||
@@ -14,7 +14,7 @@ def get_client_ip(request):
|
||||
Used when logging for user registration and login.
|
||||
"""
|
||||
# get the user's IP address
|
||||
ip_address = request.META.get("HTTP_X_FORWARDED_FOR")
|
||||
ip_address = request.headers.get("x-forwarded-for")
|
||||
|
||||
# if the IP address is not available in HTTP_X_FORWARDED_FOR
|
||||
if not ip_address:
|
||||
|
||||
@@ -120,7 +120,7 @@ class User(AbstractUser):
|
||||
home_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=HomeSortChoices.UPCOMING,
|
||||
choices=HomeSortChoices.choices,
|
||||
choices=HomeSortChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: TV Shows
|
||||
@@ -128,17 +128,17 @@ class User(AbstractUser):
|
||||
tv_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.GRID,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
tv_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
tv_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: TV Seasons
|
||||
@@ -146,17 +146,17 @@ class User(AbstractUser):
|
||||
season_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.GRID,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
season_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
season_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: Movies
|
||||
@@ -164,17 +164,17 @@ class User(AbstractUser):
|
||||
movie_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.GRID,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
movie_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
movie_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: Anime
|
||||
@@ -182,17 +182,17 @@ class User(AbstractUser):
|
||||
anime_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.TABLE,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
anime_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
anime_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: Manga
|
||||
@@ -200,17 +200,17 @@ class User(AbstractUser):
|
||||
manga_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.TABLE,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
manga_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
manga_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: Games
|
||||
@@ -218,17 +218,17 @@ class User(AbstractUser):
|
||||
game_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.GRID,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
game_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
game_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: Books
|
||||
@@ -236,17 +236,17 @@ class User(AbstractUser):
|
||||
book_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.GRID,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
book_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
book_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: Comics
|
||||
@@ -254,17 +254,17 @@ class User(AbstractUser):
|
||||
comic_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.GRID,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
comic_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
comic_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Media type preferences: Board Games
|
||||
@@ -272,17 +272,17 @@ class User(AbstractUser):
|
||||
boardgame_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=LayoutChoices.GRID,
|
||||
choices=LayoutChoices.choices,
|
||||
choices=LayoutChoices,
|
||||
)
|
||||
boardgame_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaSortChoices.SCORE,
|
||||
choices=MediaSortChoices.choices,
|
||||
choices=MediaSortChoices,
|
||||
)
|
||||
boardgame_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# UI preferences
|
||||
@@ -295,20 +295,20 @@ class User(AbstractUser):
|
||||
quick_watch_date = models.CharField(
|
||||
max_length=20,
|
||||
default=QuickWatchDateChoices.CURRENT_DATE,
|
||||
choices=QuickWatchDateChoices.choices,
|
||||
choices=QuickWatchDateChoices,
|
||||
help_text="Date to use when bulk-marking media as completed",
|
||||
)
|
||||
|
||||
date_format = models.CharField(
|
||||
max_length=20,
|
||||
default=DateFormatChoices.ISO,
|
||||
choices=DateFormatChoices.choices,
|
||||
choices=DateFormatChoices,
|
||||
help_text="Preferred date display format",
|
||||
)
|
||||
time_format = models.CharField(
|
||||
max_length=20,
|
||||
default=TimeFormatChoices.HOUR_24,
|
||||
choices=TimeFormatChoices.choices,
|
||||
choices=TimeFormatChoices,
|
||||
help_text="Preferred time display format",
|
||||
)
|
||||
|
||||
@@ -341,24 +341,24 @@ class User(AbstractUser):
|
||||
calendar_layout = models.CharField(
|
||||
max_length=20,
|
||||
default=CalendarLayoutChoices.GRID,
|
||||
choices=CalendarLayoutChoices.choices,
|
||||
choices=CalendarLayoutChoices,
|
||||
)
|
||||
|
||||
# Lists preferences
|
||||
lists_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=ListSortChoices.LAST_ITEM_ADDED,
|
||||
choices=ListSortChoices.choices,
|
||||
choices=ListSortChoices,
|
||||
)
|
||||
list_detail_sort = models.CharField(
|
||||
max_length=20,
|
||||
default=ListDetailSortChoices.DATE_ADDED,
|
||||
choices=ListDetailSortChoices.choices,
|
||||
choices=ListDetailSortChoices,
|
||||
)
|
||||
list_detail_status = models.CharField(
|
||||
max_length=20,
|
||||
default=MediaStatusChoices.ALL,
|
||||
choices=MediaStatusChoices.choices,
|
||||
choices=MediaStatusChoices,
|
||||
)
|
||||
|
||||
# Notification settings
|
||||
|
||||
@@ -85,7 +85,7 @@ class NotificationTests(TestCase):
|
||||
response = self.client.post(
|
||||
reverse("exclude_notification_item"),
|
||||
{"item_id": self.item1.id},
|
||||
HTTP_HX_REQUEST="true",
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -102,7 +102,7 @@ class NotificationTests(TestCase):
|
||||
response = self.client.post(
|
||||
reverse("include_notification_item"),
|
||||
{"item_id": self.item1.id},
|
||||
HTTP_HX_REQUEST="true",
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -117,7 +117,7 @@ class NotificationTests(TestCase):
|
||||
response = self.client.get(
|
||||
reverse("search_notification_items"),
|
||||
{"q": "Test"},
|
||||
HTTP_HX_REQUEST="true",
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -131,7 +131,7 @@ class NotificationTests(TestCase):
|
||||
response = self.client.get(
|
||||
reverse("search_notification_items"),
|
||||
{"q": "Test"},
|
||||
HTTP_HX_REQUEST="true",
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
|
||||
self.assertNotContains(response, "Test Anime")
|
||||
@@ -142,7 +142,7 @@ class NotificationTests(TestCase):
|
||||
response = self.client.get(
|
||||
reverse("search_notification_items"),
|
||||
{"q": "T"},
|
||||
HTTP_HX_REQUEST="true",
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -156,7 +156,7 @@ class NotificationTests(TestCase):
|
||||
response = self.client.get(
|
||||
reverse("search_notification_items"),
|
||||
{"q": ""},
|
||||
HTTP_HX_REQUEST="true",
|
||||
headers={"hx-request": "true"},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
Reference in New Issue
Block a user