Skip to content

Django: upgrade to 4.2 #10595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Aug 8, 2023
2 changes: 1 addition & 1 deletion common
Submodule common updated 1 files
+7 −6 pre-commit-config.yaml
3 changes: 1 addition & 2 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ filterwarnings =
ignore:DateTimeField .* received a naive datetime .* while time zone support is active:RuntimeWarning
ignore:.*:DeprecationWarning

ignore:.*:django.utils.deprecation.RemovedInDjango40Warning
ignore:.*:django.utils.deprecation.RemovedInDjango41Warning
ignore:.*:django.utils.deprecation.RemovedInDjango50Warning
ignore:.*:elasticsearch.exceptions.ElasticsearchWarning
ignore:.*:PendingDeprecationWarning
4 changes: 1 addition & 3 deletions readthedocs/analytics/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
from .models import PageView


@admin.register(PageView)
class PageViewAdmin(admin.ModelAdmin):
raw_id_fields = ('project', 'version')
list_display = ('project', 'version', 'path', 'view_count', 'date')
search_fields = ('project__slug', 'version__slug', 'path')
readonly_fields = ('date',)
list_select_related = ('project', 'version', 'version__project')


admin.site.register(PageView, PageViewAdmin)
12 changes: 6 additions & 6 deletions readthedocs/analytics/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ def test_invalid_uri(self):
+ f"?project={self.project.slug}&version={self.version.slug}"
f"&absolute_uri=https://docs.example.com"
)
self.client.get(url, HTTP_HOST=self.host)
self.client.get(url, headers={"host": self.host})
assert PageView.objects.all().count() == 0

def test_cache_headers(self):
resp = self.client.get(self.url, HTTP_HOST=self.host)
resp = self.client.get(self.url, headers={"host": self.host})
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp["CDN-Cache-Control"], "private")

Expand All @@ -142,7 +142,7 @@ def test_increase_page_view_count(self):
with mock.patch('readthedocs.analytics.tasks.timezone.now') as mocked_timezone:
mocked_timezone.return_value = self.yesterday

self.client.get(self.url, HTTP_HOST=self.host)
self.client.get(self.url, headers={"host": self.host})

assert (
PageView.objects.all().count() == 1
Expand All @@ -151,7 +151,7 @@ def test_increase_page_view_count(self):
PageView.objects.all().first().view_count == 1
), '\'index\' has 1 view'

self.client.get(self.url, HTTP_HOST=self.host)
self.client.get(self.url, headers={"host": self.host})

