From b0dfadf500804a282b7f42203fbfcbb3886a8676 Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Thu, 7 Mar 2024 17:40:14 +0530 Subject: [PATCH 01/18] Django 42 upgrade changes --- cms/admin/pageadmin.py | 4 ++-- cms/admin/placeholderadmin.py | 2 +- cms/admin/settingsadmin.py | 9 ++++---- cms/admin/static_placeholder.py | 2 +- cms/cms_plugins.py | 4 ++-- cms/templatetags/cms_tags.py | 2 +- .../project/cms_urls_for_apphook_tests.py | 3 ++- .../project/customuserapp/models.py | 4 ++-- cms/test_utils/project/emailuserapp/admin.py | 2 +- cms/test_utils/project/emailuserapp/models.py | 4 ++-- cms/test_utils/project/extensionapp/admin.py | 4 ++-- .../fourth_cms_urls_for_apphook_tests.py | 3 ++- .../project/fourth_urls_for_apphook_tests.py | 3 ++- cms/test_utils/project/noadmin_urls.py | 3 ++- cms/test_utils/project/nonroot_urls.py | 5 +++-- .../placeholder_relation_field_app/admin.py | 2 +- .../project/placeholderapp/admin.py | 6 +++--- cms/test_utils/project/placeholderapp/urls.py | 7 ++++--- cms/test_utils/project/placeholderapp_urls.py | 7 ++++--- .../pluginapp/plugins/caching/cms_plugins.py | 2 +- .../plugins/manytomany_rel/cms_plugins.py | 2 +- cms/test_utils/project/sampleapp/admin.py | 4 ++-- cms/test_utils/project/sampleapp/cms_apps.py | 5 +++-- cms/test_utils/project/sampleapp/ns_urls.py | 3 ++- cms/test_utils/project/sampleapp/urls.py | 21 ++++++++++--------- cms/test_utils/project/sampleapp/urls2.py | 4 ++-- .../project/sampleapp/urls_childapp.py | 4 ++-- .../project/sampleapp/urls_example.py | 4 ++-- .../project/sampleapp/urls_excluded.py | 7 ++++--- .../project/sampleapp/urls_extra.py | 4 ++-- .../project/sampleapp/urls_parentapp.py | 4 ++-- .../project/sampleapp/urls_sample_config.py | 4 ++-- .../second_cms_urls_for_apphook_tests.py | 7 ++++--- .../project/second_urls_for_apphook_tests.py | 3 ++- .../third_cms_urls_for_apphook_tests.py | 3 ++- .../project/third_urls_for_apphook_tests.py | 3 ++- cms/test_utils/project/urls.py | 15 ++++++------- cms/test_utils/project/urls_2.py | 5 +++-- cms/test_utils/project/urls_3.py | 5 +++-- .../project/urls_for_apphook_tests.py | 3 ++- cms/test_utils/project/urls_no18n.py | 5 +++-- cms/tests/test_admin.py | 10 ++++----- cms/tests/test_placeholder.py | 6 +++--- cms/tests/test_plugins.py | 5 +++-- cms/urls.py | 7 ++++--- cms/utils/decorators.py | 4 ++-- cms/utils/request_ip_resolvers.py | 4 ++-- cms/views.py | 9 ++++---- cms/wizards/urls.py | 4 ++-- menus/apps.py | 2 +- menus/menu_pool.py | 2 +- menus/templatetags/menu_tags.py | 6 +++--- setup.py | 2 +- test_requirements/databases.txt | 4 ++-- test_requirements/django-2.2.txt | 3 --- test_requirements/django-3.0.txt | 2 -- test_requirements/django-3.1.txt | 3 --- test_requirements/django-3.2.txt | 2 +- test_requirements/django-4.2.txt | 3 +++ test_requirements/requirements_base.txt | 2 +- 60 files changed, 146 insertions(+), 127 deletions(-) delete mode 100644 test_requirements/django-2.2.txt delete mode 100644 test_requirements/django-3.0.txt delete mode 100644 test_requirements/django-3.1.txt create mode 100644 test_requirements/django-4.2.txt diff --git a/cms/admin/pageadmin.py b/cms/admin/pageadmin.py index 9d51338fb61..06c87620474 100644 --- a/cms/admin/pageadmin.py +++ b/cms/admin/pageadmin.py @@ -88,6 +88,7 @@ def get_site(request): return site +@admin.register(Page) class PageAdmin(admin.ModelAdmin): change_list_template = "admin/cms/page/tree/base.html" actions_menu_template = 'admin/cms/page/tree/actions_dropdown.html' @@ -780,6 +781,7 @@ class Meta: return render(request, 'admin/cms/page/plugin/change_form.html', context) +@admin.register(PageContent) class PageContentAdmin(admin.ModelAdmin): ordering = ('page__node__path',) search_fields = ('=id', 'page__id', 'page__urls__slug', 'title', 'page__reverse_id') @@ -1477,5 +1479,3 @@ def render_page_row(page): yield render_page_row(page) -admin.site.register(Page, PageAdmin) -admin.site.register(PageContent, PageContentAdmin) diff --git a/cms/admin/placeholderadmin.py b/cms/admin/placeholderadmin.py index 4a0e3215530..2ddb182aada 100644 --- a/cms/admin/placeholderadmin.py +++ b/cms/admin/placeholderadmin.py @@ -177,6 +177,7 @@ class PlaceholderAdminMixin(metaclass=PlaceholderAdminMixinBase): pass +@admin.register(Placeholder) class PlaceholderAdmin(admin.ModelAdmin): def has_add_permission(self, request): @@ -1093,4 +1094,3 @@ def clear_placeholder(self, request, placeholder_id): return TemplateResponse(request, "admin/cms/page/plugin/delete_confirmation.html", context) -admin.site.register(Placeholder, PlaceholderAdmin) diff --git a/cms/admin/settingsadmin.py b/cms/admin/settingsadmin.py index 362b2f160db..43dc3b34119 100644 --- a/cms/admin/settingsadmin.py +++ b/cms/admin/settingsadmin.py @@ -10,6 +10,7 @@ from django.db import transaction from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest from django.http.request import QueryDict +from django.urls import path from django.urls import re_path from django.utils.html import conditional_escape from django.utils.translation import override @@ -21,6 +22,7 @@ from cms.utils.urlutils import admin_reverse +@admin.register(UserSettings) class SettingsAdmin(ModelAdmin): def get_urls(self): @@ -33,13 +35,13 @@ def wrapper(*args, **kwargs): info = self.model._meta.app_label, self.model._meta.model_name return [ - re_path(r'^session_store/$', + path('session_store/', self.session_store, name='%s_%s_session_store' % info), - re_path(r'^cms-toolbar/$', + path('cms-toolbar/', wrap(self.get_toolbar), name='%s_%s_get_toolbar' % info), - re_path(r'^$', + path('', wrap(self.change_view), name='%s_%s_change' % info), re_path(r'^(.+)/$', @@ -137,4 +139,3 @@ def get_model_perms(self, request): return {} -admin.site.register(UserSettings, SettingsAdmin) diff --git a/cms/admin/static_placeholder.py b/cms/admin/static_placeholder.py index accf9ddd681..352f5f0d576 100644 --- a/cms/admin/static_placeholder.py +++ b/cms/admin/static_placeholder.py @@ -2,10 +2,10 @@ from django.contrib import admin +@admin.register(StaticPlaceholder) class StaticPlaceholderAdmin(admin.ModelAdmin): list_display = ('get_name', 'code', 'site', 'creation_method') search_fields = ('name', 'code',) exclude = ('creation_method',) list_filter = ('creation_method', 'site') -admin.site.register(StaticPlaceholder, StaticPlaceholderAdmin) diff --git a/cms/cms_plugins.py b/cms/cms_plugins.py index 982e14e4478..294f7100bb5 100644 --- a/cms/cms_plugins.py +++ b/cms/cms_plugins.py @@ -8,7 +8,7 @@ from cms.utils.urlutils import admin_reverse from django.http import HttpResponseForbidden, HttpResponseBadRequest, HttpResponse from django.middleware.csrf import get_token -from django.urls import re_path +from django.urls import path from django.utils.translation import gettext, gettext_lazy as _, get_language @@ -65,7 +65,7 @@ def get_extra_placeholder_menu_items(cls, request, placeholder): def get_plugin_urls(self): return [ - re_path(r'^create_alias/$', self.create_alias, name='cms_create_alias'), + path('create_alias/', self.create_alias, name='cms_create_alias'), ] @classmethod diff --git a/cms/templatetags/cms_tags.py b/cms/templatetags/cms_tags.py index 8c05530b2ec..a3400d7e344 100644 --- a/cms/templatetags/cms_tags.py +++ b/cms/templatetags/cms_tags.py @@ -92,7 +92,7 @@ def _get_page_by_untyped_arg(page_lookup, request, site_id): middle = BrokenLinkEmailsMiddleware() domain = request.get_host() path = request.get_full_path() - referer = force_str(request.META.get('HTTP_REFERER', ''), errors='replace') + referer = force_str(request.headers.get('referer', ''), errors='replace') if not middle.is_ignorable_request(request, path, domain, referer): mail_managers(subject, body, fail_silently=True) return None diff --git a/cms/test_utils/project/cms_urls_for_apphook_tests.py b/cms/test_utils/project/cms_urls_for_apphook_tests.py index d0ad9823454..c6642610180 100644 --- a/cms/test_utils/project/cms_urls_for_apphook_tests.py +++ b/cms/test_utils/project/cms_urls_for_apphook_tests.py @@ -1,6 +1,7 @@ from cms.apphook_pool import apphook_pool from cms.views import details from django.conf import settings +from django.urls import path from django.urls import re_path @@ -11,7 +12,7 @@ urlpatterns = [ # Public pages - re_path(r'^$', details, {'slug':''}, name='pages-root'), + path('', details, {'slug':''}, name='pages-root'), reg, ] diff --git a/cms/test_utils/project/customuserapp/models.py b/cms/test_utils/project/customuserapp/models.py index 525267bc69a..c1ea81bc41f 100644 --- a/cms/test_utils/project/customuserapp/models.py +++ b/cms/test_utils/project/customuserapp/models.py @@ -5,7 +5,7 @@ from django.core.mail import send_mail from django.db import models from django.utils import timezone -from django.utils.http import urlquote +from urllib.parse import quote from django.utils.translation import gettext_lazy as _ @@ -60,7 +60,7 @@ class Meta: verbose_name_plural = _('users') def get_absolute_url(self): - return "/users/%s/" % urlquote(self.username) + return "/users/%s/" % quote(self.username) def get_full_name(self): """ diff --git a/cms/test_utils/project/emailuserapp/admin.py b/cms/test_utils/project/emailuserapp/admin.py index fa91b3a1163..ab0d34e4bb5 100644 --- a/cms/test_utils/project/emailuserapp/admin.py +++ b/cms/test_utils/project/emailuserapp/admin.py @@ -5,6 +5,7 @@ from .forms import UserChangeForm, UserCreationForm +@admin.register(EmailUser) class UserAdmin(OriginalUserAdmin): # The form to add and change user instances form = UserChangeForm @@ -36,4 +37,3 @@ class UserAdmin(OriginalUserAdmin): # Now register the emailuser admin -admin.site.register(EmailUser, UserAdmin) diff --git a/cms/test_utils/project/emailuserapp/models.py b/cms/test_utils/project/emailuserapp/models.py index cee99e0472f..f35297685ce 100644 --- a/cms/test_utils/project/emailuserapp/models.py +++ b/cms/test_utils/project/emailuserapp/models.py @@ -2,7 +2,7 @@ PermissionsMixin) from django.core.mail import send_mail from django.db import models -from django.utils.http import urlquote +from urllib.parse import quote from django.utils import timezone @@ -91,7 +91,7 @@ class Meta: abstract = True def get_absolute_url(self): - return "/users/%s/" % urlquote(self.pk) + return "/users/%s/" % quote(self.pk) def get_full_name(self): """ diff --git a/cms/test_utils/project/extensionapp/admin.py b/cms/test_utils/project/extensionapp/admin.py index 1ee3b5e2b70..007996964d0 100644 --- a/cms/test_utils/project/extensionapp/admin.py +++ b/cms/test_utils/project/extensionapp/admin.py @@ -3,15 +3,15 @@ from django.contrib import admin +@admin.register(MyPageExtension) class MyPageExtensionAdmin(PageExtensionAdmin): pass -admin.site.register(MyPageExtension, MyPageExtensionAdmin) +@admin.register(MyTitleExtension) class MyTitleExtensionAdmin(TitleExtensionAdmin): pass -admin.site.register(MyTitleExtension, MyTitleExtensionAdmin) diff --git a/cms/test_utils/project/fourth_cms_urls_for_apphook_tests.py b/cms/test_utils/project/fourth_cms_urls_for_apphook_tests.py index d0ad9823454..c6642610180 100644 --- a/cms/test_utils/project/fourth_cms_urls_for_apphook_tests.py +++ b/cms/test_utils/project/fourth_cms_urls_for_apphook_tests.py @@ -1,6 +1,7 @@ from cms.apphook_pool import apphook_pool from cms.views import details from django.conf import settings +from django.urls import path from django.urls import re_path @@ -11,7 +12,7 @@ urlpatterns = [ # Public pages - re_path(r'^$', details, {'slug':''}, name='pages-root'), + path('', details, {'slug':''}, name='pages-root'), reg, ] diff --git a/cms/test_utils/project/fourth_urls_for_apphook_tests.py b/cms/test_utils/project/fourth_urls_for_apphook_tests.py index 9418d004b23..c9c82bb7857 100644 --- a/cms/test_utils/project/fourth_urls_for_apphook_tests.py +++ b/cms/test_utils/project/fourth_urls_for_apphook_tests.py @@ -5,6 +5,7 @@ from django.conf import settings from django.conf.urls.i18n import i18n_patterns from django.contrib import admin +from django.urls import path from django.urls import include, re_path @@ -20,5 +21,5 @@ ] urlpatterns += i18n_patterns( - re_path(r'^', include('cms.test_utils.project.fourth_cms_urls_for_apphook_tests')), + path('', include('cms.test_utils.project.fourth_cms_urls_for_apphook_tests')), ) diff --git a/cms/test_utils/project/noadmin_urls.py b/cms/test_utils/project/noadmin_urls.py index 08cbd2d378f..9554b565130 100644 --- a/cms/test_utils/project/noadmin_urls.py +++ b/cms/test_utils/project/noadmin_urls.py @@ -3,6 +3,7 @@ from cms.utils.conf import get_cms_setting from django.conf import settings +from django.urls import path from django.urls import include, re_path @@ -12,5 +13,5 @@ re_path(r'^media/cms/(?P.*)$', serve, {'document_root': get_cms_setting('MEDIA_ROOT'), 'show_indexes': True}), re_path(r'^jsi18n/(?P\S+?)/$', JavaScriptCatalog.as_view()), - re_path(r'^', include('cms.urls')), + path('', include('cms.urls')), ] diff --git a/cms/test_utils/project/nonroot_urls.py b/cms/test_utils/project/nonroot_urls.py index 65c4dd3e8e8..bfb5cb79003 100644 --- a/cms/test_utils/project/nonroot_urls.py +++ b/cms/test_utils/project/nonroot_urls.py @@ -1,6 +1,7 @@ from django.conf import settings from django.conf.urls.i18n import i18n_patterns from django.contrib import admin +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -21,6 +22,6 @@ urlpatterns += i18n_patterns( re_path(r'^admin/', admin.site.urls), - re_path(r'^content/', include('cms.urls')), - re_path(r'^example/$', example_view, name='example_view'), + path('content/', include('cms.urls')), + path('example/', example_view, name='example_view'), ) diff --git a/cms/test_utils/project/placeholder_relation_field_app/admin.py b/cms/test_utils/project/placeholder_relation_field_app/admin.py index c5cd3d164cb..20eeb00fad6 100644 --- a/cms/test_utils/project/placeholder_relation_field_app/admin.py +++ b/cms/test_utils/project/placeholder_relation_field_app/admin.py @@ -5,8 +5,8 @@ from .models import FancyPoll +@admin.register(FancyPoll) class FancyPollAdmin(FrontendEditableAdminMixin, admin.ModelAdmin): pass -admin.site.register(FancyPoll, FancyPollAdmin) diff --git a/cms/test_utils/project/placeholderapp/admin.py b/cms/test_utils/project/placeholderapp/admin.py index 87699c9eaa1..bfe1a4ad3b9 100644 --- a/cms/test_utils/project/placeholderapp/admin.py +++ b/cms/test_utils/project/placeholderapp/admin.py @@ -6,18 +6,18 @@ from django.contrib import admin +@admin.register(Example1) class ExampleAdmin(FrontendEditableAdminMixin, admin.ModelAdmin): frontend_editable_fields = ("char_1", "char_2") +@admin.register(CharPksExample) class CharPksAdmin(FrontendEditableAdminMixin, admin.ModelAdmin): frontend_editable_fields = ("char_1",) +@admin.register(TwoPlaceholderExample) class TwoPlaceholderExampleAdmin(admin.ModelAdmin): pass -admin.site.register(Example1, ExampleAdmin) -admin.site.register(CharPksExample, CharPksAdmin) -admin.site.register(TwoPlaceholderExample, TwoPlaceholderExampleAdmin) diff --git a/cms/test_utils/project/placeholderapp/urls.py b/cms/test_utils/project/placeholderapp/urls.py index 0d6943d010c..a3c52ef0d21 100644 --- a/cms/test_utils/project/placeholderapp/urls.py +++ b/cms/test_utils/project/placeholderapp/urls.py @@ -1,3 +1,4 @@ +from django.urls import path from django.urls import re_path from . import views @@ -5,8 +6,8 @@ urlpatterns = [ - re_path(r'^detail/(?P[0-9]+)/$', views.detail_view, name="example_detail"), + path('detail//', views.detail_view, name="example_detail"), re_path(r'^detail_char/(?P[a-z]+)/$', views.detail_view_char, name="example_detail_char"), - re_path(r'^detail/class/(?P[0-9]+)/$', ClassDetail.as_view(), name="example_class_detail"), - re_path(r'^$', views.list_view, name="example_list"), + path('detail/class//', ClassDetail.as_view(), name="example_class_detail"), + path('', views.list_view, name="example_list"), ] diff --git a/cms/test_utils/project/placeholderapp_urls.py b/cms/test_utils/project/placeholderapp_urls.py index 0950609efe8..64b26b8d816 100644 --- a/cms/test_utils/project/placeholderapp_urls.py +++ b/cms/test_utils/project/placeholderapp_urls.py @@ -1,6 +1,7 @@ from django.conf import settings from django.conf.urls.i18n import i18n_patterns from django.contrib import admin +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -21,7 +22,7 @@ ] urlpatterns += i18n_patterns( - re_path(r'^detail/(?P[0-9]+)/$', detail_view, name="detail"), - re_path(r'^detail/(?P[0-9]+)/$', detail_view, name="example_detail"), - re_path(r'^', include('cms.urls')), + path('detail//', detail_view, name="detail"), + path('detail//', detail_view, name="example_detail"), + path('', include('cms.urls')), ) diff --git a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py index 1c1695fbc94..6b5af6de73f 100644 --- a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py +++ b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py @@ -92,7 +92,7 @@ def get_vary_cache_on(self, request, instance, placeholder): def render(self, context, instance, placeholder): request = context.get('request') - country_code = request.META.get('HTTP_COUNTRY_CODE') or "any" + country_code = request.headers.get('country-code') or "any" context['now'] = country_code return context diff --git a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py index bfa3f125ccd..308ee774238 100644 --- a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py +++ b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py @@ -26,6 +26,7 @@ def render(self, context, instance, placeholder): return context +@admin.register(ArticlePluginModel) class ArticlePluginAdmin(admin.ModelAdmin): filter_horizontal = ['sections'] @@ -67,4 +68,3 @@ class PluginWithM2MToModel(CMSPluginBase): plugin_pool.register_plugin(PluginWithFKFromModel) # Used to test integrity of plugin form -admin.site.register(ArticlePluginModel, ArticlePluginAdmin) diff --git a/cms/test_utils/project/sampleapp/admin.py b/cms/test_utils/project/sampleapp/admin.py index 73390917e75..2bc230a7c4f 100644 --- a/cms/test_utils/project/sampleapp/admin.py +++ b/cms/test_utils/project/sampleapp/admin.py @@ -13,13 +13,13 @@ class PictureInline(admin.StackedInline): model = Picture +@admin.register(Category) class CategoryAdmin(admin.ModelAdmin): inlines = [PictureInline] +@admin.register(SomeEditableModel) class SomeEditableAdmin(FrontendEditableAdminMixin, admin.ModelAdmin): pass -admin.site.register(Category, CategoryAdmin) admin.site.register(SampleAppConfig) -admin.site.register(SomeEditableModel, SomeEditableAdmin) diff --git a/cms/test_utils/project/sampleapp/cms_apps.py b/cms/test_utils/project/sampleapp/cms_apps.py index 0f203bdbc47..f2862d943b4 100644 --- a/cms/test_utils/project/sampleapp/cms_apps.py +++ b/cms/test_utils/project/sampleapp/cms_apps.py @@ -1,6 +1,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.http import HttpResponse -from django.urls import re_path, reverse +from django.urls import path +from django.urls import reverse from django.utils.translation import gettext_lazy as _ from cms.app_base import CMSApp @@ -76,7 +77,7 @@ def my_view(request): return HttpResponse("Sample App 3 Response") return [ - re_path(r'^$', my_view, name='sample3-root'), + path('', my_view, name='sample3-root'), ] diff --git a/cms/test_utils/project/sampleapp/ns_urls.py b/cms/test_utils/project/sampleapp/ns_urls.py index 40fb4a104be..c8862175b31 100644 --- a/cms/test_utils/project/sampleapp/ns_urls.py +++ b/cms/test_utils/project/sampleapp/ns_urls.py @@ -1,3 +1,4 @@ +from django.urls import path from django.urls import re_path from django.utils.translation import gettext_lazy as _ @@ -5,6 +6,6 @@ urlpatterns = [ - re_path(r'^current-app/$', views.current_app, name='current-app'), + path('current-app/', views.current_app, name='current-app'), re_path(_('page'), views.current_app, name='translated-url'), ] diff --git a/cms/test_utils/project/sampleapp/urls.py b/cms/test_utils/project/sampleapp/urls.py index 01672342d6f..e215cb43f3f 100644 --- a/cms/test_utils/project/sampleapp/urls.py +++ b/cms/test_utils/project/sampleapp/urls.py @@ -1,3 +1,4 @@ +from django.urls import path from django.urls import include, re_path from django.utils.translation import gettext_lazy as _ @@ -7,16 +8,16 @@ Also used in cms.tests.ApphooksTestCase """ urlpatterns = [ - re_path(r'^$', views.sample_view, {'message': 'sample root page',}, name='sample-root'), - re_path(r'^exempt/$', views.exempt_view, {'message': 'sample root page',}, name='sample-exempt'), - re_path(r'^settings/$', views.sample_view, kwargs={'message': 'sample settings page'}, name='sample-settings'), + path('', views.sample_view, {'message': 'sample root page',}, name='sample-root'), + path('exempt/', views.exempt_view, {'message': 'sample root page',}, name='sample-exempt'), + path('settings/', views.sample_view, kwargs={'message': 'sample settings page'}, name='sample-settings'), re_path(r'^myparams/(?P[\w_-]+)/$', views.sample_view, name='sample-params'), re_path(_(r'^account/$'), views.sample_view, {'message': 'sample account page'}, name='sample-account'), - re_path(r'^account/my_profile/$',views.sample_view, {'message': 'sample my profile page'}, name='sample-profile'), - re_path(r'^category/(?P[0-9]+)/$', views.category_view, name='category_view'), - re_path(r'^notfound/$', views.notfound, name='notfound'), - re_path(r'^extra_1/$', views.extra_view, {'message': 'test urlconf'}, name='extra_first'), - re_path(r'^class-view/$', views.ClassView(), name='sample-class-view'), - re_path(r'^class-based-view/$', views.ClassBasedView.as_view(), name='sample-class-based-view'), - re_path(r'^', include('cms.test_utils.project.sampleapp.urls_extra'), {'opts': 'someopts'}), + path('account/my_profile/',views.sample_view, {'message': 'sample my profile page'}, name='sample-profile'), + path('category//', views.category_view, name='category_view'), + path('notfound/', views.notfound, name='notfound'), + path('extra_1/', views.extra_view, {'message': 'test urlconf'}, name='extra_first'), + path('class-view/', views.ClassView(), name='sample-class-view'), + path('class-based-view/', views.ClassBasedView.as_view(), name='sample-class-based-view'), + path('', include('cms.test_utils.project.sampleapp.urls_extra'), {'opts': 'someopts'}), ] diff --git a/cms/test_utils/project/sampleapp/urls2.py b/cms/test_utils/project/sampleapp/urls2.py index cc6849b52d2..a6ad909aa81 100644 --- a/cms/test_utils/project/sampleapp/urls2.py +++ b/cms/test_utils/project/sampleapp/urls2.py @@ -1,7 +1,7 @@ -from django.urls import re_path +from django.urls import path from . import views urlpatterns = [ - re_path(r'^$', views.sample_view, {'message': 'sample apphook2 root page', }, name='sample2-root'), + path('', views.sample_view, {'message': 'sample apphook2 root page', }, name='sample2-root'), ] diff --git a/cms/test_utils/project/sampleapp/urls_childapp.py b/cms/test_utils/project/sampleapp/urls_childapp.py index 3a7708a92e0..083d7599f9a 100644 --- a/cms/test_utils/project/sampleapp/urls_childapp.py +++ b/cms/test_utils/project/sampleapp/urls_childapp.py @@ -1,7 +1,7 @@ -from django.urls import re_path +from django.urls import path from cms.test_utils.project.sampleapp import views urlpatterns = [ - re_path(r'^(?P.+)$', views.childapp_view, name='childapp_view'), + path('', views.childapp_view, name='childapp_view'), ] diff --git a/cms/test_utils/project/sampleapp/urls_example.py b/cms/test_utils/project/sampleapp/urls_example.py index f3e1568da3e..cbf9c8d29fd 100644 --- a/cms/test_utils/project/sampleapp/urls_example.py +++ b/cms/test_utils/project/sampleapp/urls_example.py @@ -1,9 +1,9 @@ -from django.urls import re_path +from django.urls import path from ..placeholderapp import views app_name = 'example_app' urlpatterns = [ - re_path(r'^example/$', views.example_view, name="example"), + path('example/', views.example_view, name="example"), ] diff --git a/cms/test_utils/project/sampleapp/urls_excluded.py b/cms/test_utils/project/sampleapp/urls_excluded.py index c69daea866d..b1daa351594 100644 --- a/cms/test_utils/project/sampleapp/urls_excluded.py +++ b/cms/test_utils/project/sampleapp/urls_excluded.py @@ -1,8 +1,9 @@ -from django.urls import include, re_path +from django.urls import path +from django.urls import include urlpatterns = [ - re_path(r'^excluded/', + path('excluded/', include('cms.test_utils.project.sampleapp.urls_example', namespace="excluded")), - re_path(r'^not_excluded/', + path('not_excluded/', include('cms.test_utils.project.sampleapp.urls_example', namespace="not_excluded")), ] diff --git a/cms/test_utils/project/sampleapp/urls_extra.py b/cms/test_utils/project/sampleapp/urls_extra.py index bae71666ba1..e711c41dc51 100644 --- a/cms/test_utils/project/sampleapp/urls_extra.py +++ b/cms/test_utils/project/sampleapp/urls_extra.py @@ -1,7 +1,7 @@ -from django.urls import re_path +from django.urls import path from . import views urlpatterns = [ - re_path(r'extra_2/$', views.extra_view, {'message': 'test included urlconf'}, name='extra_second'), + path('extra_2/', views.extra_view, {'message': 'test included urlconf'}, name='extra_second'), ] diff --git a/cms/test_utils/project/sampleapp/urls_parentapp.py b/cms/test_utils/project/sampleapp/urls_parentapp.py index ae99b7e197e..40692c79670 100644 --- a/cms/test_utils/project/sampleapp/urls_parentapp.py +++ b/cms/test_utils/project/sampleapp/urls_parentapp.py @@ -1,7 +1,7 @@ -from django.urls import re_path +from django.urls import path from cms.test_utils.project.sampleapp import views urlpatterns = [ - re_path(r'^(?P.+)$', views.parentapp_view, name='parentapp_view'), + path('', views.parentapp_view, name='parentapp_view'), ] diff --git a/cms/test_utils/project/sampleapp/urls_sample_config.py b/cms/test_utils/project/sampleapp/urls_sample_config.py index e25e0c33ed6..5db46c5bcf5 100644 --- a/cms/test_utils/project/sampleapp/urls_sample_config.py +++ b/cms/test_utils/project/sampleapp/urls_sample_config.py @@ -1,8 +1,8 @@ -from django.urls import re_path +from django.urls import path from . import views urlpatterns = [ - re_path(r'^$', views.sample_view, {'message': 'sample root page',}, name='sample-config-root'), + path('', views.sample_view, {'message': 'sample root page',}, name='sample-config-root'), ] diff --git a/cms/test_utils/project/second_cms_urls_for_apphook_tests.py b/cms/test_utils/project/second_cms_urls_for_apphook_tests.py index 41588192676..ac2f35f32b7 100644 --- a/cms/test_utils/project/second_cms_urls_for_apphook_tests.py +++ b/cms/test_utils/project/second_cms_urls_for_apphook_tests.py @@ -1,4 +1,5 @@ from django.conf import settings +from django.urls import path from django.urls import include, re_path from cms.apphook_pool import apphook_pool @@ -12,11 +13,11 @@ urlpatterns = [ # Public pages - re_path(r'^example/', + path('example/', include('cms.test_utils.project.sampleapp.urls_example', namespace="example1")), - re_path(r'^example2/', + path('example2/', include('cms.test_utils.project.sampleapp.urls_example', namespace="example2")), - re_path(r'^$', details, {'slug': ''}, name='pages-root'), + path('', details, {'slug': ''}, name='pages-root'), reg, ] diff --git a/cms/test_utils/project/second_urls_for_apphook_tests.py b/cms/test_utils/project/second_urls_for_apphook_tests.py index a829d9d68f2..f4dbbf16617 100644 --- a/cms/test_utils/project/second_urls_for_apphook_tests.py +++ b/cms/test_utils/project/second_urls_for_apphook_tests.py @@ -1,6 +1,7 @@ from django.conf import settings from django.conf.urls.i18n import i18n_patterns from django.contrib import admin +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -21,5 +22,5 @@ urlpatterns += i18n_patterns( - re_path(r'^', include('cms.test_utils.project.second_cms_urls_for_apphook_tests')), + path('', include('cms.test_utils.project.second_cms_urls_for_apphook_tests')), ) diff --git a/cms/test_utils/project/third_cms_urls_for_apphook_tests.py b/cms/test_utils/project/third_cms_urls_for_apphook_tests.py index 95cf8b2fdb5..f7917d5cb91 100644 --- a/cms/test_utils/project/third_cms_urls_for_apphook_tests.py +++ b/cms/test_utils/project/third_cms_urls_for_apphook_tests.py @@ -1,6 +1,7 @@ from cms.apphook_pool import apphook_pool from cms.views import details from django.conf import settings +from django.urls import path from django.urls import re_path if settings.APPEND_SLASH: @@ -10,7 +11,7 @@ urlpatterns = [ # Public pages - re_path(r'^$', details, {'slug':''}, name='pages-root'), + path('', details, {'slug':''}, name='pages-root'), reg, ] diff --git a/cms/test_utils/project/third_urls_for_apphook_tests.py b/cms/test_utils/project/third_urls_for_apphook_tests.py index dd87f7a0602..4b7c0393ee8 100644 --- a/cms/test_utils/project/third_urls_for_apphook_tests.py +++ b/cms/test_utils/project/third_urls_for_apphook_tests.py @@ -1,6 +1,7 @@ from django.conf import settings from django.conf.urls.i18n import i18n_patterns from django.contrib import admin +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -20,5 +21,5 @@ ] urlpatterns += i18n_patterns( - re_path(r'^', include('cms.test_utils.project.third_cms_urls_for_apphook_tests')), + path('', include('cms.test_utils.project.third_cms_urls_for_apphook_tests')), ) diff --git a/cms/test_utils/project/urls.py b/cms/test_utils/project/urls.py index c8bfaae56b9..1811c999b9a 100644 --- a/cms/test_utils/project/urls.py +++ b/cms/test_utils/project/urls.py @@ -3,6 +3,7 @@ from django.conf.urls.i18n import i18n_patterns from django.contrib.auth.views import LoginView from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import path from django.urls import include, re_path from django.views.static import serve from django.views.i18n import JavaScriptCatalog @@ -27,17 +28,17 @@ urlpatterns += i18n_patterns( - re_path(r'^sample/login_other/$', LoginView.as_view(), + path('sample/login_other/', LoginView.as_view(), kwargs={'authentication_form': LoginForm2}), - re_path(r'^sample/login/$', LoginView.as_view(), + path('sample/login/', LoginView.as_view(), kwargs={'authentication_form': LoginForm}), - re_path(r'^sample/login3/$', LoginView.as_view(), + path('sample/login3/', LoginView.as_view(), kwargs={'authentication_form': LoginForm3}), re_path(r'^admin/', admin.site.urls), - re_path(r'^example/$', example_view), - re_path(r'^example/latest/$', latest_view), - re_path(r'^plain_view/$', plain_view), + path('example/', example_view), + path('example/latest/', latest_view), + path('plain_view/', plain_view), re_path(r'^fancypolls/detail/([0-9]+)/$', fancy_poll_detail_view, name='fancy_poll_detail_view'), - re_path(r'^', include('cms.urls')), + path('', include('cms.urls')), ) diff --git a/cms/test_utils/project/urls_2.py b/cms/test_utils/project/urls_2.py index f2521604eef..0721dda40bc 100644 --- a/cms/test_utils/project/urls_2.py +++ b/cms/test_utils/project/urls_2.py @@ -2,6 +2,7 @@ from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.conf.urls.i18n import i18n_patterns +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -25,6 +26,6 @@ urlpatterns += i18n_patterns( re_path(r'^admin/', admin.site.urls), - re_path(r'^example/$', example_view), - re_path(r'^', include('cms.urls')), + path('example/', example_view), + path('', include('cms.urls')), ) diff --git a/cms/test_utils/project/urls_3.py b/cms/test_utils/project/urls_3.py index f2521604eef..0721dda40bc 100644 --- a/cms/test_utils/project/urls_3.py +++ b/cms/test_utils/project/urls_3.py @@ -2,6 +2,7 @@ from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.conf.urls.i18n import i18n_patterns +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -25,6 +26,6 @@ urlpatterns += i18n_patterns( re_path(r'^admin/', admin.site.urls), - re_path(r'^example/$', example_view), - re_path(r'^', include('cms.urls')), + path('example/', example_view), + path('', include('cms.urls')), ) diff --git a/cms/test_utils/project/urls_for_apphook_tests.py b/cms/test_utils/project/urls_for_apphook_tests.py index fa87153d5bb..110b0dbaea7 100644 --- a/cms/test_utils/project/urls_for_apphook_tests.py +++ b/cms/test_utils/project/urls_for_apphook_tests.py @@ -1,6 +1,7 @@ from django.conf import settings from django.conf.urls.i18n import i18n_patterns from django.contrib import admin +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -20,5 +21,5 @@ ] urlpatterns += i18n_patterns( - re_path(r'^', include('cms.test_utils.project.cms_urls_for_apphook_tests')), + path('', include('cms.test_utils.project.cms_urls_for_apphook_tests')), ) diff --git a/cms/test_utils/project/urls_no18n.py b/cms/test_utils/project/urls_no18n.py index 952748222ed..b0d35662c96 100644 --- a/cms/test_utils/project/urls_no18n.py +++ b/cms/test_utils/project/urls_no18n.py @@ -1,6 +1,7 @@ from django.conf import settings from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import path from django.urls import include, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve @@ -23,6 +24,6 @@ urlpatterns += [ re_path(r'^admin/', admin.site.urls), - re_path(r'^example/$', example_view), - re_path(r'^', include('cms.urls')), + path('example/', example_view), + path('', include('cms.urls')), ] diff --git a/cms/tests/test_admin.py b/cms/tests/test_admin.py index e6dc12aa3bf..e600bf419bc 100644 --- a/cms/tests/test_admin.py +++ b/cms/tests/test_admin.py @@ -760,21 +760,21 @@ def test_smart_link_pages(self): self.assertEqual(403, self.client.get(page_url).status_code) self.assertEqual(200, - self.client.get(page_url, HTTP_X_REQUESTED_WITH='XMLHttpRequest').status_code + self.client.get(page_url, headers={"x-requested-with": 'XMLHttpRequest'}).status_code ) # Test that the query param is working as expected. self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'main_title'}, - HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) + headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'menu_title'}, - HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) + headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'overwritten_url'}, - HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) + headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'page_title'}, - HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) + headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) class AdminPageEditContentSizeTests(AdminTestsBase): diff --git a/cms/tests/test_placeholder.py b/cms/tests/test_placeholder.py index 5b4e34fe226..ab24ffc1392 100644 --- a/cms/tests/test_placeholder.py +++ b/cms/tests/test_placeholder.py @@ -730,7 +730,7 @@ def test_sets_source_when_title_is_created(self): # check for en page_content_en = self.get_page_title_obj(page) - self.assertQuerysetEqual( + self.assertQuerySetEqual( Placeholder.objects.get_for_obj(page_content_en), page_content_en.get_placeholders(), transform=lambda x: x, @@ -739,7 +739,7 @@ def test_sets_source_when_title_is_created(self): # check for another language = de page_content_de = create_title('de', 'test page de', page) - self.assertQuerysetEqual( + self.assertQuerySetEqual( Placeholder.objects.get_for_obj(page_content_de), page_content_de.get_placeholders(), transform=lambda x: x, @@ -833,7 +833,7 @@ def test_placeholder_relation_field(self): with self.login_user_context(self.get_superuser()): self.client.get(get_object_edit_url(poll)) - self.assertQuerysetEqual( + self.assertQuerySetEqual( poll.placeholders.all(), Placeholder.objects.get_for_obj(poll), transform=lambda x: x, diff --git a/cms/tests/test_plugins.py b/cms/tests/test_plugins.py index 4073445050e..0d370475171 100644 --- a/cms/tests/test_plugins.py +++ b/cms/tests/test_plugins.py @@ -12,7 +12,8 @@ from django.core.exceptions import ImproperlyConfigured from django.forms.widgets import Media from django.test.testcases import TestCase -from django.urls import re_path, reverse +from django.urls import path +from django.urls import reverse from django.utils import timezone from django.utils.encoding import force_str from django.utils.translation import override as force_language @@ -82,7 +83,7 @@ def _test_view(self, request): def get_plugin_urls(self): return [ - re_path(r'^testview/$', admin.site.admin_view(self._test_view), name='dumbfixtureplugin'), + path('testview/', admin.site.admin_view(self._test_view), name='dumbfixtureplugin'), ] plugin_pool.register_plugin(DumbFixturePluginWithUrls) diff --git a/cms/urls.py b/cms/urls.py index 5f3a354f2ca..33b1d36d19f 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -1,4 +1,5 @@ from django.conf import settings +from django.urls import path from django.urls import include, re_path from cms import views @@ -21,8 +22,8 @@ urlpatterns.extend([ - re_path(r'^cms_login/$', views.login, name='cms_login'), - re_path(r'^cms_wizard/', include('cms.wizards.urls')), + path('cms_login/', views.login, name='cms_login'), + path('cms_wizard/', include('cms.wizards.urls')), re_path(regexp, views.details, name='pages-details-by-slug'), - re_path(r'^$', views.details, {'slug': ''}, name='pages-root'), + path('', views.details, {'slug': ''}, name='pages-root'), ]) diff --git a/cms/utils/decorators.py b/cms/utils/decorators.py index 559ee662e68..350f6e58b42 100644 --- a/cms/utils/decorators.py +++ b/cms/utils/decorators.py @@ -1,6 +1,6 @@ from django.conf import settings from django.contrib.auth.views import redirect_to_login -from django.utils.http import urlquote +from urllib.parse import quote from cms.page_rendering import _handle_no_page from cms.utils import get_current_site @@ -12,7 +12,7 @@ def inner(request, *args, **kwargs): page = request.current_page if page: if page.login_required and not request.user.is_authenticated: - return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) + return redirect_to_login(quote(request.get_full_path()), settings.LOGIN_URL) site = get_current_site() if not user_can_view_page(request.user, page, site): return _handle_no_page(request) diff --git a/cms/utils/request_ip_resolvers.py b/cms/utils/request_ip_resolvers.py index f55c9a1cdeb..f07472207d6 100644 --- a/cms/utils/request_ip_resolvers.py +++ b/cms/utils/request_ip_resolvers.py @@ -48,7 +48,7 @@ def real_ip(request): Should handle Nginx and some other WSGI servers. """ - return request.META.get('HTTP_X_REAL_IP') + return request.headers.get('x-real-ip') def remote_addr_ip(request): @@ -68,7 +68,7 @@ def x_forwarded_ip(request): Should handle properly configured proxy servers. """ - ip_address_list = request.META.get('HTTP_X_FORWARDED_FOR') + ip_address_list = request.headers.get('x-forwarded-for') if ip_address_list: ip_address_list = ip_address_list.split(',') return ip_address_list[0] diff --git a/cms/views.py b/cms/views.py index 8e66f256f89..f7d08959486 100644 --- a/cms/views.py +++ b/cms/views.py @@ -8,7 +8,8 @@ from django.shortcuts import render from django.urls import reverse from django.utils.cache import patch_cache_control -from django.utils.http import is_safe_url, urlquote +from urllib.parse import quote +from django.utils.http import url_has_allowed_host_and_scheme from django.utils.timezone import now from django.utils.translation import get_language_from_request from django.views.decorators.http import require_POST @@ -165,7 +166,7 @@ def details(request, slug): # permission checks if page.login_required and not request.user.is_authenticated: - return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) + return redirect_to_login(quote(request.get_full_path()), settings.LOGIN_URL) content = page.get_title_obj(language=request_language) # use the page object with populated cache @@ -180,10 +181,10 @@ def details(request, slug): def login(request): redirect_to = request.GET.get(REDIRECT_FIELD_NAME) - if not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()): + if not url_has_allowed_host_and_scheme(url=redirect_to, allowed_hosts=request.get_host()): redirect_to = reverse("pages-root") else: - redirect_to = urlquote(redirect_to) + redirect_to = quote(redirect_to) if request.user.is_authenticated: return HttpResponseRedirect(redirect_to) diff --git a/cms/wizards/urls.py b/cms/wizards/urls.py index a978c079931..27129658f9c 100755 --- a/cms/wizards/urls.py +++ b/cms/wizards/urls.py @@ -1,8 +1,8 @@ -from django.urls import re_path +from django.urls import path from .views import WizardCreateView urlpatterns = [ - re_path(r"^create/$", WizardCreateView.as_view(), name="cms_wizard_create"), + path("create/", WizardCreateView.as_view(), name="cms_wizard_create"), ] diff --git a/menus/apps.py b/menus/apps.py index 8c8af2e290f..d3960c10083 100644 --- a/menus/apps.py +++ b/menus/apps.py @@ -1,5 +1,5 @@ from django.apps import AppConfig -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ class MenusConfig(AppConfig): diff --git a/menus/menu_pool.py b/menus/menu_pool.py index 792fed6d95c..91a45b3df16 100644 --- a/menus/menu_pool.py +++ b/menus/menu_pool.py @@ -8,7 +8,7 @@ from django.urls import NoReverseMatch from django.utils.functional import cached_property from django.utils.module_loading import autodiscover_modules -from django.utils.translation import get_language_from_request, ugettext_lazy as _ +from django.utils.translation import get_language_from_request, gettext_lazy as _ from cms.utils.conf import get_cms_setting from cms.utils.moderator import use_draft diff --git a/menus/templatetags/menu_tags.py b/menus/templatetags/menu_tags.py index 6f85b5de764..5f732896cd2 100644 --- a/menus/templatetags/menu_tags.py +++ b/menus/templatetags/menu_tags.py @@ -3,7 +3,7 @@ from django import template from django.contrib.sites.models import Site from django.urls import reverse, NoReverseMatch -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.translation import get_language, gettext from classytags.arguments import IntegerArgument, Argument, StringArgument @@ -340,11 +340,11 @@ def _raw_language_marker(language, lang_code): def _native_language_marker(language, lang_code): with force_language(lang_code): - return force_text(gettext(language)) + return force_str(gettext(language)) def _current_language_marker(language, lang_code): - return force_text(gettext(language)) + return force_str(gettext(language)) def _short_language_marker(language, lang_code): diff --git a/setup.py b/setup.py index d8ea96e059b..3d81f24001e 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ REQUIREMENTS = [ - 'Django>=2.2', + 'Django>=3.2', 'django-classy-tags>=0.7.2', 'django-formtools>=2.1', 'django-treebeard>=4.3', diff --git a/test_requirements/databases.txt b/test_requirements/databases.txt index 5adc1b2736f..b38a2ed81e6 100644 --- a/test_requirements/databases.txt +++ b/test_requirements/databases.txt @@ -1,2 +1,2 @@ -psycopg2==2.8.6 -mysqlclient==2.0.3 +psycopg2==2.9.9 +mysqlclient==2.1.1 diff --git a/test_requirements/django-2.2.txt b/test_requirements/django-2.2.txt deleted file mode 100644 index 0aa0762d22e..00000000000 --- a/test_requirements/django-2.2.txt +++ /dev/null @@ -1,3 +0,0 @@ --r requirements_base.txt -Django>=2.2,<3.0 -django-formtools==2.2 diff --git a/test_requirements/django-3.0.txt b/test_requirements/django-3.0.txt deleted file mode 100644 index c705bba798c..00000000000 --- a/test_requirements/django-3.0.txt +++ /dev/null @@ -1,2 +0,0 @@ --r requirements_base.txt -Django>=3.0,<3.1 diff --git a/test_requirements/django-3.1.txt b/test_requirements/django-3.1.txt deleted file mode 100644 index 7e732747f75..00000000000 --- a/test_requirements/django-3.1.txt +++ /dev/null @@ -1,3 +0,0 @@ --r requirements_base.txt -Django>=3.1,<3.2 -django-formtools==2.2 diff --git a/test_requirements/django-3.2.txt b/test_requirements/django-3.2.txt index e0c7e287b2c..697d6f7e3b7 100644 --- a/test_requirements/django-3.2.txt +++ b/test_requirements/django-3.2.txt @@ -1,3 +1,3 @@ -r requirements_base.txt Django>=3.2,<3.4 -django-formtools==2.2 +django-formtools==2.4.1 diff --git a/test_requirements/django-4.2.txt b/test_requirements/django-4.2.txt new file mode 100644 index 00000000000..c738cab3be8 --- /dev/null +++ b/test_requirements/django-4.2.txt @@ -0,0 +1,3 @@ +-r requirements_base.txt +Django>=4.2,<5.0 +django-formtools==2.4.1 diff --git a/test_requirements/requirements_base.txt b/test_requirements/requirements_base.txt index c686e9aa5be..13059f4e61e 100644 --- a/test_requirements/requirements_base.txt +++ b/test_requirements/requirements_base.txt @@ -10,7 +10,7 @@ djangocms-admin-style>=1.5 docutils<0.18 # Fix for: https://github.yuuza.net/sphinx-doc/sphinx/issues/9727 iptools mock>=2.0.0 -Pillow==5.2.0 +Pillow==10.1.0 pyenchant==3.0.1 pyflakes>=2.1 python-coveralls>2.5.0 From 997f0bbc2f39dbf4db7a64321234819d7b29e807 Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Thu, 7 Mar 2024 17:53:49 +0530 Subject: [PATCH 02/18] Added changelog --- CHANGELOG.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8c5254f3df5..a2590dca501 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,7 @@ +=== 4.0.1 (unreleased) === +* Introduced Django 4.2 support. +* Dropped Support for Django<3.1 + === 4.0.0 (unreleased) === * feat: Added live-url querystring parameter option for PageContent edit and preview endpoints From 3b7fad807c5f8d356f11eee3ead4f039d273e978 Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Thu, 7 Mar 2024 18:11:25 +0530 Subject: [PATCH 03/18] Updated test.yml to exclude django 3.1 and below --- .github/workflows/test.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 66273a26508..4e4fdfd011a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,10 +10,8 @@ jobs: matrix: python-version: [ 3.7, 3.8, 3.9 ] # latest release minus two requirements-file: [ - django-2.2.txt, - django-3.0.txt, - django-3.1.txt, django-3.2.txt, + django-4.2.txt ] os: [ ubuntu-20.04, @@ -61,10 +59,8 @@ jobs: matrix: python-version: [ 3.7, 3.8, 3.9 ] # latest release minus two requirements-file: [ - django-2.2.txt, - django-3.0.txt, - django-3.1.txt, django-3.2.txt, + django-4.2.txt, ] os: [ ubuntu-20.04, @@ -111,10 +107,8 @@ jobs: matrix: python-version: [ 3.7, 3.8, 3.9 ] # latest release minus two requirements-file: [ - django-2.2.txt, - django-3.0.txt, - django-3.1.txt, django-3.2.txt, + django-4.2.txt, ] os: [ ubuntu-20.04, From b969e9b667e1b58a417d8091ed1947595333228c Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Thu, 7 Mar 2024 18:20:05 +0530 Subject: [PATCH 04/18] Added readthedocs and pillow pinned=9.5.0 --- .readthedocs.yaml | 20 ++++++++++++++++++++ test_requirements/requirements_base.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000000..37c736ede3b --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,20 @@ +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.9" + +sphinx: + configuration: docs/conf.py + fail_on_warning: false + +formats: + - epub + - pdf + +python: + install: + - requirements: docs/requirements.txt \ No newline at end of file diff --git a/test_requirements/requirements_base.txt b/test_requirements/requirements_base.txt index 13059f4e61e..d762dbc6539 100644 --- a/test_requirements/requirements_base.txt +++ b/test_requirements/requirements_base.txt @@ -10,7 +10,7 @@ djangocms-admin-style>=1.5 docutils<0.18 # Fix for: https://github.yuuza.net/sphinx-doc/sphinx/issues/9727 iptools mock>=2.0.0 -Pillow==10.1.0 +Pillow==9.5.0 pyenchant==3.0.1 pyflakes>=2.1 python-coveralls>2.5.0 From 65a7324a63dd521d02ac4fc69a0e79afc6341837 Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Thu, 7 Mar 2024 18:30:41 +0530 Subject: [PATCH 05/18] removed python 3.7 and added 3.10 --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4e4fdfd011a..69d232b9f63 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.7, 3.8, 3.9 ] # latest release minus two + python-version: [ 3.8, 3.9, 3.10 ] # latest release minus two requirements-file: [ django-3.2.txt, django-4.2.txt @@ -57,7 +57,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.7, 3.8, 3.9 ] # latest release minus two + python-version: [ 3.8, 3.9, 3.10 ] # latest release minus two requirements-file: [ django-3.2.txt, django-4.2.txt, @@ -105,7 +105,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.7, 3.8, 3.9 ] # latest release minus two + python-version: [ 3.8, 3.9, 3.10 ] # latest release minus two requirements-file: [ django-3.2.txt, django-4.2.txt, From 67337ac69e7587771e9e51292eda83159f9a8565 Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 03:26:18 +0000 Subject: [PATCH 06/18] fix: workflow and django 4.2 compatibility issues --- .github/workflows/test.yml | 6 +-- cms/__init__.py | 1 - cms/cms_config.py | 2 +- cms/signals/__init__.py | 42 +++---------------- .../project/app_using_non_feature/__init__.py | 1 - .../project/app_with_bad_cms_file/__init__.py | 1 - .../project/app_with_cms_config/__init__.py | 1 - .../project/app_with_cms_feature/__init__.py | 1 - .../__init__.py | 1 - .../__init__.py | 1 - .../__init__.py | 1 - .../__init__.py | 1 - .../app_without_cms_app_class/__init__.py | 1 - .../project/app_without_cms_file/__init__.py | 1 - cms/test_utils/testcases.py | 7 +++- cms/tests/__init__.py | 7 ++++ cms/utils/compat/__init__.py | 18 +++++--- menus/__init__.py | 1 - 18 files changed, 35 insertions(+), 59 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 69d232b9f63..b459bbea4f5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.8, 3.9, 3.10 ] # latest release minus two + python-version: [ 3.8, 3.9, '3.10' ] # latest release minus two requirements-file: [ django-3.2.txt, django-4.2.txt @@ -57,7 +57,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.8, 3.9, 3.10 ] # latest release minus two + python-version: [ 3.8, 3.9, '3.10' ] # latest release minus two requirements-file: [ django-3.2.txt, django-4.2.txt, @@ -105,7 +105,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.8, 3.9, 3.10 ] # latest release minus two + python-version: [ 3.8, 3.9, '3.10' ] # latest release minus two requirements-file: [ django-3.2.txt, django-4.2.txt, diff --git a/cms/__init__.py b/cms/__init__.py index 7363a1e2fd9..8f2dcac6cfa 100644 --- a/cms/__init__.py +++ b/cms/__init__.py @@ -1,3 +1,2 @@ __version__ = '4.0.1.dev2' -default_app_config = 'cms.apps.CMSConfig' diff --git a/cms/cms_config.py b/cms/cms_config.py index b8fe549bf53..486f22fda8e 100644 --- a/cms/cms_config.py +++ b/cms/cms_config.py @@ -1,5 +1,5 @@ from logging import getLogger -from collections import Iterable +from collections.abc import Iterable from django.core.exceptions import ImproperlyConfigured diff --git a/cms/signals/__init__.py b/cms/signals/__init__.py index ac2aa9c2046..2a81f423e83 100644 --- a/cms/signals/__init__.py +++ b/cms/signals/__init__.py @@ -13,52 +13,22 @@ #################### Our own signals ################### # fired after page location is changed - is moved from one node to other -page_moved = Signal(providing_args=["instance"]) +page_moved = Signal() # fired if a public page with an apphook is added or changed -urls_need_reloading = Signal(providing_args=[]) +urls_need_reloading = Signal() # *disclaimer* # The generic object operation signals are very likely to change # as their usage evolves. # As a result, rely on these at your own risk -pre_obj_operation = Signal( - providing_args=[ - "operation", - "request", - "token", - "obj", - ] -) +pre_obj_operation = Signal() -post_obj_operation = Signal( - providing_args=[ - "operation", - "request", - "token", - "obj", - ] -) +post_obj_operation = Signal() -pre_placeholder_operation = Signal( - providing_args=[ - "operation", - "request", - "language", - "token", - "origin", - ] -) +pre_placeholder_operation = Signal() -post_placeholder_operation = Signal( - providing_args=[ - "operation", - "request", - "language", - "token", - "origin", - ] -) +post_placeholder_operation = Signal() ################### apphook reloading ################### diff --git a/cms/test_utils/project/app_using_non_feature/__init__.py b/cms/test_utils/project/app_using_non_feature/__init__.py index 7262828c538..e69de29bb2d 100644 --- a/cms/test_utils/project/app_using_non_feature/__init__.py +++ b/cms/test_utils/project/app_using_non_feature/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_using_non_feature.apps.NonFeatureCMSConfig' diff --git a/cms/test_utils/project/app_with_bad_cms_file/__init__.py b/cms/test_utils/project/app_with_bad_cms_file/__init__.py index f093da3cfa9..e69de29bb2d 100644 --- a/cms/test_utils/project/app_with_bad_cms_file/__init__.py +++ b/cms/test_utils/project/app_with_bad_cms_file/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_with_bad_cms_file.apps.BadCMSFileConfig' diff --git a/cms/test_utils/project/app_with_cms_config/__init__.py b/cms/test_utils/project/app_with_cms_config/__init__.py index ce7ec3f01c1..e69de29bb2d 100644 --- a/cms/test_utils/project/app_with_cms_config/__init__.py +++ b/cms/test_utils/project/app_with_cms_config/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_with_cms_config.apps.CMSConfigConfig' diff --git a/cms/test_utils/project/app_with_cms_feature/__init__.py b/cms/test_utils/project/app_with_cms_feature/__init__.py index 137461ac6d6..e69de29bb2d 100644 --- a/cms/test_utils/project/app_with_cms_feature/__init__.py +++ b/cms/test_utils/project/app_with_cms_feature/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_with_cms_feature.apps.CMSFeatureConfig' diff --git a/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py b/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py index 01465b286f0..e69de29bb2d 100644 --- a/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py +++ b/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_with_cms_feature_and_config.apps.CMSFeatureAndConfigConfig' diff --git a/cms/test_utils/project/app_with_feature_not_implemented/__init__.py b/cms/test_utils/project/app_with_feature_not_implemented/__init__.py index 15de5378e13..e69de29bb2d 100644 --- a/cms/test_utils/project/app_with_feature_not_implemented/__init__.py +++ b/cms/test_utils/project/app_with_feature_not_implemented/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_with_feature_not_implemented.apps.CMSFeatureConfig' diff --git a/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py b/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py index 548761b502a..e69de29bb2d 100644 --- a/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py +++ b/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_with_two_cms_config_classes.apps.TwoCMSAppClassesConfig' diff --git a/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py b/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py index a340059416c..e69de29bb2d 100644 --- a/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py +++ b/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_with_two_cms_feature_classes.apps.TwoCMSAppClassesConfig' diff --git a/cms/test_utils/project/app_without_cms_app_class/__init__.py b/cms/test_utils/project/app_without_cms_app_class/__init__.py index 4109b7b2d8d..e69de29bb2d 100644 --- a/cms/test_utils/project/app_without_cms_app_class/__init__.py +++ b/cms/test_utils/project/app_without_cms_app_class/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_without_cms_app_class.apps.WithoutCMSAppClassConfig' diff --git a/cms/test_utils/project/app_without_cms_file/__init__.py b/cms/test_utils/project/app_without_cms_file/__init__.py index 12711318eb7..e69de29bb2d 100644 --- a/cms/test_utils/project/app_without_cms_file/__init__.py +++ b/cms/test_utils/project/app_without_cms_file/__init__.py @@ -1 +0,0 @@ -default_app_config = 'cms.test_utils.project.app_without_cms_file.apps.WithoutCMSFileConfig' diff --git a/cms/test_utils/testcases.py b/cms/test_utils/testcases.py index 9b8ed46b0c5..7d10adcffdd 100644 --- a/cms/test_utils/testcases.py +++ b/cms/test_utils/testcases.py @@ -23,14 +23,15 @@ from cms.api import create_page, add_plugin from cms.middleware.toolbar import ToolbarMiddleware -from cms.plugin_rendering import ContentRenderer, StructureRenderer from cms.models import Page, PageContent from cms.models.permissionmodels import ( GlobalPagePermission, PagePermission, PageUser, ) +from cms.plugin_rendering import ContentRenderer, StructureRenderer from cms.test_utils.util.context_managers import UserLoginContext +from cms.utils.compat import DJANGO_4_1 from cms.utils.conf import get_cms_setting from cms.utils.permissions import set_current_user from cms.utils.urlutils import admin_reverse @@ -663,4 +664,6 @@ class CMSTestCase(BaseCMSTestCase, testcases.TestCase): class TransactionCMSTestCase(CMSTestCase, testcases.TransactionTestCase): - pass + if DJANGO_4_1: + def assertQuerySetEqual(self, *args, **kwargs): + return self.assertQuerysetEqual(*args, **kwargs) diff --git a/cms/tests/__init__.py b/cms/tests/__init__.py index e69de29bb2d..c88fb5d91e7 100644 --- a/cms/tests/__init__.py +++ b/cms/tests/__init__.py @@ -0,0 +1,7 @@ +import django + + +if django.VERSION < (4, 2): # TODO: remove when dropping support for Django < 4.2 + from django.test.testcases import TransactionTestCase + + TransactionTestCase.assertQuerySetEqual = TransactionTestCase.assertQuerysetEqual \ No newline at end of file diff --git a/cms/utils/compat/__init__.py b/cms/utils/compat/__init__.py index 951b8f16ae4..d5bd669f12d 100644 --- a/cms/utils/compat/__init__.py +++ b/cms/utils/compat/__init__.py @@ -1,14 +1,22 @@ from platform import python_version from django import get_version -from distutils.version import LooseVersion + +try: + from packaging.version import Version +except ModuleNotFoundError: + from distutils.version import LooseVersion as Version DJANGO_VERSION = get_version() PYTHON_VERSION = python_version() + # These means "less than or equal to DJANGO_FOO_BAR" -DJANGO_2_2 = LooseVersion(DJANGO_VERSION) < LooseVersion('3.0') -DJANGO_3_0 = LooseVersion(DJANGO_VERSION) < LooseVersion('3.1') -DJANGO_3_1 = LooseVersion(DJANGO_VERSION) < LooseVersion('3.2') -DJANGO_3_2 = LooseVersion(DJANGO_VERSION) < LooseVersion('3.3') +DJANGO_2_2 = Version(DJANGO_VERSION) < Version('3.0') +DJANGO_3_0 = Version(DJANGO_VERSION) < Version('3.1') +DJANGO_3_1 = Version(DJANGO_VERSION) < Version('3.2') +DJANGO_3_2 = Version(DJANGO_VERSION) < Version('3.3') +DJANGO_3 = Version(DJANGO_VERSION) < Version('4.0') +DJANGO_4_1 = Version(DJANGO_VERSION) < Version('4.2') +DJANGO_4_2 = Version(DJANGO_VERSION) < Version('4.3') diff --git a/menus/__init__.py b/menus/__init__.py index 8b2e2941cea..e69de29bb2d 100644 --- a/menus/__init__.py +++ b/menus/__init__.py @@ -1 +0,0 @@ -default_app_config = 'menus.apps.MenusConfig' From 5925f9d81b85c3c2c8be791c83d7ee0a36b2a9da Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 03:34:03 +0000 Subject: [PATCH 07/18] fix: remove useless --- cms/tests/__init__.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/cms/tests/__init__.py b/cms/tests/__init__.py index c88fb5d91e7..e69de29bb2d 100644 --- a/cms/tests/__init__.py +++ b/cms/tests/__init__.py @@ -1,7 +0,0 @@ -import django - - -if django.VERSION < (4, 2): # TODO: remove when dropping support for Django < 4.2 - from django.test.testcases import TransactionTestCase - - TransactionTestCase.assertQuerySetEqual = TransactionTestCase.assertQuerysetEqual \ No newline at end of file From 36dfb06205299db826a2b5e77db56cca2ff38553 Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 06:43:03 +0000 Subject: [PATCH 08/18] fix: fix PR errors --- .github/workflows/test.yml | 2 +- cms/admin/pageadmin.py | 2 - .../pluginapp/plugins/caching/cms_plugins.py | 4 +- cms/tests/test_docs.py | 102 ------------------ cms/utils/compat/__init__.py | 8 +- cms/views.py | 2 + menus/menu_pool.py | 4 + setup.py | 8 +- test_requirements/django-4.2.txt | 1 - 9 files changed, 16 insertions(+), 117 deletions(-) delete mode 100644 cms/tests/test_docs.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b459bbea4f5..22d33644aaa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,7 +68,7 @@ jobs: services: mysql: - image: mysql:5.7 + image: mysql:8.0 env: MYSQL_ALLOW_EMPTY_PASSWORD: yes MYSQL_DATABASE: djangocms_test diff --git a/cms/admin/pageadmin.py b/cms/admin/pageadmin.py index 06c87620474..5cac651145f 100644 --- a/cms/admin/pageadmin.py +++ b/cms/admin/pageadmin.py @@ -907,8 +907,6 @@ def duplicate(self, request, object_id): if obj is None: raise self._get_404_exception(object_id) - request = copy.copy(request) - if request.method == 'GET': # source is a field in the form # because its value is in the url, diff --git a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py index 6b5af6de73f..a6938407f2a 100644 --- a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py +++ b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py @@ -92,7 +92,7 @@ def get_vary_cache_on(self, request, instance, placeholder): def render(self, context, instance, placeholder): request = context.get('request') - country_code = request.headers.get('country-code') or "any" + country_code = request.headers.get('Country-Code') or "any" context['now'] = country_code return context @@ -101,7 +101,7 @@ class SekizaiPlugin(CMSPluginBase): name = 'WITH SEki' module = 'Test' render_plugin = True - render_template = "plugins/sekizai.html" + render_template = "plugins/sekizai.html"s def render(self, context, instance, placeholder): context['now'] = datetime.now().microsecond diff --git a/cms/tests/test_docs.py b/cms/tests/test_docs.py deleted file mode 100644 index d8147781f9d..00000000000 --- a/cms/tests/test_docs.py +++ /dev/null @@ -1,102 +0,0 @@ -from contextlib import contextmanager -from unittest import skipIf, skipUnless - -import os -import socket -import sys - -from io import StringIO - -from sphinx.errors import SphinxWarning -from sphinx.application import Sphinx - -try: - import enchant -except ImportError: - enchant = None - -import cms -from cms.test_utils.testcases import CMSTestCase -from cms.test_utils.util.context_managers import TemporaryDirectory - - -ROOT_DIR = os.path.dirname(cms.__file__) -DOCS_DIR = os.path.abspath(os.path.join(ROOT_DIR, u'..', u'docs')) - - -def has_no_internet(): - try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.settimeout(5) - s.connect(('4.4.4.2', 80)) - s.send(b"hello") - except socket.error: # no internet - return True - return False - - -@contextmanager -def tmp_list_append(l, x): - l.append(x) - try: - yield - finally: - if x in l: - l.remove(x) - - -class DocsTestCase(CMSTestCase): - """ - Test docs building correctly for HTML - """ - @skipIf(has_no_internet(), "No internet") - def test_html(self): - status = StringIO() - with TemporaryDirectory() as OUT_DIR: - app = Sphinx( - srcdir=DOCS_DIR, - confdir=DOCS_DIR, - outdir=OUT_DIR, - doctreedir=OUT_DIR, - buildername="html", - warningiserror=True, - status=status, - ) - try: - app.build() - except: - print(status.getvalue()) - raise - - @skipIf(has_no_internet(), "No internet") - @skipIf(enchant is None, "Enchant not installed") - @skipUnless(os.environ.get('TEST_DOCS') == '1', 'Skipping for simplicity') - def test_spelling(self): - status = StringIO() - with TemporaryDirectory() as OUT_DIR: - with tmp_list_append(sys.argv, 'spelling'): - try: - app = Sphinx( - srcdir=DOCS_DIR, - confdir=DOCS_DIR, - outdir=OUT_DIR, - doctreedir=OUT_DIR, - buildername="spelling", - warningiserror=True, - status=status, - confoverrides={ - 'extensions': [ - 'djangocms', - 'sphinx.ext.intersphinx', - 'sphinxcontrib.spelling' - ] - } - ) - app.build() - self.assertEqual(app.statuscode, 0, status.getvalue()) - except SphinxWarning: - # while normally harmless, causes a test failure - pass - except: - print(status.getvalue()) - raise diff --git a/cms/utils/compat/__init__.py b/cms/utils/compat/__init__.py index d5bd669f12d..24f3814e57b 100644 --- a/cms/utils/compat/__init__.py +++ b/cms/utils/compat/__init__.py @@ -1,11 +1,7 @@ from platform import python_version -from django import get_version - -try: - from packaging.version import Version -except ModuleNotFoundError: - from distutils.version import LooseVersion as Version +from django import get_version +from packaging.version import Version DJANGO_VERSION = get_version() diff --git a/cms/views.py b/cms/views.py index f7d08959486..7beb1ba4b61 100644 --- a/cms/views.py +++ b/cms/views.py @@ -91,6 +91,8 @@ def details(request, slug): user_languages = get_public_languages(site_id=site.pk) request_language = get_language_from_request(request, check_path=True) + if not request_language: + request_language = get_default_language_for_site(get_current_site().pk) if not page.is_home and request_language not in user_languages: # The homepage is treated differently because diff --git a/menus/menu_pool.py b/menus/menu_pool.py index 91a45b3df16..78ae91c6643 100644 --- a/menus/menu_pool.py +++ b/menus/menu_pool.py @@ -10,7 +10,9 @@ from django.utils.module_loading import autodiscover_modules from django.utils.translation import get_language_from_request, gettext_lazy as _ +from cms.utils import get_current_site from cms.utils.conf import get_cms_setting +from cms.utils.i18n import get_default_language_for_site from cms.utils.moderator import use_draft from menus.base import Menu @@ -102,6 +104,8 @@ def __init__(self, pool, request): self.menus = pool.get_registered_menus(for_rendering=True) self.request = request self.request_language = get_language_from_request(request, check_path=True) + if not self.request_language: + self.request_language = get_default_language_for_site(get_current_site().pk) self.site = Site.objects.get_current(request) self.draft_mode_active = use_draft(request) diff --git a/setup.py b/setup.py index 3d81f24001e..4f2202a4569 100644 --- a/setup.py +++ b/setup.py @@ -6,12 +6,13 @@ REQUIREMENTS = [ - 'Django>=3.2', + 'Django>=3.2, <5', 'django-classy-tags>=0.7.2', 'django-formtools>=2.1', 'django-treebeard>=4.3', 'django-sekizai>=0.7', 'djangocms-admin-style>=1.2', + 'packaging' ] @@ -24,14 +25,15 @@ 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Framework :: Django', 'Framework :: Django :: 2.2', 'Framework :: Django :: 3.0', 'Framework :: Django :: 3.1', 'Framework :: Django :: 3.2', + 'Framework :: Django :: 4.2', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development', diff --git a/test_requirements/django-4.2.txt b/test_requirements/django-4.2.txt index c738cab3be8..33804ceb2ff 100644 --- a/test_requirements/django-4.2.txt +++ b/test_requirements/django-4.2.txt @@ -1,3 +1,2 @@ -r requirements_base.txt Django>=4.2,<5.0 -django-formtools==2.4.1 From 8c90e0a3839dbf74500060eb23a70f6e6ef6abd7 Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 06:52:32 +0000 Subject: [PATCH 09/18] fix: fix typo --- cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py index a6938407f2a..8b060fc5b9c 100644 --- a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py +++ b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py @@ -101,7 +101,7 @@ class SekizaiPlugin(CMSPluginBase): name = 'WITH SEki' module = 'Test' render_plugin = True - render_template = "plugins/sekizai.html"s + render_template = "plugins/sekizai.html" def render(self, context, instance, placeholder): context['now'] = datetime.now().microsecond From e7241e4e1535ff27081be7fa35cab972b66a63e7 Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Fri, 8 Mar 2024 12:40:57 +0530 Subject: [PATCH 10/18] Removed LanguagesessionKEY --- cms/middleware/language.py | 2 +- cms/tests/test_i18n.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cms/middleware/language.py b/cms/middleware/language.py index aabbd466592..77c1aa07f35 100644 --- a/cms/middleware/language.py +++ b/cms/middleware/language.py @@ -1,6 +1,6 @@ import datetime -from django.utils.translation import LANGUAGE_SESSION_KEY, get_language +from django.utils.translation import get_language from django.conf import settings from django.utils.deprecation import MiddlewareMixin diff --git a/cms/tests/test_i18n.py b/cms/tests/test_i18n.py index a1cd3067940..6c6044a7ce9 100644 --- a/cms/tests/test_i18n.py +++ b/cms/tests/test_i18n.py @@ -2,7 +2,6 @@ from django.conf import settings from django.test.utils import override_settings -from django.utils.translation import LANGUAGE_SESSION_KEY from cms import api from cms.test_utils.testcases import CMSTestCase From 2e4454b7ae7afb37c0d3ac84100af767b5b9b643 Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 07:14:28 +0000 Subject: [PATCH 11/18] fix: restore 'default_app_config' --- cms/__init__.py | 1 + cms/test_utils/project/app_using_non_feature/__init__.py | 1 + cms/test_utils/project/app_with_bad_cms_file/__init__.py | 1 + cms/test_utils/project/app_with_cms_config/__init__.py | 1 + cms/test_utils/project/app_with_cms_feature/__init__.py | 1 + .../project/app_with_cms_feature_and_config/__init__.py | 1 + .../project/app_with_feature_not_implemented/__init__.py | 1 + .../project/app_with_two_cms_config_classes/__init__.py | 1 + .../project/app_with_two_cms_feature_classes/__init__.py | 1 + cms/test_utils/project/app_without_cms_app_class/__init__.py | 1 + cms/test_utils/project/app_without_cms_file/__init__.py | 1 + menus/__init__.py | 1 + 12 files changed, 12 insertions(+) diff --git a/cms/__init__.py b/cms/__init__.py index 8f2dcac6cfa..7363a1e2fd9 100644 --- a/cms/__init__.py +++ b/cms/__init__.py @@ -1,2 +1,3 @@ __version__ = '4.0.1.dev2' +default_app_config = 'cms.apps.CMSConfig' diff --git a/cms/test_utils/project/app_using_non_feature/__init__.py b/cms/test_utils/project/app_using_non_feature/__init__.py index e69de29bb2d..7262828c538 100644 --- a/cms/test_utils/project/app_using_non_feature/__init__.py +++ b/cms/test_utils/project/app_using_non_feature/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_using_non_feature.apps.NonFeatureCMSConfig' diff --git a/cms/test_utils/project/app_with_bad_cms_file/__init__.py b/cms/test_utils/project/app_with_bad_cms_file/__init__.py index e69de29bb2d..f093da3cfa9 100644 --- a/cms/test_utils/project/app_with_bad_cms_file/__init__.py +++ b/cms/test_utils/project/app_with_bad_cms_file/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_with_bad_cms_file.apps.BadCMSFileConfig' diff --git a/cms/test_utils/project/app_with_cms_config/__init__.py b/cms/test_utils/project/app_with_cms_config/__init__.py index e69de29bb2d..ce7ec3f01c1 100644 --- a/cms/test_utils/project/app_with_cms_config/__init__.py +++ b/cms/test_utils/project/app_with_cms_config/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_with_cms_config.apps.CMSConfigConfig' diff --git a/cms/test_utils/project/app_with_cms_feature/__init__.py b/cms/test_utils/project/app_with_cms_feature/__init__.py index e69de29bb2d..137461ac6d6 100644 --- a/cms/test_utils/project/app_with_cms_feature/__init__.py +++ b/cms/test_utils/project/app_with_cms_feature/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_with_cms_feature.apps.CMSFeatureConfig' diff --git a/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py b/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py index e69de29bb2d..01465b286f0 100644 --- a/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py +++ b/cms/test_utils/project/app_with_cms_feature_and_config/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_with_cms_feature_and_config.apps.CMSFeatureAndConfigConfig' diff --git a/cms/test_utils/project/app_with_feature_not_implemented/__init__.py b/cms/test_utils/project/app_with_feature_not_implemented/__init__.py index e69de29bb2d..15de5378e13 100644 --- a/cms/test_utils/project/app_with_feature_not_implemented/__init__.py +++ b/cms/test_utils/project/app_with_feature_not_implemented/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_with_feature_not_implemented.apps.CMSFeatureConfig' diff --git a/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py b/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py index e69de29bb2d..548761b502a 100644 --- a/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py +++ b/cms/test_utils/project/app_with_two_cms_config_classes/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_with_two_cms_config_classes.apps.TwoCMSAppClassesConfig' diff --git a/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py b/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py index e69de29bb2d..a340059416c 100644 --- a/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py +++ b/cms/test_utils/project/app_with_two_cms_feature_classes/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_with_two_cms_feature_classes.apps.TwoCMSAppClassesConfig' diff --git a/cms/test_utils/project/app_without_cms_app_class/__init__.py b/cms/test_utils/project/app_without_cms_app_class/__init__.py index e69de29bb2d..4109b7b2d8d 100644 --- a/cms/test_utils/project/app_without_cms_app_class/__init__.py +++ b/cms/test_utils/project/app_without_cms_app_class/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_without_cms_app_class.apps.WithoutCMSAppClassConfig' diff --git a/cms/test_utils/project/app_without_cms_file/__init__.py b/cms/test_utils/project/app_without_cms_file/__init__.py index e69de29bb2d..12711318eb7 100644 --- a/cms/test_utils/project/app_without_cms_file/__init__.py +++ b/cms/test_utils/project/app_without_cms_file/__init__.py @@ -0,0 +1 @@ +default_app_config = 'cms.test_utils.project.app_without_cms_file.apps.WithoutCMSFileConfig' diff --git a/menus/__init__.py b/menus/__init__.py index e69de29bb2d..8b2e2941cea 100644 --- a/menus/__init__.py +++ b/menus/__init__.py @@ -0,0 +1 @@ +default_app_config = 'menus.apps.MenusConfig' From d25f4dd623fcf5914440ddca88307c6b5df9907d Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 08:25:10 +0000 Subject: [PATCH 12/18] fix: failing tests --- cms/admin/pageadmin.py | 1 - cms/middleware/language.py | 73 +++++++++++++++++++------ cms/test_utils/testcases.py | 3 +- cms/tests/test_apphooks.py | 3 +- cms/tests/test_i18n.py | 11 ++-- cms/tests/test_page_admin.py | 4 +- cms/tests/test_templatetags.py | 3 +- docs/requirements.txt | 2 +- test_requirements/requirements_base.txt | 1 + 9 files changed, 73 insertions(+), 28 deletions(-) diff --git a/cms/admin/pageadmin.py b/cms/admin/pageadmin.py index 5cac651145f..0b8370b1970 100644 --- a/cms/admin/pageadmin.py +++ b/cms/admin/pageadmin.py @@ -1,5 +1,4 @@ from collections import namedtuple -import copy import json import django diff --git a/cms/middleware/language.py b/cms/middleware/language.py index aabbd466592..56bbcd1586e 100644 --- a/cms/middleware/language.py +++ b/cms/middleware/language.py @@ -1,22 +1,63 @@ -import datetime - -from django.utils.translation import LANGUAGE_SESSION_KEY, get_language from django.conf import settings from django.utils.deprecation import MiddlewareMixin +from django.utils.translation import get_language + +from cms.utils.compat import DJANGO_3 + +if DJANGO_3: + from django.utils.translation import LANGUAGE_SESSION_KEY class LanguageCookieMiddleware(MiddlewareMixin): - def process_response(self, request, response): - language = get_language() - if hasattr(request, 'session'): - session_language = request.session.get(LANGUAGE_SESSION_KEY, None) - if session_language and not session_language == language: - request.session[LANGUAGE_SESSION_KEY] = language - request.session.save() - if settings.LANGUAGE_COOKIE_NAME in request.COOKIES and \ - request.COOKIES[settings.LANGUAGE_COOKIE_NAME] == language: + def __init__(self, get_response): + super().__init__(get_response) + + if DJANGO_3: + + def __call__(self, request): + response = self.get_response(request) + language = get_language() + if hasattr(request, 'session'): + session_language = request.session.get(LANGUAGE_SESSION_KEY, None) + if session_language and not session_language == language: + request.session[LANGUAGE_SESSION_KEY] = language + request.session.save() + if ( + settings.LANGUAGE_COOKIE_NAME in request.COOKIES + and request.COOKIES[settings.LANGUAGE_COOKIE_NAME] == language # noqa: W503 + ): + return response + response.set_cookie( + settings.LANGUAGE_COOKIE_NAME, + value=language, + domain=settings.LANGUAGE_COOKIE_DOMAIN, + max_age=settings.LANGUAGE_COOKIE_AGE or 365 * 24 * 60 * 60, # 1 year + path=settings.LANGUAGE_COOKIE_PATH, + ) + return response + else: + + def __call__(self, request): + response = self.get_response(request) + language = get_language() + if ( + settings.LANGUAGE_COOKIE_NAME in request.COOKIES # noqa: W503 + and request.COOKIES[settings.LANGUAGE_COOKIE_NAME] == language + ): + return response + + # To ensure support of very old browsers, Django processed automatically "expires" according + # to max_age value. + # https://docs.djangoproject.com/en/3.2/ref/request-response/#django.http.HttpResponse.set_cookie + + response.set_cookie( + settings.LANGUAGE_COOKIE_NAME, + value=language, + domain=settings.LANGUAGE_COOKIE_DOMAIN, + max_age=settings.LANGUAGE_COOKIE_AGE or 365 * 24 * 60 * 60, # 1 year + httponly=settings.LANGUAGE_COOKIE_HTTPONLY, + path=settings.LANGUAGE_COOKIE_PATH, + samesite=settings.LANGUAGE_COOKIE_SAMESITE, + secure=settings.LANGUAGE_COOKIE_SECURE, + ) return response - max_age = 365 * 24 * 60 * 60 # 10 years - expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age) - response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language, expires=expires) - return response diff --git a/cms/test_utils/testcases.py b/cms/test_utils/testcases.py index 7d10adcffdd..9fc58187f5f 100644 --- a/cms/test_utils/testcases.py +++ b/cms/test_utils/testcases.py @@ -11,6 +11,7 @@ from django.core.cache import cache from django.core.exceptions import ObjectDoesNotExist from django.forms.models import model_to_dict +from django.http import HttpResponse from django.template import engines from django.template.context import Context from django.test import testcases @@ -451,7 +452,7 @@ def get_page_request(self, page, user, path=None, lang_code='en', disable=False, if persist is not None: request.GET[get_cms_setting('CMS_TOOLBAR_URL__PERSIST')] = persist request.current_page = page - mid = ToolbarMiddleware() + mid = ToolbarMiddleware(lambda req: HttpResponse("")) mid.process_request(request) if hasattr(request, 'toolbar'): request.toolbar.populate() diff --git a/cms/tests/test_apphooks.py b/cms/tests/test_apphooks.py index 5cb77ef5d07..36410d434ea 100644 --- a/cms/tests/test_apphooks.py +++ b/cms/tests/test_apphooks.py @@ -22,6 +22,7 @@ from cms.test_utils.testcases import CMSTestCase from cms.tests.test_menu_utils import DumbPageLanguageUrl from cms.toolbar.toolbar import CMSToolbar +from cms.utils.compat import DJANGO_3 from menus.menu_pool import menu_pool from menus.utils import DefaultLanguageChanger @@ -284,7 +285,7 @@ def test_apphook_permissions_preserves_view_name(self): view_names = ( ('sample-settings', 'sample_view'), ('sample-class-view', 'ClassView'), - ('sample-class-based-view', 'ClassBasedView'), + ('sample-class-based-view', 'ClassBasedView' if DJANGO_3 else 'view'), ) with force_language("en"): diff --git a/cms/tests/test_i18n.py b/cms/tests/test_i18n.py index a1cd3067940..b3af9377561 100644 --- a/cms/tests/test_i18n.py +++ b/cms/tests/test_i18n.py @@ -2,13 +2,14 @@ from django.conf import settings from django.test.utils import override_settings -from django.utils.translation import LANGUAGE_SESSION_KEY from cms import api from cms.test_utils.testcases import CMSTestCase -from cms.utils import i18n, get_language_from_request +from cms.utils import get_language_from_request, i18n +from cms.utils.compat import DJANGO_3 -from cms.utils.compat import DJANGO_3_0, DJANGO_3_1, DJANGO_3_2 +if DJANGO_3: + from django.utils.translation import LANGUAGE_SESSION_KEY @override_settings( @@ -362,7 +363,7 @@ def test_session_language(self): # ugly and long set of session session = self.client.session - if DJANGO_3_0 or DJANGO_3_1 or DJANGO_3_2: + if not DJANGO_3: self.client.cookies[settings.LANGUAGE_COOKIE_NAME] = 'fr' else: session[LANGUAGE_SESSION_KEY] = 'fr' @@ -371,7 +372,7 @@ def test_session_language(self): self.assertEqual(response.status_code, 302) self.assertRedirects(response, '/fr/') self.client.get('/en/') - if DJANGO_3_0 or DJANGO_3_1 or DJANGO_3_2: + if not DJANGO_3: self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, 'en') else: self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], 'en') diff --git a/cms/tests/test_page_admin.py b/cms/tests/test_page_admin.py index bbf7876f8c2..3c302b45a08 100644 --- a/cms/tests/test_page_admin.py +++ b/cms/tests/test_page_admin.py @@ -6,7 +6,7 @@ from django.contrib.sites.models import Site from django.core.cache import cache from django.forms.models import model_to_dict -from django.http import HttpRequest +from django.http import HttpRequest, HttpResponse from django.test.html import HTMLParseError, Parser from django.test.utils import override_settings from django.urls import clear_url_caches @@ -1286,7 +1286,7 @@ def test_form_url_page_change(self): content = self.get_page_title_obj(page, 'en') form_url = self.get_page_change_uri('en', page) # Middleware is needed to correctly setup the environment for the admin - middleware = CurrentUserMiddleware() + middleware = CurrentUserMiddleware(lambda req: HttpResponse("")) request = self.get_request() middleware.process_request(request) response = content_admin.change_view( diff --git a/cms/tests/test_templatetags.py b/cms/tests/test_templatetags.py index 6e5aefaa419..9dff4d3b727 100644 --- a/cms/tests/test_templatetags.py +++ b/cms/tests/test_templatetags.py @@ -6,6 +6,7 @@ from django.contrib.sites.models import Site from django.core import mail from django.core.exceptions import ImproperlyConfigured +from django.http import HttpResponse from django.test import RequestFactory from django.test.utils import override_settings from django.utils.encoding import force_str @@ -181,7 +182,7 @@ def test_get_page_by_pk_arg_edit_mode(self): user = self._create_user("admin", True, True) request.current_page = control request.user = user - middleware = ToolbarMiddleware() + middleware = ToolbarMiddleware(lambda req: HttpResponse("")) middleware.process_request(request) page = _get_page_by_untyped_arg(control.pk, request, 1) self.assertEqual(page, control) diff --git a/docs/requirements.txt b/docs/requirements.txt index 79050b9b4d0..834e49f1b1c 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,7 +2,7 @@ MarkupSafe==0.23 Pygments==2.0.2 sphinx sphinxcontrib-spelling -pyenchant==3.0.1 +pyenchant==3.2.2 sphinx-autobuild divio-docs-theme datetime diff --git a/test_requirements/requirements_base.txt b/test_requirements/requirements_base.txt index d762dbc6539..22a20211491 100644 --- a/test_requirements/requirements_base.txt +++ b/test_requirements/requirements_base.txt @@ -8,6 +8,7 @@ django-sekizai>=0.7 django-treebeard>=4.3 djangocms-admin-style>=1.5 docutils<0.18 # Fix for: https://github.yuuza.net/sphinx-doc/sphinx/issues/9727 +djangocms-text-ckeditor iptools mock>=2.0.0 Pillow==9.5.0 From 5c317a5545bf9911f0b354a19cafcab57721a09a Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 08:51:17 +0000 Subject: [PATCH 13/18] fix: update pip requirement --- test_requirements/django-3.2.txt | 1 + test_requirements/django-4.2.txt | 1 + test_requirements/requirements_base.txt | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test_requirements/django-3.2.txt b/test_requirements/django-3.2.txt index 697d6f7e3b7..158c1e4daf4 100644 --- a/test_requirements/django-3.2.txt +++ b/test_requirements/django-3.2.txt @@ -1,3 +1,4 @@ -r requirements_base.txt Django>=3.2,<3.4 django-formtools==2.4.1 +djangocms-text-ckeditor<5.0.0 \ No newline at end of file diff --git a/test_requirements/django-4.2.txt b/test_requirements/django-4.2.txt index 33804ceb2ff..2d3fd24426f 100644 --- a/test_requirements/django-4.2.txt +++ b/test_requirements/django-4.2.txt @@ -1,2 +1,3 @@ -r requirements_base.txt Django>=4.2,<5.0 +djangocms-text-ckeditor>=5.1.5 \ No newline at end of file diff --git a/test_requirements/requirements_base.txt b/test_requirements/requirements_base.txt index 22a20211491..30dc3abdb71 100644 --- a/test_requirements/requirements_base.txt +++ b/test_requirements/requirements_base.txt @@ -8,7 +8,6 @@ django-sekizai>=0.7 django-treebeard>=4.3 djangocms-admin-style>=1.5 docutils<0.18 # Fix for: https://github.yuuza.net/sphinx-doc/sphinx/issues/9727 -djangocms-text-ckeditor iptools mock>=2.0.0 Pillow==9.5.0 @@ -21,6 +20,6 @@ sphinxcontrib-spelling<7.0.0 # restriction for py35 tests unittest-xml-reporting==1.11.0 # FIXME: - Remove when a django 3.0 compatible djangocms-text-ckeditor version is released -https://github.com/Aiky30/djangocms-text-ckeditor/archive/feature/cms-40-django-30-support-.zip +#https://github.com/Aiky30/djangocms-text-ckeditor/archive/feature/cms-40-django-30-support-.zip https://github.com/ojii/django-better-test/archive/8aa2407d097fe3789b74682f0e6bd7d15d449416.zip#egg=django-better-test https://github.com/ojii/django-app-manage/archive/65da18ef234a4e985710c2c0ec760023695b40fe.zip#egg=django-app-manage From 11756c577b38510df720d5673b516836c528baf5 Mon Sep 17 00:00:00 2001 From: Josh Peng Yu Date: Fri, 8 Mar 2024 09:12:14 +0000 Subject: [PATCH 14/18] fix: failing tests --- cms/middleware/language.py | 6 +++--- cms/tests/test_admin.py | 10 +++++----- cms/tests/test_i18n.py | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cms/middleware/language.py b/cms/middleware/language.py index 56bbcd1586e..c32f04abae7 100644 --- a/cms/middleware/language.py +++ b/cms/middleware/language.py @@ -2,9 +2,9 @@ from django.utils.deprecation import MiddlewareMixin from django.utils.translation import get_language -from cms.utils.compat import DJANGO_3 +from cms.utils.compat import DJANGO_2_2 -if DJANGO_3: +if DJANGO_2_2: from django.utils.translation import LANGUAGE_SESSION_KEY @@ -12,7 +12,7 @@ class LanguageCookieMiddleware(MiddlewareMixin): def __init__(self, get_response): super().__init__(get_response) - if DJANGO_3: + if DJANGO_2_2: def __call__(self, request): response = self.get_response(request) diff --git a/cms/tests/test_admin.py b/cms/tests/test_admin.py index e600bf419bc..e6dc12aa3bf 100644 --- a/cms/tests/test_admin.py +++ b/cms/tests/test_admin.py @@ -760,21 +760,21 @@ def test_smart_link_pages(self): self.assertEqual(403, self.client.get(page_url).status_code) self.assertEqual(200, - self.client.get(page_url, headers={"x-requested-with": 'XMLHttpRequest'}).status_code + self.client.get(page_url, HTTP_X_REQUESTED_WITH='XMLHttpRequest').status_code ) # Test that the query param is working as expected. self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'main_title'}, - headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) + HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'menu_title'}, - headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) + HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'overwritten_url'}, - headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) + HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) self.assertEqual(1, len(json.loads(self.client.get(page_url, {'q':'page_title'}, - headers={"x-requested-with": 'XMLHttpRequest'}).content.decode("utf-8")))) + HTTP_X_REQUESTED_WITH='XMLHttpRequest').content.decode("utf-8")))) class AdminPageEditContentSizeTests(AdminTestsBase): diff --git a/cms/tests/test_i18n.py b/cms/tests/test_i18n.py index b3af9377561..0e48d8a5656 100644 --- a/cms/tests/test_i18n.py +++ b/cms/tests/test_i18n.py @@ -6,9 +6,9 @@ from cms import api from cms.test_utils.testcases import CMSTestCase from cms.utils import get_language_from_request, i18n -from cms.utils.compat import DJANGO_3 +from cms.utils.compat import DJANGO_2_2 -if DJANGO_3: +if DJANGO_2_2: from django.utils.translation import LANGUAGE_SESSION_KEY @@ -363,7 +363,7 @@ def test_session_language(self): # ugly and long set of session session = self.client.session - if not DJANGO_3: + if not DJANGO_2_2: self.client.cookies[settings.LANGUAGE_COOKIE_NAME] = 'fr' else: session[LANGUAGE_SESSION_KEY] = 'fr' @@ -372,7 +372,7 @@ def test_session_language(self): self.assertEqual(response.status_code, 302) self.assertRedirects(response, '/fr/') self.client.get('/en/') - if not DJANGO_3: + if not DJANGO_2_2: self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, 'en') else: self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], 'en') From d40bdc2876536305a6766463d233c6ec2cb607c9 Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Fri, 8 Mar 2024 17:44:03 +0530 Subject: [PATCH 15/18] updated path from re_path in settingsadmin --- cms/admin/settingsadmin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/admin/settingsadmin.py b/cms/admin/settingsadmin.py index 43dc3b34119..6905db68daf 100644 --- a/cms/admin/settingsadmin.py +++ b/cms/admin/settingsadmin.py @@ -44,7 +44,7 @@ def wrapper(*args, **kwargs): path('', wrap(self.change_view), name='%s_%s_change' % info), - re_path(r'^(.+)/$', + path(r'^(.+)/$', wrap(self.change_view), name='%s_%s_change' % info), ] From e8da26d198f01a2defc90f13419254b787fa8fb7 Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Fri, 8 Mar 2024 17:54:30 +0530 Subject: [PATCH 16/18] removed unused import --- cms/admin/settingsadmin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cms/admin/settingsadmin.py b/cms/admin/settingsadmin.py index 6905db68daf..e71d6257477 100644 --- a/cms/admin/settingsadmin.py +++ b/cms/admin/settingsadmin.py @@ -11,7 +11,6 @@ from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest from django.http.request import QueryDict from django.urls import path -from django.urls import re_path from django.utils.html import conditional_escape from django.utils.translation import override From 955c43bfc01f9bad29432188624ba1b358acdeca Mon Sep 17 00:00:00 2001 From: Vipul Narang Date: Fri, 8 Mar 2024 18:11:00 +0530 Subject: [PATCH 17/18] updated regular expression --- cms/admin/settingsadmin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/admin/settingsadmin.py b/cms/admin/settingsadmin.py index e71d6257477..7e9c7b5e784 100644 --- a/cms/admin/settingsadmin.py +++ b/cms/admin/settingsadmin.py @@ -43,7 +43,7 @@ def wrapper(*args, **kwargs): path('', wrap(self.change_view), name='%s_%s_change' % info), - path(r'^(.+)/$', + path('/$', wrap(self.change_view), name='%s_%s_change' % info), ] From 7181112e20c2e3c2c709ab45009b56f18c7f9860 Mon Sep 17 00:00:00 2001 From: vipulnarang95 <61502917+vipulnarang95@users.noreply.github.com> Date: Fri, 8 Mar 2024 19:13:43 +0530 Subject: [PATCH 18/18] Update settingsadmin.py --- cms/admin/settingsadmin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/admin/settingsadmin.py b/cms/admin/settingsadmin.py index 7e9c7b5e784..baa4ea4db99 100644 --- a/cms/admin/settingsadmin.py +++ b/cms/admin/settingsadmin.py @@ -43,7 +43,7 @@ def wrapper(*args, **kwargs): path('', wrap(self.change_view), name='%s_%s_change' % info), - path('/$', + path('/', wrap(self.change_view), name='%s_%s_change' % info), ]