Skip to content

Commit 4a3b27a

Browse files
committed
feat: Add support for django5.2
1 parent c6ed5cb commit 4a3b27a

File tree

12 files changed

+46
-41
lines changed

12 files changed

+46
-41
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
strategy:
3838
matrix:
3939
python-version: ["3.12"]
40-
django-version: ["django42"]
40+
django-version: ["django42", "django52"]
4141
steps:
4242
- uses: actions/checkout@v4
4343
- uses: actions/setup-python@v5
@@ -63,7 +63,7 @@ jobs:
6363
make static
6464
make tests
6565
- name: Run code coverage
66-
if: matrix.python-version == '3.12' && matrix.django-version == 'django42'
66+
if: matrix.python-version == '3.12' && matrix.django-version == 'django52'
6767
uses: codecov/codecov-action@v5
6868
with:
6969
flags: unittests

credentials/apps/api/v2/decorators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def wrapper(*args, **kwargs):
2626
data = request.body
2727
logger.info(
2828
f"{request.method} request received to endpoint [{request.get_full_path()}] from user "
29-
f"[{request.user.username}] originating from [{request.META.get('HTTP_HOST', 'Unknown')}] "
29+
f"[{request.user.username}] originating from [{request.headers.get('host', 'Unknown')}] "
3030
f"with data: [{data}]"
3131
)
3232
except Exception as exc:

credentials/apps/api/v2/tests/test_serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
from datetime import datetime
33
from logging import WARNING
44
from uuid import uuid4
5+
from zoneinfo import ZoneInfo
56

67
import ddt
7-
import pytz
88
from django.test import TestCase
99
from django.urls import reverse
1010
from rest_framework.exceptions import ValidationError
@@ -204,7 +204,7 @@ def test_to_internal_value(self):
204204
Request = namedtuple("Request", ["site"])
205205
serializer = UserGradeSerializer(context={"request": Request(site=self.site)})
206206
updated_at_dt = datetime.now()
207-
updated_at_utc = updated_at_dt.replace(tzinfo=pytz.UTC)
207+
updated_at_utc = updated_at_dt.replace(tzinfo=ZoneInfo("UTC"))
208208