assert (
PageView.objects.all().count() == 1
Expand All @@ -165,7 +165,7 @@ def test_increase_page_view_count(self):
with mock.patch('readthedocs.analytics.tasks.timezone.now') as mocked_timezone:
mocked_timezone.return_value = self.today

self.client.get(self.url, HTTP_HOST=self.host)
self.client.get(self.url, headers={"host": self.host})

assert (
PageView.objects.all().count() == 2
Expand All @@ -179,7 +179,7 @@ def test_increase_page_view_count(self):
with mock.patch('readthedocs.analytics.tasks.timezone.now') as mocked_timezone:
mocked_timezone.return_value = self.tomorrow

self.client.get(self.url, HTTP_HOST=self.host)
self.client.get(self.url, headers={"host": self.host})

assert (
PageView.objects.all().count() == 3
Expand Down
8 changes: 4 additions & 4 deletions readthedocs/api/v2/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
)

urlpatterns = [
re_path(r'^', include(router.urls)),
path("", include(router.urls)),
]

urlpatterns += [
Expand All @@ -59,8 +59,8 @@
]

task_urls = [
re_path(
r"jobs/status/(?P<task_id>[^/]+)/$",
path(
"jobs/status/<str:task_id>/",
task_views.job_status,
name='api_job_status',
),
Expand Down Expand Up @@ -122,5 +122,5 @@
from readthedocsext.donate.restapi.urls import urlpatterns as sustainability_urls

urlpatterns += [
re_path(r'^sustainability/', include(sustainability_urls)),
path("sustainability/", include(sustainability_urls)),
]
19 changes: 7 additions & 12 deletions readthedocs/builds/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class BuildCommandResultInline(admin.TabularInline):
fields = ("command", "exit_code", "output")


@admin.register(Build)
class BuildAdmin(admin.ModelAdmin):
fields = (
"project",
Expand Down Expand Up @@ -65,12 +66,13 @@ def project_slug(self, obj):
def version_slug(self, obj):
return obj.version.slug

@admin.display(description="Config File")
def pretty_config(self, instance):
return pretty_json_field(instance, "config")

pretty_config.short_description = "Config File"


@admin.register(Version)
class VersionAdmin(admin.ModelAdmin):

list_display = (
Expand All @@ -92,11 +94,11 @@ class VersionAdmin(admin.ModelAdmin):
def project_slug(self, obj):
return obj.project.slug

@admin.display(description="Config File")
def pretty_config(self, instance):
return pretty_json_field(instance, "config")

pretty_config.short_description = "Config File"

@admin.action(description="Build version")
def build_version(self, request, queryset):
"""Trigger a build for the project version."""
total = 0
Expand All @@ -112,8 +114,7 @@ def build_version(self, request, queryset):
"Triggered builds for {} version(s).".format(total),
)

build_version.short_description = "Build version"

@admin.action(description="Reindex version to ES")
def reindex_version(self, request, queryset):
"""Reindexes all selected versions to ES."""
html_objs_qs = []
Expand All @@ -130,8 +131,7 @@ def reindex_version(self, request, queryset):

self.message_user(request, "Task initiated successfully.", messages.SUCCESS)

reindex_version.short_description = "Reindex version to ES"

@admin.action(description="Wipe version from ES")
def wipe_version_indexes(self, request, queryset):
"""Wipe selected versions from ES."""
html_objs_qs = []
Expand All @@ -152,7 +152,6 @@ def wipe_version_indexes(self, request, queryset):
messages.SUCCESS,
)

wipe_version_indexes.short_description = "Wipe version from ES"


@admin.register(RegexAutomationRule)
Expand All @@ -176,7 +175,3 @@ class VersionAutomationRuleAdmin(PolymorphicParentModelAdmin, admin.ModelAdmin):
child_models = (RegexAutomationRule,)
search_fields = ("project__slug",)
list_filter = ("action", "version_type")


admin.site.register(Build, BuildAdmin)
admin.site.register(Version, VersionAdmin)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.4 on 2023-08-02 10:59

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("builds", "0051_add_addons_field"),
]

operations = [
migrations.AlterField(
model_name="versionautomationrule",
name="polymorphic_ctype",
field=models.ForeignKey(
editable=False,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="polymorphic_%(app_label)s.%(class)s_set+",
to="contenttypes.contenttype",
),
),
]
2 changes: 1 addition & 1 deletion readthedocs/builds/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""URL configuration for builds app."""

from django.conf.urls import re_path
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of this PR seems to remove re_path, but this just changes the import?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. re_path was moved around and it's now under a different import path.

The usage of re_path here cannot be changed by path directly because we have non-simple/standard regex that django-upgrade can detect and adapt to just path. That's my bet, tho.

from django.urls import re_path
from django.views.generic.base import RedirectView


Expand Down
14 changes: 7 additions & 7 deletions readthedocs/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,14 @@ class UserAdminExtra(ExtraSimpleHistoryAdmin, UserAdmin):
actions = ["ban_user", "sync_remote_repositories_action"]
inlines = [UserProjectInline]

@admin.display(
description="Banned",
boolean=True,
)
def is_banned(self, obj):
return hasattr(obj, 'profile') and obj.profile.banned

is_banned.short_description = 'Banned'
is_banned.boolean = True

@admin.action(description="Ban user")
def ban_user(self, request, queryset):
users = []
for profile in UserProfile.objects.filter(user__in=queryset):
Expand All @@ -96,8 +98,7 @@ def ban_user(self, request, queryset):
users.append(profile.user.username)
self.message_user(request, 'Banned users: %s' % ', '.join(users))

ban_user.short_description = 'Ban user'

@admin.action(description="Sync remote repositories")
def sync_remote_repositories_action(self, request, queryset):
formatted_task_urls = []

Expand All @@ -118,9 +119,9 @@ def sync_remote_repositories_action(self, request, queryset):
),
)

sync_remote_repositories_action.short_description = "Sync remote repositories"


@admin.register(UserProfile)
class UserProfileAdmin(ExtraSimpleHistoryAdmin):
list_display = ('user', 'homepage')
search_fields = ('user__username', 'homepage')
Expand Down Expand Up @@ -153,6 +154,5 @@ def organizations(self, obj):

admin.site.unregister(User)
admin.site.register(User, UserAdminExtra)
admin.site.register(UserProfile, UserProfileAdmin)
admin.site.unregister(Message)
admin.site.register(Message, MessageAdminExtra)
2 changes: 1 addition & 1 deletion readthedocs/core/tests/test_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_extra_historical_fields_with_request(self):
'repo_type': self.project.repo_type,
'language': self.project.language,
},
HTTP_USER_AGENT='Firefox',
headers={"user-agent": "Firefox"},
)
self.assertEqual(r.status_code, 302)
self.assertEqual(self.project.history.count(), 2)
Expand Down
4 changes: 1 addition & 3 deletions readthedocs/gold/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
from .models import GoldUser


@admin.register(GoldUser)
class GoldAdmin(admin.ModelAdmin):
model = GoldUser
raw_id_fields = ('user', 'projects')
list_display = ('user', 'level', 'modified_date', 'subscribed')
list_filter = ('level',)
search_fields = ('projects__slug', 'user__email', 'user__username', 'stripe_id')


admin.site.register(GoldUser, GoldAdmin)
16 changes: 8 additions & 8 deletions readthedocs/gold/urls.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@

"""Gold subscription URLs."""

from django.conf.urls import re_path
from django.urls import path, re_path

from readthedocs.gold import views
from readthedocs.projects.constants import PROJECT_SLUG_REGEX

urlpatterns = [
re_path(
r'^$',
path(
"",
views.GoldSubscription.as_view(),
name='gold_detail',
),
re_path(
r'^subscription/checkout/create/$',
path(
"subscription/checkout/create/",
views.GoldCreateCheckoutSession.as_view(),
name='gold_checkout_create',
),
re_path(
r'^subscription/portal/$',
path(
"subscription/portal/",
views.GoldSubscriptionPortal.as_view(),
name='gold_subscription_portal',
),
re_path(r'^projects/$', views.GoldProjectsListCreate.as_view(), name='gold_projects'),
path("projects/", views.GoldProjectsListCreate.as_view(), name="gold_projects"),
re_path(
(
r'^projects/remove/(?P<project_slug>{project_slug})/$'.format(
Expand Down
19 changes: 9 additions & 10 deletions readthedocs/integrations/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def inner(_, obj):
return inner


@admin.register(HttpExchange)
class HttpExchangeAdmin(admin.ModelAdmin):

"""
Expand Down Expand Up @@ -73,13 +74,16 @@ class HttpExchangeAdmin(admin.ModelAdmin):
'Response body',
)

@admin.display(
description="Passed",
boolean=True,
)
def failed_icon(self, obj):
return not obj.failed

failed_icon.boolean = True
failed_icon.short_description = 'Passed'


@admin.register(Integration)
class IntegrationAdmin(admin.ModelAdmin):

"""
Expand All @@ -94,6 +98,7 @@ class IntegrationAdmin(admin.ModelAdmin):
readonly_fields = ['exchanges']

# TODO: review this now that we are using official Django's JSONField
@admin.display(description="HTTP exchanges")
def exchanges(self, obj):
"""
Manually make an inline-ish block.
Expand All @@ -103,8 +108,8 @@ def exchanges(self, obj):
"""
url = urls.reverse(
'admin:{}_{}_changelist'.format(
HttpExchange._meta.app_label, # pylint: disable=protected-access
HttpExchange._meta.model_name, # pylint: disable=protected-access
HttpExchange._meta.app_label,
HttpExchange._meta.model_name,
),
)
return mark_safe(
Expand All @@ -115,9 +120,3 @@ def exchanges(self, obj):
obj.exchanges.count(),
),
)

exchanges.short_description = 'HTTP exchanges'


admin.site.register(HttpExchange, HttpExchangeAdmin)
admin.site.register(Integration, IntegrationAdmin)
9 changes: 4 additions & 5 deletions readthedocs/invitations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ class RevokeInvitation(PrivateViewMixin, UserPassesTestMixin, DeleteView):
pk_url_kwarg = "invitation_pk"
http_method_names = ["post"]

def delete(self, request, *args, **kwargs):
def form_valid(self, form):
invitation = self.get_object()
invitation.create_audit_log(
action=AuditLog.INVITATION_REVOKED,
request=request,
user=request.user,
request=self.request,
user=self.request.user,
)
return super().delete(request, *args, **kwargs)
return super().form_valid(form)

def test_func(self):
invitation = self.get_object()
Expand Down Expand Up @@ -70,7 +70,6 @@ def get_context_data(self, **kwargs):
context["target_type"] = invitation.object._meta.verbose_name
return context

# pylint: disable=unused-argument
def post(self, request, *args, **kwargs):
"""
Accept or decline an invitation.
Expand Down
Loading