Date: Sunday, February 20, 2022 @ 16:18:24 Author: dvzrv Revision: 1135302
upgpkg: hyperkitty 1.3.5-4: Rebuild for django 4.0 compatibility. Add fixes for django 4.0 compatibility: https://gitlab.com/mailman/hyperkitty/-/merge_requests/384 Remove unneeded quotes and curly braces. Added: hyperkitty/trunk/hyperkitty-1.3.5-django4.0.patch Modified: hyperkitty/trunk/PKGBUILD ----------------------------------+ PKGBUILD | 100 +++++----- hyperkitty-1.3.5-django4.0.patch | 341 +++++++++++++++++++++++++++++++++++++ 2 files changed, 393 insertions(+), 48 deletions(-) Modified: PKGBUILD =================================================================== --- PKGBUILD 2022-02-20 16:04:10 UTC (rev 1135301) +++ PKGBUILD 2022-02-20 16:18:24 UTC (rev 1135302) @@ -3,7 +3,7 @@ _name=HyperKitty pkgname=hyperkitty pkgver=1.3.5 -pkgrel=3 +pkgrel=4 pkgdesc="A web interface to access GNU Mailman v3 archives" arch=(any) url="https://gitlab.com/mailman/hyperkitty" @@ -20,23 +20,25 @@ 'python-xapian-haystack: for using xapian as search backend' 'uwsgi-plugin-python: for running inside uwsgi' 'ruby-sassc: alternative to sassc') -backup=("etc/uwsgi/${pkgname}.ini" - "etc/webapps/${pkgname}/settings_local.py" - "etc/webapps/${pkgname}/urls.py" +backup=( + etc/uwsgi/$pkgname.ini + etc/webapps/$pkgname/settings_local.py + etc/webapps/$pkgname/urls.py ) -install="${pkgname}.install" +install=$pkgname.install source=( - "https://files.pythonhosted.org/packages/source/${_name::1}/${_name}/${_name}-${pkgver}.tar.gz"{,.asc} - "${pkgname}-1.3.2-settings.patch" - "${pkgname}-1.3.5-qcluster_retry.patch" - "${pkgname}-1.3.5-mistune2.0.0_imports.patch" - "${pkgname}-1.3.5-implict_primary_keys.patch" - "${pkgname}-1.3.5-assert_printable_date.patch" - "${pkgname}-1.3.5-assert_date_header.patch" - "${pkgname}-qcluster.service" - "${pkgname}.sysusers" - "${pkgname}.tmpfiles" - "${pkgname}.uwsgi" + https://files.pythonhosted.org/packages/source/${_name::1}/$_name/$_name-$pkgver.tar.gz{,.asc} + $pkgname-1.3.2-settings.patch + $pkgname-1.3.5-qcluster_retry.patch + $pkgname-1.3.5-mistune2.0.0_imports.patch + $pkgname-1.3.5-implict_primary_keys.patch + $pkgname-1.3.5-assert_printable_date.patch + $pkgname-1.3.5-assert_date_header.patch + $pkgname-qcluster.service + $pkgname.sysusers + $pkgname.tmpfiles + $pkgname.uwsgi + $pkgname-1.3.5-django4.0.patch ) sha512sums=('9e794cd522904369dea5a70489e3ab7fe149680ed13f03e5002f0ad84304cf1de7481c71e302cf46cd9fa244cadca5d0c41767ceb4cee82b7153f052bc1b677d' 'SKIP' @@ -49,7 +51,8 @@ 'a41c938082ceee555143ddb21c3a95835f9832b9aff423142d78d3e52f12500561f80e0ce43c67a4f190065c9d045945741ac71ab3307db1419c4dc0686db09a' '3267427109b08b8c9336b187381ed14357a07370bdcdfc24da94555020ad0424c5bbebc09e131e981e0540c51db443ffe558209e1bca7c2a1b7b1f602ed0805b' 'c943d82b8640a513728e3f07fa44c0ddb5a3bb8ec84a3a70990e51287ca01977887f895b901688fc4643d8fcb106d524259a86a51bccaafd77c69b241f1b23ba' - '351f40a6bc1fd1735c883408f9941808e081206927a7c02467e03228243dd156378cac21f851b498702bd4f96fde8e4c80536dbcc6f3c384bf708bed4e988971') + '351f40a6bc1fd1735c883408f9941808e081206927a7c02467e03228243dd156378cac21f851b498702bd4f96fde8e4c80536dbcc6f3c384bf708bed4e988971' + '27c018daa36d84207fc7911568f85e4f903b8b87026c98e6b05b5dfe78b2437bc6619ea6a30ac4b3666c6e46f0115627bafcd7cba8a6739354bfc80d5666cee7') b2sums=('2ef6917425bdf00a5a03383a8f7ff0eb1243557c1189d9afba33b3c1f09db63b40827b0e7f9602964f251197045594d786df13c6cd288c97980967bdf85eba4c' 'SKIP' '1eab6221db4adb1a066bde8d6c84a90d3e414d1d30c5cf55a90a4ac58d131f7c4872c85d65e98d91ee0f4cac6f71c47c829993c736617a86be8fec5d831422c8' @@ -61,39 +64,40 @@ 'e8ae1d123e74b0c6984df3e5fff720e03dcbc3f007123718fe845024b42e5c13b7eac4da6bde04a9e1372d446bfa50ac12479730a9092e8396b73434e59663d3' 'f4e912e75c5127897837d67626ba94a418ec408f0f3a9bcd1767633347e107600cc43825caa5737a84362273a353bf03097879ff5b9065663150f6db4b96238a' 'e4fd83e38703d8ff9a714b238296e4e12791b8ce0c19446709e5c20b4012ed10b97504cafda66cdbe12e56a9f943c094147b6a02db3bd9c854e609adca38ff01' - '767f334add0dd0e83b27e198415a2ef8ae3c505aa7f37d12138e37a98dc5575e43f83eb665431464ed488a5bf6b8913cd675eb112dc880cf17ff51511a3f07e6') + '767f334add0dd0e83b27e198415a2ef8ae3c505aa7f37d12138e37a98dc5575e43f83eb665431464ed488a5bf6b8913cd675eb112dc880cf17ff51511a3f07e6' + '8d958d3e9cce9fbee504d30108fb43d4978c2dca300ccdd9f1a136bc4dd3daca6009c5cc95e1143d6df7b704c0cef5c6318e55fef7c31b03c21cb24876b479bf') validpgpkeys=('541EA0448453394FF77A0ECC9D9B2BA061D0A67C') # Abhilash Raj <[email protected]> prepare() { - mv -v "${_name}-${pkgver}" "$pkgname-$pkgver" - cd "$pkgname-$pkgver" # setting FHS compliant default paths, remove debug options - patch -Np1 -i "../${pkgname}-1.3.2-settings.patch" - + patch -d $_name-$pkgver -p1 -i ../$pkgname-1.3.2-settings.patch # fix warnings with qcluster retry # https://gitlab.com/mailman/hyperkitty/-/issues/402 - patch -Np1 -i ../"${pkgname}-1.3.5-qcluster_retry.patch" + patch -d $_name-$pkgver -p1 -i ../$pkgname-1.3.5-qcluster_retry.patch # fix imports with python-mistune >= 2.0.0 # https://gitlab.com/mailman/hyperkitty/-/issues/395 - patch -Np1 -i ../"${pkgname}-1.3.5-mistune2.0.0_imports.patch" + patch -d $_name-$pkgver -p1 -i ../$pkgname-1.3.5-mistune2.0.0_imports.patch # fix excessive warnings with django >= 3.2 # https://gitlab.com/mailman/hyperkitty/-/issues/401 - patch -Np1 -i ../"${pkgname}-1.3.5-implict_primary_keys.patch" + patch -d $_name-$pkgver -p1 -i ../$pkgname-1.3.5-implict_primary_keys.patch # fix issues due to changes in the email module in python 3.10 # https://gitlab.com/mailman/hyperkitty/-/issues/401 - patch -Np1 -i ../"${pkgname}-1.3.5-assert_printable_date.patch" - patch -Np1 -i ../"${pkgname}-1.3.5-assert_date_header.patch" - touch settings_local.py + patch -d $_name-$pkgver -p1 -i ../$pkgname-1.3.5-assert_printable_date.patch + patch -d $_name-$pkgver -p1 -i ../$pkgname-1.3.5-assert_date_header.patch + # make compatible with django 4.0: https://gitlab.com/mailman/hyperkitty/-/merge_requests/384 + patch -d $_name-$pkgver -p1 -i ../$pkgname-1.3.5-django4.0.patch + + touch $_name-$pkgver/settings_local.py } build() { - cd "$pkgname-$pkgver" + cd $_name-$pkgver python setup.py build } check() { - cd "$pkgname-$pkgver" - export PYTHONPATH="build:${PYTHONPATH}" + cd $_name-$pkgver + export PYTHONPATH="build:$PYTHONPATH" python example_project/manage.py test --settings=hyperkitty.tests.settings_test hyperkitty } @@ -100,33 +104,33 @@ package() { local python_stdlib_basepath="$(python -c "from sysconfig import get_path; print(get_path('stdlib'))")" - cd "$pkgname-$pkgver" - python setup.py install --optimize=1 --root="${pkgdir}" + cd $_name-$pkgver + python setup.py install --optimize=1 --root="$pkgdir" # remove example_project from top level site-packages: # https://gitlab.com/mailman/hyperkitty/issues/279 - rm -rfv "${pkgdir}/${python_stdlib_basepath}/site-packages/example_project" + rm -rfv "$pkgdir/$python_stdlib_basepath/site-packages/example_project" # doc - install -vDm 644 README.rst -t "${pkgdir}/usr/share/doc/${pkgname}" + install -vDm 644 README.rst -t "$pkgdir/usr/share/doc/$pkgname" # django project - install -vDm 644 example_project/{__init__,manage,settings,wsgi}.py -t "${pkgdir}/usr/share/webapps/${pkgname}" + install -vDm 644 example_project/{__init__,manage,settings,wsgi}.py -t "$pkgdir/usr/share/webapps/$pkgname" # symlink locale and static dirs to state dir - ln -svf "/var/lib/${pkgname}/locale/" "${pkgdir}/usr/share/webapps/${pkgname}" - ln -svf "/var/lib/${pkgname}/static/" "${pkgdir}/usr/share/webapps/${pkgname}" + ln -svf /var/lib/$pkgname/locale/ "$pkgdir/usr/share/webapps/$pkgname" + ln -svf /var/lib/$pkgname/static/ "$pkgdir/usr/share/webapps/$pkgname" # state dir - install -vdm 750 "${pkgdir}/var/lib/${pkgname}/data" - install -vdm 755 "${pkgdir}/var/lib/${pkgname}/"{locale,static} + install -vdm 750 "$pkgdir/var/lib/$pkgname/data" + install -vdm 755 "$pkgdir/var/lib/$pkgname/"{locale,static} # log dir - install -vdm 750 "${pkgdir}/var/log/${pkgname}" + install -vdm 750 "$pkgdir/var/log/$pkgname" # config - install -vDm 640 settings_local.py example_project/urls.py -t "${pkgdir}/etc/webapps/${pkgname}" - ln -svf "/etc/webapps/${pkgname}/settings_local.py" "${pkgdir}/usr/share/webapps/${pkgname}/settings_local.py" - ln -svf "/etc/webapps/${pkgname}/urls.py" "${pkgdir}/usr/share/webapps/${pkgname}/urls.py" + install -vDm 640 settings_local.py example_project/urls.py -t "$pkgdir/etc/webapps/$pkgname" + ln -svf "/etc/webapps/$pkgname/settings_local.py" "$pkgdir/usr/share/webapps/$pkgname/settings_local.py" + ln -svf "/etc/webapps/$pkgname/urls.py" "$pkgdir/usr/share/webapps/$pkgname/urls.py" # systemd service - install -vDm 644 "../${pkgname}-qcluster.service" -t "${pkgdir}/usr/lib/systemd/system" + install -vDm 644 "../$pkgname-qcluster.service" -t "$pkgdir/usr/lib/systemd/system" # uwsgi - install -vDm 644 "../${pkgname}.uwsgi" "${pkgdir}/etc/uwsgi/${pkgname}.ini" + install -vDm 644 "../$pkgname.uwsgi" "$pkgdir/etc/uwsgi/$pkgname.ini" # tmpfiles.d - install -vDm 644 "../${pkgname}.tmpfiles" "${pkgdir}/usr/lib/tmpfiles.d/${pkgname}.conf" + install -vDm 644 "../$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf" # sysusers.d - install -vDm 644 "../${pkgname}.sysusers" "${pkgdir}/usr/lib/sysusers.d/${pkgname}.conf" + install -vDm 644 "../$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf" } Added: hyperkitty-1.3.5-django4.0.patch =================================================================== --- hyperkitty-1.3.5-django4.0.patch (rev 0) +++ hyperkitty-1.3.5-django4.0.patch 2022-02-20 16:18:24 UTC (rev 1135302) @@ -0,0 +1,341 @@ +From e8228c7eddae75d168b28bc3a7abe351bab04b65 Mon Sep 17 00:00:00 2001 +From: John Vandenberg <[email protected]> +Date: Mon, 27 Dec 2021 10:48:27 +0800 +Subject: [PATCH 1/3] Support Django 4.0 + +--- + example_project/urls.py | 12 +-- + hyperkitty/tests/urls_test.py | 9 +- + hyperkitty/urls.py | 157 +++++++++++++++------------------- + hyperkitty/views/mailman.py | 5 +- + setup.py | 2 +- + 5 files changed, 85 insertions(+), 100 deletions(-) + +diff --git a/example_project/urls.py b/example_project/urls.py +index 9c854989..53245861 100644 +--- a/example_project/urls.py ++++ b/example_project/urls.py +@@ -21,21 +21,21 @@ This file is the main URL config for a Django website including HyperKitty. + """ + + from django.conf import settings +-from django.conf.urls import include, url ++from django.conf.urls import include + from django.contrib import admin + from django.urls import path, reverse_lazy + from django.views.generic import RedirectView + + + urlpatterns = [ +- url(r'^$', RedirectView.as_view( ++ path('', RedirectView.as_view( + url=reverse_lazy('hk_root'))), +- url(r'^hyperkitty/', include('hyperkitty.urls')), ++ path('hyperkitty/', include('hyperkitty.urls')), + # url(r'^postorius/', include('postorius.urls')), +- url(r'', include('django_mailman3.urls')), +- url(r'^accounts/', include('allauth.urls')), ++ path('', include('django_mailman3.urls')), ++ path('accounts/', include('allauth.urls')), + # Django admin +- url(r'^admin/', admin.site.urls), ++ path('admin/', admin.site.urls), + ] + + +diff --git a/hyperkitty/tests/urls_test.py b/hyperkitty/tests/urls_test.py +index 67d5497a..4e1c3af7 100644 +--- a/hyperkitty/tests/urls_test.py ++++ b/hyperkitty/tests/urls_test.py +@@ -21,11 +21,12 @@ + This file is the main URL config for a Django website including HyperKitty. + """ + +-from django.conf.urls import include, url ++from django.conf.urls import include ++from django.urls import path + + + urlpatterns = [ +- url(r'', include('hyperkitty.urls')), +- url(r'', include('django_mailman3.urls')), +- url(r'^accounts/', include('allauth.urls')), ++ path('', include('hyperkitty.urls')), ++ path('', include('django_mailman3.urls')), ++ path('accounts/', include('allauth.urls')), + ] +diff --git a/hyperkitty/urls.py b/hyperkitty/urls.py +index a6782fbd..f5e45e1a 100644 +--- a/hyperkitty/urls.py ++++ b/hyperkitty/urls.py +@@ -21,8 +21,9 @@ + # Author: Aurelien Bompard <[email protected]> + # + +-from django.conf.urls import include, url ++from django.conf.urls import include + from django.contrib.staticfiles.urls import staticfiles_urlpatterns ++from django.urls import path, re_path + from django.views.generic.base import TemplateView + + from hyperkitty.api import email as api_email +@@ -41,146 +42,130 @@ from hyperkitty.views import ( + + # List archives and overview + list_patterns = [ +- url(r'^(?P<year>\d{4})/(?P<month>\d\d?)/(?P<day>\d\d?)/$', ++ re_path(r'^(?P<year>\d{4})/(?P<month>\d\d?)/(?P<day>\d\d?)/$', + mlist.archives, name='hk_archives_with_day'), +- url(r'^(?P<year>\d{4})/(?P<month>\d\d?)/$', ++ re_path(r'^(?P<year>\d{4})/(?P<month>\d\d?)/$', + mlist.archives, name='hk_archives_with_month'), +- url(r'^latest$', mlist.archives, name='hk_archives_latest'), +- url(r'^$', mlist.overview, name='hk_list_overview'), +- url(r'^recent-activity$', +- mlist.recent_activity, name='hk_list_recent_activity'), +- url(r'^recent-threads$', +- mlist.overview_recent_threads, name='hk_list_overview_recent_threads'), +- url(r'^pop-threads$', +- mlist.overview_pop_threads, name='hk_list_overview_pop_threads'), +- url(r'^top-threads$', +- mlist.overview_top_threads, name='hk_list_overview_top_threads'), +- url(r'^favorites$', +- mlist.overview_favorites, name='hk_list_overview_favorites'), +- url(r'^posted-to$', +- mlist.overview_posted_to, name='hk_list_overview_posted_to'), +- url(r'^top-posters$', +- mlist.overview_top_posters, name='hk_list_overview_top_posters'), +- url(r'^export/(?P<filename>[^/]+)\.mbox.gz$', ++ path('latest', mlist.archives, name='hk_archives_latest'), ++ path('', mlist.overview, name='hk_list_overview'), ++ path('recent-activity', mlist.recent_activity, name='hk_list_recent_activity'), ++ path('recent-threads', mlist.overview_recent_threads, name='hk_list_overview_recent_threads'), ++ path('pop-threads', mlist.overview_pop_threads, name='hk_list_overview_pop_threads'), ++ path('top-threads', mlist.overview_top_threads, name='hk_list_overview_top_threads'), ++ path('favorites', mlist.overview_favorites, name='hk_list_overview_favorites'), ++ path('posted-to', mlist.overview_posted_to, name='hk_list_overview_posted_to'), ++ path('top-posters', mlist.overview_top_posters, name='hk_list_overview_top_posters'), ++ re_path(r'^export/(?P<filename>[^/]+)\.mbox.gz$', + mlist.export_mbox, name='hk_list_export_mbox'), +- url(r'delete/', mlist.delete, name='hk_list_delete'), +- url(r'feed/', check_mlist_private(MailingListFeed()), name='hk_list_feed'), ++ path('delete/', mlist.delete, name='hk_list_delete'), ++ path('feed/', check_mlist_private(MailingListFeed()), name='hk_list_feed'), + ] + + + # Messages + message_patterns = [ +- url(r'^$', message.index, name='hk_message_index'), +- url(r'^attachment/(?P<counter>\d+)/(?P<filename>.+)$', +- message.attachment, name='hk_message_attachment'), +- url(r'^vote$', message.vote, name='hk_message_vote'), +- url(r'^reply$', message.reply, name='hk_message_reply'), +- url(r'^delete$', message.delete, name='hk_message_delete'), ++ path('', message.index, name='hk_message_index'), ++ path('attachment/<int:counter>/<path:filename>', message.attachment, name='hk_message_attachment'), ++ path('vote', message.vote, name='hk_message_vote'), ++ path('reply', message.reply, name='hk_message_reply'), ++ path('delete', message.delete, name='hk_message_delete'), + ] + + + # Threads + thread_patterns = [ +- url(r'^$', thread.thread_index, name='hk_thread'), +- url(r'^replies$', thread.replies, name='hk_thread_replies'), +- url(r'^tags$', thread.tags, name='hk_tags'), +- url(r'^suggest-tags$', thread.suggest_tags, name='hk_suggest_tags'), +- url(r'^favorite$', thread.favorite, name='hk_favorite'), +- url(r'^category$', thread.set_category, name='hk_thread_set_category'), +- url(r'^reattach$', thread.reattach, name='hk_thread_reattach'), +- url(r'^reattach-suggest$', +- thread.reattach_suggest, name='hk_thread_reattach_suggest'), +- url(r'^delete$', message.delete, name='hk_thread_delete'), ++ path('', thread.thread_index, name='hk_thread'), ++ path('replies', thread.replies, name='hk_thread_replies'), ++ path('tags', thread.tags, name='hk_tags'), ++ path('suggest-tags', thread.suggest_tags, name='hk_suggest_tags'), ++ path('favorite', thread.favorite, name='hk_favorite'), ++ path('category', thread.set_category, name='hk_thread_set_category'), ++ path('reattach', thread.reattach, name='hk_thread_reattach'), ++ path('reattach-suggest', thread.reattach_suggest, name='hk_thread_reattach_suggest'), ++ path('delete', message.delete, name='hk_thread_delete'), + ] + + + # REST API + api_list_patterns = [ +- url(r'^$', +- api_mailinglist.MailingListDetail.as_view(), name="hk_api_mailinglist_detail"), +- url(r'^threads/$', +- api_thread.ThreadList.as_view(), name="hk_api_thread_list"), +- url(r'^thread/(?P<thread_id>[^/]+)/$', +- api_thread.ThreadDetail.as_view(), name="hk_api_thread_detail"), +- url(r'^emails/$', +- api_email.EmailList.as_view(), name="hk_api_email_list"), +- url(r'^email/(?P<message_id_hash>.*)/$', ++ path('', api_mailinglist.MailingListDetail.as_view(), name="hk_api_mailinglist_detail"), ++ path('threads/', api_thread.ThreadList.as_view(), name="hk_api_thread_list"), ++ path('thread/<str:thread_id>/', api_thread.ThreadDetail.as_view(), name="hk_api_thread_detail"), ++ path('emails/', api_email.EmailList.as_view(), name="hk_api_email_list"), ++ re_path(r'^email/(?P<message_id_hash>.*)/$', + api_email.EmailDetail.as_view(), name="hk_api_email_detail"), +- url(r'^thread/(?P<thread_id>[^/]+)/emails/$', +- api_email.EmailList.as_view(), name="hk_api_thread_email_list"), ++ path('thread/<str:thread_id>/emails/', api_email.EmailList.as_view(), name="hk_api_thread_email_list"), + ] + api_patterns = [ +- url(r'^$', TemplateView.as_view(template_name="hyperkitty/api.html")), +- url(r'^lists/$', +- api_mailinglist.MailingListList.as_view(), name="hk_api_mailinglist_list"), +- url(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/', include(api_list_patterns)), +- url(r'^sender/(?P<mailman_id>[^/]+)/emails/$', +- api_email.EmailListBySender.as_view(), name="hk_api_sender_email_list"), +- url(r'^tags/$', api_tag.TagList.as_view(), name="hk_api_tag_list"), ++ path('', TemplateView.as_view(template_name="hyperkitty/api.html")), ++ path('lists/', api_mailinglist.MailingListList.as_view(), name="hk_api_mailinglist_list"), ++ re_path(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/', include(api_list_patterns)), ++ path('sender/<str:mailman_id>/emails/', api_email.EmailListBySender.as_view(), name="hk_api_sender_email_list"), ++ path('tags/', api_tag.TagList.as_view(), name="hk_api_tag_list"), + ] + + + urlpatterns = [ + # Index +- url(r'^$', index.index, name='hk_root'), +- url(r'^find-list$', index.find_list, name='hk_find_list'), ++ path('', index.index, name='hk_root'), ++ path('find-list', index.find_list, name='hk_find_list'), + + # User profile +- url(r'^profile/', include([ +- url(r'^$', accounts.user_profile, name='hk_user_profile'), +- url(r'^favorites$', accounts.favorites, name='hk_user_favorites'), +- url(r'^last_views$', accounts.last_views, name='hk_user_last_views'), +- url(r'^votes$', accounts.votes, name='hk_user_votes'), +- url(r'^subscriptions$', accounts.subscriptions, ++ path('profile/', include([ ++ path('', accounts.user_profile, name='hk_user_profile'), ++ path('favorites', accounts.favorites, name='hk_user_favorites'), ++ path('last_views', accounts.last_views, name='hk_user_last_views'), ++ path('votes', accounts.votes, name='hk_user_votes'), ++ path('subscriptions', accounts.subscriptions, + name='hk_user_subscriptions'), + ])), + + # Users +- url(r'^users/$', users.users, name='hk_users_overview'), +- url(r'^users/(?P<user_id>[^/]+)/$', accounts.public_profile, name='hk_public_user_profile'), +- url(r'^users/(?P<user_id>[^/]+)/posts$', accounts.posts, name='hk_user_posts'), ++ path('users/', users.users, name='hk_users_overview'), ++ path('users/<str:user_id>/', accounts.public_profile, name='hk_public_user_profile'), ++ path('users/<str:user_id>/posts', accounts.posts, name='hk_user_posts'), + + # List archives and overview +- url(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/', include(list_patterns)), ++ re_path(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/', include(list_patterns)), + + # Messages +- url(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/message/' ++ re_path(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/message/' + r'(?P<message_id_hash>\w+)/', include(message_patterns)), +- url(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/message/new$', ++ re_path(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/message/new$', + message.new_message, name='hk_message_new'), + + # Threads +- url(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/thread/(?P<threadid>\w+)/', ++ re_path(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/thread/(?P<threadid>\w+)/', + include(thread_patterns)), + + # Search +- url(r'^search$', search.search, name='hk_search'), ++ path('search', search.search, name='hk_search'), + + # Categories and Tags +- url(r'^categories/$', categories.categories, name='hk_categories_overview'), +- url(r'^tags/$', tags.tags, name='hk_tags_overview'), ++ path('categories/', categories.categories, name='hk_categories_overview'), ++ path('tags/', tags.tags, name='hk_tags_overview'), + + # Mailman archiver API +- url(r'^api/mailman/urls$', mailman.urls, name='hk_mailman_urls'), +- url(r'^api/mailman/archive$', mailman.archive, name='hk_mailman_archive'), ++ path('api/mailman/urls', mailman.urls, name='hk_mailman_urls'), ++ path('api/mailman/archive', mailman.archive, name='hk_mailman_archive'), + + # REST API +- url(r'^api/', include(api_patterns)), ++ path('api/', include(api_patterns)), + + # Mailman 2.X compatibility +- url(r'^listinfo/?$', compat.summary), +- url(r'^listinfo/(?P<list_name>[^/]+)/?$', compat.summary), +- url(r'^pipermail/(?P<list_name>[^/]+)/?$', compat.summary), +- url(r'^pipermail/(?P<list_name>[^/]+)/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/?$', compat.arch_month), +- url(r'^pipermail/(?P<list_name>[^/]+)/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/(?P<summary_type>[a-z]+)\.html$', compat.arch_month), +- url(r'^pipermail/(?P<list_name>[^/]+)/(?P<year>\d\d\d\d)-(?P<month_name>\w+)\.txt.gz', compat.arch_month_mbox), ++ re_path(r'^listinfo/?$', compat.summary), ++ re_path(r'^listinfo/(?P<list_name>[^/]+)/?$', compat.summary), ++ re_path(r'^pipermail/(?P<list_name>[^/]+)/?$', compat.summary), ++ re_path(r'^pipermail/(?P<list_name>[^/]+)/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/?$', compat.arch_month), ++ re_path(r'^pipermail/(?P<list_name>[^/]+)/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/(?P<summary_type>[a-z]+)\.html$', compat.arch_month), ++ re_path(r'^pipermail/(?P<list_name>[^/]+)/(?P<year>\d\d\d\d)-(?P<month_name>\w+)\.txt.gz', compat.arch_month_mbox), + #url(r'^pipermail/(?P<list_name>[^/]+)/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/(?P<msg_num>\d+)\.html$', compat.message), +- url(r'^list/(?P<list_name>[^@]+)@[^/]+/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/?$', compat.arch_month), ++ re_path(r'^list/(?P<list_name>[^@]+)@[^/]+/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/?$', compat.arch_month), + #url(r'^list/(?P<list_name>[^@]+)@[^/]+/(?P<year>\d\d\d\d)-(?P<month_name>\w+)/(?P<msg_num>\d+)\.html$', compat.message), + + # URL compatibility with previous versions +- url(r'^list/(?P<list_id>[^@/]+)/', compat.redirect_list_id), +- url(r'^lists/', compat.redirect_lists), ++ re_path(r'^list/(?P<list_id>[^@/]+)/', compat.redirect_list_id), ++ path('lists/', compat.redirect_lists), + + ] + #) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +diff --git a/hyperkitty/views/mailman.py b/hyperkitty/views/mailman.py +index 285e4cd2..9b6dfb7e 100644 +--- a/hyperkitty/views/mailman.py ++++ b/hyperkitty/views/mailman.py +@@ -27,13 +27,12 @@ from email import message_from_binary_file + from email.message import EmailMessage + from email.policy import default + from functools import wraps +-from urllib.parse import urljoin ++from urllib.parse import unquote, urljoin + + from django.conf import settings + from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation + from django.http import HttpResponse + from django.urls import reverse +-from django.utils.http import urlunquote + from django.views.decorators.csrf import csrf_exempt + from django.views.decorators.http import require_POST + +@@ -134,7 +133,7 @@ def _get_url(mlist_fqdn, msg_id=None): + msg_hash = get_message_id_hash(msg_id.strip().strip("<>")) + url = reverse('hk_message_index', kwargs={ + "mlist_fqdn": mlist_fqdn, "message_id_hash": msg_hash}) +- relative_url = urlunquote(url) ++ relative_url = unquote(url) + mail_domain = mlist_fqdn.split("@")[1] + try: + domain = MailDomain.objects.get( +diff --git a/setup.py b/setup.py +index c16294b0..827cef0b 100755 +--- a/setup.py ++++ b/setup.py +@@ -37,7 +37,7 @@ with open('hyperkitty/__init__.py') as fp: + + # Requirements + REQUIRES = [ +- "django>=2.2,<3.3", ++ "django>=2.2,<4.1", + "django_mailman3>=1.3.7", + "django-gravatar2>=1.0.6", + "djangorestframework>=3.0.0", +-- +GitLab +