209209
data = {
210210
"username": "alice",

credentials/apps/api/v2/tests/test_views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import json
33
from decimal import Decimal
44
from unittest import mock
5+
from zoneinfo import ZoneInfo
56

67
import ddt
7-
import pytz
88
from django.contrib.auth.models import Permission
99
from django.core.exceptions import ObjectDoesNotExist
1010
from django.test import TestCase
@@ -598,7 +598,7 @@ def test_upgrade_with_lms_last_updated_at_data(self):
598598

599599
# simulate updating the existing record with the new field in the data
600600
dt = datetime.datetime.now()
601-
last_updated_at = dt.replace(tzinfo=pytz.UTC)
601+
last_updated_at = dt.replace(tzinfo=ZoneInfo("UTC"))
602602
data = self.serialize_user_grade(grade)
603603
data["lms_last_updated_at"] = last_updated_at
604604
response = self.client.post(self.list_path, data=JSONRenderer().render(data), content_type=JSON_CONTENT_TYPE)

credentials/apps/badges/admin.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ def delete_queryset(self, request, queryset):
318318
return
319319
super().delete_queryset(request, queryset)
320320

321+
@admin.display(description=_("icon"))
321322
def image(self, obj):
322323
"""
323324
Badge template preview image.
@@ -326,8 +327,6 @@ def image(self, obj):
326327
return format_html('<img src="{}" width="50" height="auto" />', obj.icon)
327328
return None
328329

329-
image.short_description = _("icon")
330-
331330
def save_model(self, request, obj, form, change):
332331
pass
333332

@@ -391,6 +390,7 @@ class BadgeRequirementAdmin(admin.ModelAdmin):
391390
def has_add_permission(self, request):
392391
return False
393392

393+
@admin.display(description=_("badge template"))
394394
def template_link(self, instance):
395395
"""
396396
Interactive link to parent (badge template).
@@ -401,8 +401,6 @@ def template_link(self, instance):
401401
url = reverse(reverse_name, args=reverse_args)
402402
return format_html('<a href="{}">{}</a>', url, instance.template)
403403

404-
template_link.short_description = _("badge template")
405-
406404
def response_change(self, request, obj):
407405
if "_save" in request.POST:
408406
reverse_name = ADMIN_CHANGE_VIEW_REVERSE_NAMES.get(obj.template.origin, "admin:index")
@@ -453,6 +451,7 @@ class BadgePenaltyAdmin(admin.ModelAdmin):
453451
def has_add_permission(self, request):
454452
return False
455453

454+
@admin.display(description=_("badge template"))
456455
def template_link(self, instance):
457456
"""
458457
Interactive link to parent (badge template).
@@ -462,8 +461,6 @@ def template_link(self, instance):
462461
url = reverse(reverse_name, args=reverse_args)
463462
return format_html('<a href="{}">{}</a>', url, instance.template)
464463

465-
template_link.short_description = _("badge template")
466-
467464
def formfield_for_manytomany(self, db_field, request, **kwargs):
468465
if db_field.name == "requirements":
469466
object_id = request.resolver_match.kwargs.get("object_id")

credentials/apps/catalog/tests/factories.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
import datetime
66
from uuid import uuid4
7+
from zoneinfo import ZoneInfo
78

89
import factory
910
from factory.fuzzy import FuzzyDateTime, FuzzyInteger, FuzzyText
10-
from pytz import UTC
1111
from slugify import slugify
1212

1313
from credentials.apps.catalog.data import PathwayStatus
@@ -35,6 +35,7 @@ class Meta:
3535
class CourseFactory(factory.django.DjangoModelFactory):
3636
class Meta:
3737
model = Course
38+
skip_postgeneration_save = True
3839

3940
site = factory.SubFactory(SiteFactory)
4041
uuid = factory.LazyFunction(uuid4)
@@ -55,13 +56,14 @@ class Meta:
5556
uuid = factory.LazyFunction(uuid4)
5657
key = FuzzyText(prefix="course-run-id/", suffix="/fake")
5758
title_override = None
58-
start_date = FuzzyDateTime(datetime.datetime(2014, 1, 1, tzinfo=UTC))
59-
end_date = FuzzyDateTime(datetime.datetime(2014, 1, 1, tzinfo=UTC)).end_dt
59+
start_date = FuzzyDateTime(datetime.datetime(2014, 1, 1, tzinfo=ZoneInfo("UTC")))
60+
end_date = FuzzyDateTime(datetime.datetime(2014, 1, 1, tzinfo=ZoneInfo("UTC"))).end_dt
6061

6162

6263
class ProgramFactory(factory.django.DjangoModelFactory):
6364
class Meta:
6465
model = Program
66+
skip_postgeneration_save = True
6567

6668
site = factory.SubFactory(SiteFactory)
6769
uuid = factory.LazyFunction(uuid4)

credentials/settings/base.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,11 @@
230230
TIME_ZONE = "UTC"
231231
TIME_ZONE_CLASS = timezone.utc
232232

233+
# Using zoneinfo from the standard library instead of pytz
233234
# https://docs.djangoproject.com/en/4.2/releases/4.0/#zoneinfo-default-timezone-implementation
234-
USE_DEPRECATED_PYTZ = True
235235

236236
USE_I18N = True
237237

238-
USE_L10N = True
239-
240238
USE_TZ = True
241239

242240
LOCALE_PATHS = (root("conf", "locale"),)
@@ -422,6 +420,9 @@
422420
"EXCEPTION_HANDLER": "credentials.apps.api.v2.views.credentials_throttle_handler",
423421
}
424422

423+
# DRF-YASG Settings
424+
SWAGGER_USE_COMPAT_RENDERERS = False
425+
425426
# Django-ratelimit Settings
426427
RATELIMIT_VIEW = "credentials.apps.records.views.rate_limited"
427428

@@ -460,7 +461,14 @@
460461
FILE_STORAGE_BACKEND = {}
461462
EXTRA_APPS = []
462463
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
463-
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
464+
STORAGES = {
465+
"default": {
466+
"BACKEND": "django.core.files.storage.FileSystemStorage",
467+
},
468+
"staticfiles": {
469+
"BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
470+
},
471+
}
464472
CACHES = {
465473
"default": {
466474
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",

credentials/settings/test.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@
3535

3636
# Local Directories
3737
TEST_ROOT = path("test_root")
38-
DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage"
38+
STORAGES = {
39+
**STORAGES,
40+
"default": {
41+
"BACKEND": "django.core.files.storage.FileSystemStorage",
42+
},
43+
"staticfiles": {
44+
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
45+
},
46+
}
3947
MEDIA_ROOT = str(TEST_ROOT / "uploads")
4048
MEDIA_URL = "/static/uploads/"
4149

@@ -49,7 +57,6 @@
4957
"JWT_AUDIENCE": SOCIAL_AUTH_EDX_OAUTH2_KEY,
5058
}
5159
)
52-
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.StaticFilesStorage"
5360

5461
# Verifiable Credentials
5562
ENABLE_VERIFIABLE_CREDENTIALS = True

credentials/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878

7979
if is_badges_enabled():
8080
urlpatterns += [
81-
re_path(r"^badges/", include(("credentials.apps.badges.urls", "badges"), namespace="badges")),
81+
path("badges/", include(("credentials.apps.badges.urls", "badges"), namespace="badges")),
8282
]
8383

8484
# edx-drf-extensions csrf app

requirements/base.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ openedx-events
4646
pillow
4747
pygments
4848
python-memcached
49+
python-slugify
4950
pymemcache
50-
pytz
5151
qrcode
5252
requests
5353
segment-analytics-python

0 commit comments

Comments
 (0)