diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 589f0d7a6..e77c33f93 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -131,6 +131,8 @@ jobs: python manage.py makemigrations --check --dry-run --settings tests.settings.${{ matrix.database }} - name: Run Tests + env: + PYTHONWARNINGS: 'always' run: | . ~/venv/bin/activate coverage run manage.py test --settings tests.settings.${{ matrix.database }} diff --git a/.gitignore b/.gitignore index dca0217fe..8c5e44045 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ !.coveragerc !.tx/config +build/ +*.egg-info + *_settings.py *.py[co] inyoka.xapdb/ diff --git a/docs/conf.py b/docs/conf.py index 51329712a..4dd145515 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -71,8 +71,8 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { - 'django': ('https://docs.djangoproject.com/en/2.2', - 'https://docs.djangoproject.com/en/2.2/_objects'), + 'django': ('https://docs.djangoproject.com/en/3.2', + 'https://docs.djangoproject.com/en/3.2/_objects'), 'python': ('https://docs.python.org/3', None), 'sphinx': ('https://www.sphinx-doc.org', None), } diff --git a/docs/settings.rst b/docs/settings.rst index 16fd13b6c..4afdac65f 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -18,7 +18,7 @@ Every configuration directive can be overridden by using a custom settings file $ export DJANGO_SETTINGS_MODULE="settings" Any settings variable that is shown in the `Django settings documentation -`_ can be used. +`_ can be used. The development, test and production configuration files should start with:: @@ -45,7 +45,7 @@ Generics } The caches that will be used by Inyoka and Django. See - https://docs.djangoproject.com/en/2.2/ref/settings/#caches + https://docs.djangoproject.com/en/3.2/ref/settings/#caches .. py:data:: DATABASES @@ -59,21 +59,21 @@ Generics } Defines the available databases. See - https://docs.djangoproject.com/en/2.2/ref/settings/#databases + https://docs.djangoproject.com/en/3.2/ref/settings/#databases .. py:data:: DEBUG Defaults to: ``False`` Enable or disable debugging. See - https://docs.djangoproject.com/en/2.2/ref/settings/#DEBUG + https://docs.djangoproject.com/en/3.2/ref/settings/#DEBUG .. py:data:: DEBUG_PROPAGATE_EXCEPTIONS Defaults to: ``False`` Enable or disable Django to push exceptions to a higher level. See - https://docs.djangoproject.com/en/2.2/ref/settings/#debug-propagate-exceptions + https://docs.djangoproject.com/en/3.2/ref/settings/#debug-propagate-exceptions .. py:data:: FILE_UPLOAD_HANDLERS @@ -85,7 +85,7 @@ Generics We only allow uploads via memory up to 2.5mb and do not stream into temporary files. See - https://docs.djangoproject.com/en/2.2/ref/settings/#file-upload-handlers + https://docs.djangoproject.com/en/3.2/ref/settings/#file-upload-handlers Installation settings @@ -287,7 +287,7 @@ Paths and URLs Defaults to: ``('~/inyoka/inyoka/locale',)`` - See https://docs.djangoproject.com/en/2.2/ref/settings/#locale-paths + See https://docs.djangoproject.com/en/3.2/ref/settings/#locale-paths .. seealso:: :py:data:`BASE_PATH` @@ -296,7 +296,7 @@ Paths and URLs Defaults to: ``'~/inyoka/inyoka/media'`` Absolute path to the directory that holds media and the URL. See - https://docs.djangoproject.com/en/2.2/ref/settings/#media-root + https://docs.djangoproject.com/en/3.2/ref/settings/#media-root .. seealso:: :py:data:`BASE_PATH` @@ -304,7 +304,7 @@ Paths and URLs Defaults to: ``'http://media.example.com'`` - See https://docs.djangoproject.com/en/2.2/ref/settings/#media-url + See https://docs.djangoproject.com/en/3.2/ref/settings/#media-url .. seealso:: :py:data:`BASE_DOMAIN_NAME` @@ -319,14 +319,14 @@ Paths and URLs Defaults to: ``'inyoka.portal.urls'`` This URL conf is used for contrib stuff like the auth system. See - https://docs.djangoproject.com/en/2.2/ref/settings/#root-urlconf + https://docs.djangoproject.com/en/3.2/ref/settings/#root-urlconf .. py:data:: SESSION_COOKIE_DOMAIN Defaults to: ``'.example.com'`` See - https://docs.djangoproject.com/en/2.2/ref/settings/#session-cookie-domain + https://docs.djangoproject.com/en/3.2/ref/settings/#session-cookie-domain .. seealso:: :py:data:`BASE_DOMAIN_NAME` @@ -334,7 +334,7 @@ Paths and URLs Defaults to: ``'~/inyoka/inyoka/static-collected'`` - See https://docs.djangoproject.com/en/2.2/ref/settings/#static-root + See https://docs.djangoproject.com/en/3.2/ref/settings/#static-root .. seealso:: :py:data:`BASE_PATH` @@ -342,7 +342,7 @@ Paths and URLs Defaults to: ``'http://static.example.com'`` - See https://docs.djangoproject.com/en/2.2/ref/settings/#static-url + See https://docs.djangoproject.com/en/3.2/ref/settings/#static-url .. seealso:: :py:data:`BASE_DOMAIN_NAME` @@ -354,7 +354,7 @@ Security Defaults to: ``None`` Make this unique, and don't share it with anybody. See - https://docs.djangoproject.com/en/2.2/ref/settings/#secret-key + https://docs.djangoproject.com/en/3.2/ref/settings/#secret-key .. .. py:data:: INTERNAL_IPS diff --git a/example_development_settings.py b/example_development_settings.py index 2f1d223f3..dd617036d 100644 --- a/example_development_settings.py +++ b/example_development_settings.py @@ -3,7 +3,7 @@ DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'ubuntuusers', 'USER': 'root', 'PASSWORD': '', diff --git a/extra/babel.cfg b/extra/babel.cfg index 7151fc054..92f622f99 100644 --- a/extra/babel.cfg +++ b/extra/babel.cfg @@ -1,3 +1,4 @@ +[django: **/templates/**.html] [python: **.py] [jinja2: **.html] fail_silently = False @@ -9,3 +10,4 @@ encoding = utf-8 [extractors] jinja2 = jinja2.ext:babel_extract +django = inyoka.locale.babel_django_templates:extract_django diff --git a/extra/requirements/linux-py3.9-development.txt b/extra/requirements/linux-py3.9-development.txt index 4705aafdb..c77a85e1b 100644 --- a/extra/requirements/linux-py3.9-development.txt +++ b/extra/requirements/linux-py3.9-development.txt @@ -20,6 +20,10 @@ amqp==5.1.1 \ --hash=sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2 \ --hash=sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359 # via kombu +asgiref==3.7.2 \ + --hash=sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e \ + --hash=sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed + # via django async-timeout==4.0.3 \ --hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \ --hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028 @@ -50,17 +54,17 @@ billiard==4.1.0 \ --hash=sha256:0f50d6be051c6b2b75bfbc8bfd85af195c5739c281d3f5b86a5640c65563614a \ --hash=sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5 # via celery -build==0.10.0 \ - --hash=sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171 \ - --hash=sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269 +build==1.0.3 \ + --hash=sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b \ + --hash=sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f # via pip-tools bump2version==1.0.1 \ --hash=sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410 \ --hash=sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6 # via Inyoka (setup.py) -celery==5.3.1 \ - --hash=sha256:27f8f3f3b58de6e0ab4f174791383bbd7445aff0471a43e99cfd77727940753f \ - --hash=sha256:f84d1c21a1520c116c2b7d26593926581191435a03aa74b77c941b93ca1c6210 +celery==5.3.4 \ + --hash=sha256:1e6ed40af72695464ce98ca2c201ad0ef8fd192246f6c9eac8bba343b980ad34 \ + --hash=sha256:9023df6a8962da79eb30c0c84d5f4863d9793a466354cc931d7f72423996de28 # via Inyoka (setup.py) certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ @@ -155,7 +159,9 @@ click==8.1.7 \ # click-didyoumean # click-plugins # click-repl + # django-codemod # pip-tools + # rich-click click-didyoumean==0.3.0 \ --hash=sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667 \ --hash=sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035 @@ -168,80 +174,84 @@ click-repl==0.3.0 \ --hash=sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9 \ --hash=sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812 # via celery -coverage==7.3.0 \ - --hash=sha256:07ea61bcb179f8f05ffd804d2732b09d23a1238642bf7e51dad62082b5019b34 \ - --hash=sha256:1084393c6bda8875c05e04fce5cfe1301a425f758eb012f010eab586f1f3905e \ - --hash=sha256:13c6cbbd5f31211d8fdb477f0f7b03438591bdd077054076eec362cf2207b4a7 \ - --hash=sha256:211a4576e984f96d9fce61766ffaed0115d5dab1419e4f63d6992b480c2bd60b \ - --hash=sha256:2d22172f938455c156e9af2612650f26cceea47dc86ca048fa4e0b2d21646ad3 \ - --hash=sha256:34f9f0763d5fa3035a315b69b428fe9c34d4fc2f615262d6be3d3bf3882fb985 \ - --hash=sha256:3558e5b574d62f9c46b76120a5c7c16c4612dc2644c3d48a9f4064a705eaee95 \ - --hash=sha256:36ce5d43a072a036f287029a55b5c6a0e9bd73db58961a273b6dc11a2c6eb9c2 \ - --hash=sha256:37d5576d35fcb765fca05654f66aa71e2808d4237d026e64ac8b397ffa66a56a \ - --hash=sha256:3c9834d5e3df9d2aba0275c9f67989c590e05732439b3318fa37a725dff51e74 \ - --hash=sha256:438856d3f8f1e27f8e79b5410ae56650732a0dcfa94e756df88c7e2d24851fcd \ - --hash=sha256:477c9430ad5d1b80b07f3c12f7120eef40bfbf849e9e7859e53b9c93b922d2af \ - --hash=sha256:49ab200acf891e3dde19e5aa4b0f35d12d8b4bd805dc0be8792270c71bd56c54 \ - --hash=sha256:49dbb19cdcafc130f597d9e04a29d0a032ceedf729e41b181f51cd170e6ee865 \ - --hash=sha256:4c8e31cf29b60859876474034a83f59a14381af50cbe8a9dbaadbf70adc4b214 \ - --hash=sha256:4eddd3153d02204f22aef0825409091a91bf2a20bce06fe0f638f5c19a85de54 \ - --hash=sha256:5247bab12f84a1d608213b96b8af0cbb30d090d705b6663ad794c2f2a5e5b9fe \ - --hash=sha256:5492a6ce3bdb15c6ad66cb68a0244854d9917478877a25671d70378bdc8562d0 \ - --hash=sha256:56afbf41fa4a7b27f6635bc4289050ac3ab7951b8a821bca46f5b024500e6321 \ - --hash=sha256:59777652e245bb1e300e620ce2bef0d341945842e4eb888c23a7f1d9e143c446 \ - --hash=sha256:60f64e2007c9144375dd0f480a54d6070f00bb1a28f65c408370544091c9bc9e \ - --hash=sha256:63c5b8ecbc3b3d5eb3a9d873dec60afc0cd5ff9d9f1c75981d8c31cfe4df8527 \ - --hash=sha256:68d8a0426b49c053013e631c0cdc09b952d857efa8f68121746b339912d27a12 \ - --hash=sha256:74c160285f2dfe0acf0f72d425f3e970b21b6de04157fc65adc9fd07ee44177f \ - --hash=sha256:7a9baf8e230f9621f8e1d00c580394a0aa328fdac0df2b3f8384387c44083c0f \ - --hash=sha256:7df91fb24c2edaabec4e0eee512ff3bc6ec20eb8dccac2e77001c1fe516c0c84 \ - --hash=sha256:7f297e0c1ae55300ff688568b04ff26b01c13dfbf4c9d2b7d0cb688ac60df479 \ - --hash=sha256:80501d1b2270d7e8daf1b64b895745c3e234289e00d5f0e30923e706f110334e \ - --hash=sha256:85b7335c22455ec12444cec0d600533a238d6439d8d709d545158c1208483873 \ - --hash=sha256:887665f00ea4e488501ba755a0e3c2cfd6278e846ada3185f42d391ef95e7e70 \ - --hash=sha256:8f39c49faf5344af36042b293ce05c0d9004270d811c7080610b3e713251c9b0 \ - --hash=sha256:90b6e2f0f66750c5a1178ffa9370dec6c508a8ca5265c42fbad3ccac210a7977 \ - --hash=sha256:96d7d761aea65b291a98c84e1250cd57b5b51726821a6f2f8df65db89363be51 \ - --hash=sha256:97af9554a799bd7c58c0179cc8dbf14aa7ab50e1fd5fa73f90b9b7215874ba28 \ - --hash=sha256:97c44f4ee13bce914272589b6b41165bbb650e48fdb7bd5493a38bde8de730a1 \ - --hash=sha256:a67e6bbe756ed458646e1ef2b0778591ed4d1fcd4b146fc3ba2feb1a7afd4254 \ - --hash=sha256:ac0dec90e7de0087d3d95fa0533e1d2d722dcc008bc7b60e1143402a04c117c1 \ - --hash=sha256:ad0f87826c4ebd3ef484502e79b39614e9c03a5d1510cfb623f4a4a051edc6fd \ - --hash=sha256:b3eb0c93e2ea6445b2173da48cb548364f8f65bf68f3d090404080d338e3a689 \ - --hash=sha256:b543302a3707245d454fc49b8ecd2c2d5982b50eb63f3535244fd79a4be0c99d \ - --hash=sha256:b859128a093f135b556b4765658d5d2e758e1fae3e7cc2f8c10f26fe7005e543 \ - --hash=sha256:bac329371d4c0d456e8d5f38a9b0816b446581b5f278474e416ea0c68c47dcd9 \ - --hash=sha256:c02cfa6c36144ab334d556989406837336c1d05215a9bdf44c0bc1d1ac1cb637 \ - --hash=sha256:c9737bc49a9255d78da085fa04f628a310c2332b187cd49b958b0e494c125071 \ - --hash=sha256:ccc51713b5581e12f93ccb9c5e39e8b5d4b16776d584c0f5e9e4e63381356482 \ - --hash=sha256:ce2ee86ca75f9f96072295c5ebb4ef2a43cecf2870b0ca5e7a1cbdd929cf67e1 \ - --hash=sha256:d000a739f9feed900381605a12a61f7aaced6beae832719ae0d15058a1e81c1b \ - --hash=sha256:db76a1bcb51f02b2007adacbed4c88b6dee75342c37b05d1822815eed19edee5 \ - --hash=sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a \ - --hash=sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393 \ - --hash=sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a \ - --hash=sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba +coverage==7.3.1 \ + --hash=sha256:025ded371f1ca280c035d91b43252adbb04d2aea4c7105252d3cbc227f03b375 \ + --hash=sha256:04312b036580ec505f2b77cbbdfb15137d5efdfade09156961f5277149f5e344 \ + --hash=sha256:0575c37e207bb9b98b6cf72fdaaa18ac909fb3d153083400c2d48e2e6d28bd8e \ + --hash=sha256:07d156269718670d00a3b06db2288b48527fc5f36859425ff7cec07c6b367745 \ + --hash=sha256:1f111a7d85658ea52ffad7084088277135ec5f368457275fc57f11cebb15607f \ + --hash=sha256:220eb51f5fb38dfdb7e5d54284ca4d0cd70ddac047d750111a68ab1798945194 \ + --hash=sha256:229c0dd2ccf956bf5aeede7e3131ca48b65beacde2029f0361b54bf93d36f45a \ + --hash=sha256:245c5a99254e83875c7fed8b8b2536f040997a9b76ac4c1da5bff398c06e860f \ + --hash=sha256:2829c65c8faaf55b868ed7af3c7477b76b1c6ebeee99a28f59a2cb5907a45760 \ + --hash=sha256:4aba512a15a3e1e4fdbfed2f5392ec221434a614cc68100ca99dcad7af29f3f8 \ + --hash=sha256:4c96dd7798d83b960afc6c1feb9e5af537fc4908852ef025600374ff1a017392 \ + --hash=sha256:50dd1e2dd13dbbd856ffef69196781edff26c800a74f070d3b3e3389cab2600d \ + --hash=sha256:5289490dd1c3bb86de4730a92261ae66ea8d44b79ed3cc26464f4c2cde581fbc \ + --hash=sha256:53669b79f3d599da95a0afbef039ac0fadbb236532feb042c534fbb81b1a4e40 \ + --hash=sha256:553d7094cb27db58ea91332e8b5681bac107e7242c23f7629ab1316ee73c4981 \ + --hash=sha256:586649ada7cf139445da386ab6f8ef00e6172f11a939fc3b2b7e7c9082052fa0 \ + --hash=sha256:5ae4c6da8b3d123500f9525b50bf0168023313963e0e2e814badf9000dd6ef92 \ + --hash=sha256:5b4ee7080878077af0afa7238df1b967f00dc10763f6e1b66f5cced4abebb0a3 \ + --hash=sha256:5d991e13ad2ed3aced177f524e4d670f304c8233edad3210e02c465351f785a0 \ + --hash=sha256:614f1f98b84eb256e4f35e726bfe5ca82349f8dfa576faabf8a49ca09e630086 \ + --hash=sha256:636a8ac0b044cfeccae76a36f3b18264edcc810a76a49884b96dd744613ec0b7 \ + --hash=sha256:6407424621f40205bbe6325686417e5e552f6b2dba3535dd1f90afc88a61d465 \ + --hash=sha256:6bc6f3f4692d806831c136c5acad5ccedd0262aa44c087c46b7101c77e139140 \ + --hash=sha256:6cb7fe1581deb67b782c153136541e20901aa312ceedaf1467dcb35255787952 \ + --hash=sha256:74bb470399dc1989b535cb41f5ca7ab2af561e40def22d7e188e0a445e7639e3 \ + --hash=sha256:75c8f0df9dfd8ff745bccff75867d63ef336e57cc22b2908ee725cc552689ec8 \ + --hash=sha256:770f143980cc16eb601ccfd571846e89a5fe4c03b4193f2e485268f224ab602f \ + --hash=sha256:7eb0b188f30e41ddd659a529e385470aa6782f3b412f860ce22b2491c89b8593 \ + --hash=sha256:7eb3cd48d54b9bd0e73026dedce44773214064be93611deab0b6a43158c3d5a0 \ + --hash=sha256:87d38444efffd5b056fcc026c1e8d862191881143c3aa80bb11fcf9dca9ae204 \ + --hash=sha256:8a07b692129b8a14ad7a37941a3029c291254feb7a4237f245cfae2de78de037 \ + --hash=sha256:966f10df9b2b2115da87f50f6a248e313c72a668248be1b9060ce935c871f276 \ + --hash=sha256:a6191b3a6ad3e09b6cfd75b45c6aeeffe7e3b0ad46b268345d159b8df8d835f9 \ + --hash=sha256:aab8e9464c00da5cb9c536150b7fbcd8850d376d1151741dd0d16dfe1ba4fd26 \ + --hash=sha256:ac3c5b7e75acac31e490b7851595212ed951889918d398b7afa12736c85e13ce \ + --hash=sha256:ac9ad38204887349853d7c313f53a7b1c210ce138c73859e925bc4e5d8fc18e7 \ + --hash=sha256:b9c0c19f70d30219113b18fe07e372b244fb2a773d4afde29d5a2f7930765136 \ + --hash=sha256:c397c70cd20f6df7d2a52283857af622d5f23300c4ca8e5bd8c7a543825baa5a \ + --hash=sha256:c6601a60318f9c3945be6ea0f2a80571f4299b6801716f8a6e4846892737ebe4 \ + --hash=sha256:c6f55d38818ca9596dc9019eae19a47410d5322408140d9a0076001a3dcb938c \ + --hash=sha256:ca70466ca3a17460e8fc9cea7123c8cbef5ada4be3140a1ef8f7b63f2f37108f \ + --hash=sha256:ca833941ec701fda15414be400c3259479bfde7ae6d806b69e63b3dc423b1832 \ + --hash=sha256:cd0f7429ecfd1ff597389907045ff209c8fdb5b013d38cfa7c60728cb484b6e3 \ + --hash=sha256:cd694e19c031733e446c8024dedd12a00cda87e1c10bd7b8539a87963685e969 \ + --hash=sha256:cdd088c00c39a27cfa5329349cc763a48761fdc785879220d54eb785c8a38520 \ + --hash=sha256:de30c1aa80f30af0f6b2058a91505ea6e36d6535d437520067f525f7df123887 \ + --hash=sha256:defbbb51121189722420a208957e26e49809feafca6afeef325df66c39c4fdb3 \ + --hash=sha256:f09195dda68d94a53123883de75bb97b0e35f5f6f9f3aa5bf6e496da718f0cb6 \ + --hash=sha256:f12d8b11a54f32688b165fd1a788c408f927b0960984b899be7e4c190ae758f1 \ + --hash=sha256:f1a317fdf5c122ad642db8a97964733ab7c3cf6009e1a8ae8821089993f175ff \ + --hash=sha256:f2781fd3cabc28278dc982a352f50c81c09a1a500cc2086dc4249853ea96b981 \ + --hash=sha256:f4f456590eefb6e1b3c9ea6328c1e9fa0f1006e7481179d749b3376fc793478e # via Inyoka (setup.py) defusedxml==0.7.1 \ --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 # via Inyoka (setup.py) -django==2.2.28 \ - --hash=sha256:0200b657afbf1bc08003845ddda053c7641b9b24951e52acd51f6abda33a7413 \ - --hash=sha256:365429d07c1336eb42ba15aa79f45e1c13a0b04d5c21569e7d596696418a6a45 +django==3.2.21 \ + --hash=sha256:a5de4c484e7b7418e6d3e52a5b8794f0e6b9f9e4ce3c037018cf1c489fa87f3c \ + --hash=sha256:d31b06c58aa2cd73998ca5966bc3001243d3c4e77ee2d0c479bced124765fd99 # via # Inyoka (setup.py) # django-debug-toolbar # django-filter # django-guardian # django-redis -django-debug-toolbar==3.2.4 \ - --hash=sha256:644bbd5c428d3283aa9115722471769cac1bec189edf3a0c855fd8ff870375a9 \ - --hash=sha256:6b633b6cfee24f232d73569870f19aa86c819d750e7f3e833f2344a9eb4b4409 +django-codemod==2.1.1 \ + --hash=sha256:a6f45fdf2d88ae9d6e1b92302b8f2bd38840ccd6283a634f17bf00175e9599c9 \ + --hash=sha256:abf7412550c7264c0e883f466720180c4f71efc6ce5e59b9d3e827bc1ff8fed7 # via Inyoka (setup.py) -django-filter==21.1 \ - --hash=sha256:632a251fa8f1aadb4b8cceff932bb52fe2f826dd7dfe7f3eac40e5c463d6836e \ - --hash=sha256:f4a6737a30104c98d2e2a5fb93043f36dd7978e0c7ddc92f5998e85433ea5063 +django-debug-toolbar==4.2.0 \ + --hash=sha256:af99128c06e8e794479e65ab62cc6c7d1e74e1c19beb44dcbf9bad7a9c017327 \ + --hash=sha256:bc7fdaafafcdedefcc67a4a5ad9dac96efd6e41db15bc74d402a54a2ba4854dc + # via Inyoka (setup.py) +django-filter==23.3 \ + --hash=sha256:015fe155582e1805b40629344e4a6cf3cc40450827d294d040b4b8c1749a9fa6 \ + --hash=sha256:65bc5d1d8f4fff3aaf74cb5da537b6620e9214fb4b3180f6c560776b1b6dccd0 # via Inyoka (setup.py) django-guardian==2.4.0 \ --hash=sha256:440ca61358427e575323648b25f8384739e54c38b3d655c81d75e0cd0d61b697 \ @@ -251,9 +261,13 @@ django-hosts==5.2 \ --hash=sha256:32be764dbb0714878a1e6ba5c771418946eb0a17079a14f12e1afa90f182f191 \ --hash=sha256:cc4128b3020f059faaad6adb0f8a6784a72b74f979ef2c0d640677d872422dbe # via Inyoka (setup.py) -django-redis==5.2.0 \ - --hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \ - --hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de +django-redis==5.3.0 \ + --hash=sha256:2d8660d39f586c41c9907d5395693c477434141690fd7eca9d32376af00b0aac \ + --hash=sha256:8bc5793ec06b28ea802aad85ec437e7646511d4e571e07ccad19cfed8b9ddd44 + # via Inyoka (setup.py) +django-upgrade==1.14.1 \ + --hash=sha256:23813464e94713e1c660ba46b0fe53b2f490fdd6263da9f22a4ae5402a4d5d31 \ + --hash=sha256:8972e2aaa4be81da629dcabc2a784ad436a82a761f9a0ffd46e5ed6b9d155dfa # via Inyoka (setup.py) docutils==0.18.1 \ --hash=sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c \ @@ -291,9 +305,9 @@ html5lib==1.1 \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f # via Inyoka (setup.py) -icalendar==5.0.7 \ - --hash=sha256:18ad51f9d1741d33795ddaf5c886c59f6575f287d30e5a145c2d42ef72910c7f \ - --hash=sha256:e306014a64dc4dcf638da0acb2487ee4ada57b871b03a62ed7b513dfc135655c +icalendar==5.0.8 \ + --hash=sha256:405c84f88bba535e9bb89acf51453d4e5d93dab959a1d561b951996438e44afb \ + --hash=sha256:6c69ebdaf290c1eed64cfc601e4385c9c7b26a725c7e21ee9a0e70637d1ddb8b # via Inyoka (setup.py) idna==3.4 \ --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ @@ -308,7 +322,9 @@ imagesize==1.4.1 \ importlib-metadata==6.8.0 \ --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743 - # via sphinx + # via + # build + # sphinx isort==5.12.0 \ --hash=sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504 \ --hash=sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6 @@ -319,10 +335,42 @@ jinja2==3.1.2 \ # via # Inyoka (setup.py) # sphinx -kombu==5.3.1 \ - --hash=sha256:48ee589e8833126fd01ceaa08f8a2041334e9f5894e5763c8486a550454551e9 \ - --hash=sha256:fbd7572d92c0bf71c112a6b45163153dea5a7b6a701ec16b568c27d0fd2370f2 +kombu==5.3.2 \ + --hash=sha256:0ba213f630a2cb2772728aef56ac6883dc3a2f13435e10048f6e97d48506dbbd \ + --hash=sha256:b753c9cfc9b1e976e637a7cbc1a65d446a22e45546cd996ea28f932082b7dc9e # via celery +libcst==1.0.1 \ + --hash=sha256:0138068baf09561268c7f079373bda45f0e2b606d2d19df1307ca8a5134fc465 \ + --hash=sha256:119ba709f1dcb785a4458cf36cedb51d6f9cb2eec0acd7bb171f730eac7cb6ce \ + --hash=sha256:1adcfa7cafb6a0d39a1a0bec541355608038b45815e0c5019c95f91921d42884 \ + --hash=sha256:37187337f979ba426d8bfefc08008c3c1b09b9e9f9387050804ed2da88107570 \ + --hash=sha256:414350df5e334ddf0db1732d63da44e81b734d45abe1c597b5e5c0dd46aa4156 \ + --hash=sha256:440887e5f82efb299f2e98d4bfa5663851a878cfc0efed652ab8c50205191436 \ + --hash=sha256:47dba43855e9c7b06d8b256ee81f0ebec6a4f43605456519577e09dfe4b4288c \ + --hash=sha256:4840a3de701778f0a19582bb3085c61591329153f801dc25da84689a3733960b \ + --hash=sha256:4b4e336f6d68456017671cdda8ddebf9caebce8052cc21a3f494b03d7bd28386 \ + --hash=sha256:5599166d5fec40e18601fb8868519dde99f77b6e4ad6074958018f9545da7abd \ + --hash=sha256:5e3293e77657ba62533553bb9f0c5fb173780e164c65db1ea2a3e0d03944a284 \ + --hash=sha256:600c4d3a9a2f75d5a055fed713a5a4d812709947909610aa6527abe08a31896f \ + --hash=sha256:6caa33430c0c7a0fcad921b0deeec61ddb96796b6f88dca94966f6db62065f4f \ + --hash=sha256:80423311f09fc5fc3270ede44d30d9d8d3c2d3dd50dbf703a581ca7346949fa6 \ + --hash=sha256:8420926791b0b6206cb831a7ec73d26ae820e65bdf07ce9813c7754c7722c07a \ + --hash=sha256:8c50541c3fd6b1d5a3765c4bb5ee8ecbba9d0e798e48f79fd5adf3b6752de4d0 \ + --hash=sha256:8d31ce2790eab59c1bd8e33fe72d09cfc78635c145bdc3f08296b360abb5f443 \ + --hash=sha256:967c66fabd52102954207bf1541312b467afc210fdf7033f32da992fb6c2372c \ + --hash=sha256:9a4931feceab171e6fce73de94e13880424367247dad6ff2b49cabfec733e144 \ + --hash=sha256:9d6dec2a3c443792e6af7c36fadc256e4ea586214c76b52f0d18118811dbe351 \ + --hash=sha256:a6b5aea04c35e13109edad3cf83bc6dcd74309b150a781d2189eecb288b73a87 \ + --hash=sha256:ae49dcbfadefb82e830d41d9f0a1db0af3b771224768f431f1b7b3a9803ed7e3 \ + --hash=sha256:ae7f4e71d714f256b5f2ff98b5a9effba0f9dff4d779d8f35d7eb157bef78f59 \ + --hash=sha256:b0533de4e35396c61aeb3a6266ac30369a855910c2385aaa902ff4aabd60d409 \ + --hash=sha256:b666a605f4205c8357696f3b6571a38f6a8537cdcbb8f357587d35168298af34 \ + --hash=sha256:b97f652b15c50e91df411a9c8d5e6f75882b30743a49b387dcedd3f68ed94d75 \ + --hash=sha256:c90c74a8a314f0774f045122323fb60bacba79cbf5f71883c0848ecd67179541 \ + --hash=sha256:d237e9164a43caa7d6765ee560412264484e7620c546a2ee10a8d01bd56884e0 \ + --hash=sha256:ddd4e0eeec499d1c824ab545e62e957dbbd69a16bc4273208817638eb7d6b3c6 \ + --hash=sha256:f2cb687e1514625e91024e50a5d2e485c0ad3be24f199874ebf32b5de0346150 + # via django-codemod lxml==4.9.3 \ --hash=sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3 \ --hash=sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d \ @@ -417,13 +465,20 @@ lxml==4.9.3 \ --hash=sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7 \ --hash=sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4 # via Inyoka (setup.py) +markdown-it-py==3.0.0 \ + --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ + --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb + # via rich markupsafe==2.1.3 \ --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \ --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \ + --hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \ --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \ --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \ + --hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \ + --hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \ --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \ --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \ --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \ @@ -431,6 +486,7 @@ markupsafe==2.1.3 \ --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \ --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \ --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \ + --hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \ --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \ --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \ --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \ @@ -439,6 +495,7 @@ markupsafe==2.1.3 \ --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \ --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \ --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \ + --hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \ --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \ --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \ --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \ @@ -446,9 +503,12 @@ markupsafe==2.1.3 \ --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \ --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \ --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \ + --hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \ --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \ --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \ + --hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \ --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \ + --hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \ --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \ --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \ --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \ @@ -467,12 +527,22 @@ markupsafe==2.1.3 \ --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \ --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ - --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 + --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \ + --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \ + --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11 # via jinja2 mccabe==0.6.1 \ --hash=sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42 \ --hash=sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f # via flake8 +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +mypy-extensions==1.0.0 \ + --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ + --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 + # via typing-inspect outcome==1.2.0 \ --hash=sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672 \ --hash=sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5 @@ -494,71 +564,73 @@ parse-type==0.6.2 \ --hash=sha256:06d39a8b70fde873eb2a131141a0e79bb34a432941fb3d66fad247abafc9766c \ --hash=sha256:79b1f2497060d0928bc46016793f1fca1057c4aacdf15ef876aa48d75a73a355 # via behave -pillow==10.0.0 \ - --hash=sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5 \ - --hash=sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530 \ - --hash=sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d \ - --hash=sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca \ - --hash=sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891 \ - --hash=sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992 \ - --hash=sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7 \ - --hash=sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3 \ - --hash=sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba \ - --hash=sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3 \ - --hash=sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3 \ - --hash=sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f \ - --hash=sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538 \ - --hash=sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 \ - --hash=sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d \ - --hash=sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c \ - --hash=sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017 \ - --hash=sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3 \ - --hash=sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223 \ - --hash=sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e \ - --hash=sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3 \ - --hash=sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6 \ - --hash=sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640 \ - --hash=sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334 \ - --hash=sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1 \ - --hash=sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba \ - --hash=sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa \ - --hash=sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0 \ - --hash=sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396 \ - --hash=sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d \ - --hash=sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 \ - --hash=sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf \ - --hash=sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43 \ - --hash=sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37 \ - --hash=sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2 \ - --hash=sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd \ - --hash=sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86 \ - --hash=sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967 \ - --hash=sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 \ - --hash=sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568 \ - --hash=sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed \ - --hash=sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f \ - --hash=sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551 \ - --hash=sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3 \ - --hash=sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614 \ - --hash=sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff \ - --hash=sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d \ - --hash=sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883 \ - --hash=sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684 \ - --hash=sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0 \ - --hash=sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de \ - --hash=sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b \ - --hash=sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3 \ - --hash=sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199 \ - --hash=sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51 \ - --hash=sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90 +pathspec==0.11.2 \ + --hash=sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20 \ + --hash=sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3 + # via django-codemod +pillow==10.0.1 \ + --hash=sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff \ + --hash=sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f \ + --hash=sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21 \ + --hash=sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635 \ + --hash=sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a \ + --hash=sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f \ + --hash=sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1 \ + --hash=sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d \ + --hash=sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db \ + --hash=sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849 \ + --hash=sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7 \ + --hash=sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876 \ + --hash=sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3 \ + --hash=sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317 \ + --hash=sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91 \ + --hash=sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d \ + --hash=sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b \ + --hash=sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd \ + --hash=sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed \ + --hash=sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500 \ + --hash=sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7 \ + --hash=sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a \ + --hash=sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a \ + --hash=sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0 \ + --hash=sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf \ + --hash=sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f \ + --hash=sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1 \ + --hash=sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088 \ + --hash=sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971 \ + --hash=sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a \ + --hash=sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205 \ + --hash=sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54 \ + --hash=sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08 \ + --hash=sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21 \ + --hash=sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d \ + --hash=sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08 \ + --hash=sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e \ + --hash=sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf \ + --hash=sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b \ + --hash=sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145 \ + --hash=sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2 \ + --hash=sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d \ + --hash=sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d \ + --hash=sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf \ + --hash=sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad \ + --hash=sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d \ + --hash=sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1 \ + --hash=sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4 \ + --hash=sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2 \ + --hash=sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19 \ + --hash=sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37 \ + --hash=sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4 \ + --hash=sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68 \ + --hash=sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1 # via Inyoka (setup.py) pip-tools==7.3.0 \ --hash=sha256:8717693288720a8c6ebd07149c93ab0be1fced0b5191df9e9decd3263e20d85e \ --hash=sha256:8e9c99127fe024c025b46a0b2d15c7bd47f18f33226cf7330d35493663fc1d1d # via Inyoka (setup.py) -pluggy==1.2.0 \ - --hash=sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849 \ - --hash=sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3 +pluggy==1.3.0 \ + --hash=sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12 \ + --hash=sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7 # via allure-python-commons prompt-toolkit==3.0.39 \ --hash=sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac \ @@ -590,6 +662,7 @@ pygments==2.16.1 \ --hash=sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29 # via # Inyoka (setup.py) + # rich # sphinx pyproject-hooks==1.0.0 \ --hash=sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8 \ @@ -612,15 +685,17 @@ python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 # via Inyoka (setup.py) -pytz==2023.3 \ - --hash=sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588 \ - --hash=sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb +pytz==2023.3.post1 \ + --hash=sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b \ + --hash=sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7 # via # Inyoka (setup.py) # django # icalendar pyyaml==6.0.1 \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ @@ -628,7 +703,10 @@ pyyaml==6.0.1 \ --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ @@ -636,9 +714,12 @@ pyyaml==6.0.1 \ --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ @@ -653,14 +734,18 @@ pyyaml==6.0.1 \ --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f - # via responses + # via + # libcst + # responses pyzmq==25.1.1 \ --hash=sha256:019e59ef5c5256a2c7378f2fb8560fc2a9ff1d315755204295b2eab96b254d0a \ --hash=sha256:034239843541ef7a1aee0c7b2cb7f6aafffb005ede965ae9cbd49d5ff4ff73cf \ @@ -756,9 +841,9 @@ pyzmq==25.1.1 \ --hash=sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7 \ --hash=sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4 # via Inyoka (setup.py) -redis==5.0.0 \ - --hash=sha256:06570d0b2d84d46c21defc550afbaada381af82f5b83e5b3777600e05d8e2ed0 \ - --hash=sha256:5cea6c0d335c9a7332a460ed8729ceabb4d0c489c7285b0a86dbbf8a017bd120 +redis==4.6.0 \ + --hash=sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d \ + --hash=sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c # via # celery # django-redis @@ -773,13 +858,23 @@ responses==0.23.3 \ --hash=sha256:205029e1cb334c21cb4ec64fc7599be48b859a0fd381a42443cdd600bfe8b16a \ --hash=sha256:e6fbcf5d82172fecc0aa1860fd91e58cbfd96cee5e96da5b63fa6eb3caa10dd3 # via Inyoka (setup.py) -selenium==4.11.2 \ - --hash=sha256:98e72117b194b3fa9c69b48998f44bf7dd4152c7bd98544911a1753b9f03cc7d \ - --hash=sha256:9f9a5ed586280a3594f7461eb1d9dab3eac9d91e28572f365e9b98d9d03e02b5 +rich==13.5.3 \ + --hash=sha256:87b43e0543149efa1253f485cd845bb7ee54df16c9617b8a893650ab84b4acb6 \ + --hash=sha256:9257b468badc3d347e146a4faa268ff229039d4c2d176ab0cffb4c4fbc73d5d9 + # via + # django-codemod + # rich-click +rich-click==1.6.1 \ + --hash=sha256:0fcf4d1a09029d79322dd814ab0b2e66ac183633037561881d45abae8a161d95 \ + --hash=sha256:f8ff96693ec6e261d1544e9f7d9a5811c5ef5d74c8adb4978430fc0dac16777e + # via django-codemod +selenium==4.12.0 \ + --hash=sha256:95be6aa449a0ab4ac1198bb9de71bbe9170405e04b9752f4b450dc7292a21828 \ + --hash=sha256:b2c48b1440db54a0653300d9955f5421390723d53b36ec835e18de8e13bbd401 # via Inyoka (setup.py) -sentry-sdk==1.29.2 \ - --hash=sha256:3e17215d8006612e2df02b0e73115eb8376c37e3f586d8436fa41644e605074d \ - --hash=sha256:a99ee105384788c3f228726a88baf515fe7b5f1d2d0f215a03d194369f158df7 +sentry-sdk==1.31.0 \ + --hash=sha256:64a7141005fb775b9db298a30de93e3b83e0ddd1232dc6f36eb38aebc1553291 \ + --hash=sha256:6de2e88304873484207fed836388e422aeff000609b104c802749fd89d56ba5b # via Inyoka (setup.py) sgmllib3k==1.0.0 \ --hash=sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9 @@ -805,9 +900,9 @@ sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ --hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 # via trio -sphinx==7.2.3 \ - --hash=sha256:6379ea22c49955a44ed4e62bde8c94575e9544303cc0554eaa97099ae5853a3a \ - --hash=sha256:ece68bb4d77b7dc090573825db45a6f9183e74098d1c21573485de250b1d1e3f +sphinx==7.2.6 \ + --hash=sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560 \ + --hash=sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5 # via # Inyoka (setup.py) # sphinx-rtd-theme @@ -855,6 +950,10 @@ sqlparse==0.4.4 \ # via # django # django-debug-toolbar +tokenize-rt==5.2.0 \ + --hash=sha256:9fe80f8a5c1edad2d3ede0f37481cc0cc1538a2f442c9c2f9e4feacd2792d054 \ + --hash=sha256:b79d41a65cfec71285433511b50271b05da3584a1da144a0752e9c621a285289 + # via django-upgrade tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f @@ -872,18 +971,26 @@ trio==0.22.2 \ # via # selenium # trio-websocket -trio-websocket==0.10.3 \ - --hash=sha256:1a748604ad906a7dcab9a43c6eb5681e37de4793ba0847ef0bc9486933ed027b \ - --hash=sha256:a9937d48e8132ebf833019efde2a52ca82d223a30a7ea3e8d60a7d28f75a4e3a +trio-websocket==0.10.4 \ + --hash=sha256:c7a620c4013c34b7e4477d89fe76695da1e455e4510a8d7ae13f81c632bdce1d \ + --hash=sha256:e66b3db3e2453017431dfbd352081006654e1241c2a6800dc2f43d7df54d55c5 # via selenium types-pyyaml==6.0.12.11 \ --hash=sha256:7d340b19ca28cddfdba438ee638cd4084bde213e501a3978738543e27094775b \ --hash=sha256:a461508f3096d1d5810ec5ab95d7eeecb651f3a15b71959999988942063bf01d # via responses -typing-extensions==4.7.1 \ - --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ - --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 - # via kombu +typing-extensions==4.8.0 \ + --hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \ + --hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef + # via + # asgiref + # kombu + # libcst + # typing-inspect +typing-inspect==0.9.0 \ + --hash=sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f \ + --hash=sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78 + # via libcst tzdata==2023.3 \ --hash=sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a \ --hash=sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda @@ -924,9 +1031,9 @@ wsproto==1.2.0 \ --hash=sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065 \ --hash=sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736 # via trio-websocket -zipp==3.16.2 \ - --hash=sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0 \ - --hash=sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147 +zipp==3.17.0 \ + --hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \ + --hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: @@ -934,7 +1041,7 @@ pip==23.2.1 \ --hash=sha256:7ccf472345f20d35bdc9d1841ff5f313260c2c33fe417f48c30ac46cccabf5be \ --hash=sha256:fb0bd5435b3200c602b5bf61d2d43c2f13c02e29c1707567ae7fbc514eb9faf2 # via pip-tools -setuptools==68.1.2 \ - --hash=sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d \ - --hash=sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b +setuptools==68.2.2 \ + --hash=sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87 \ + --hash=sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a # via pip-tools diff --git a/extra/requirements/linux-py3.9-production.txt b/extra/requirements/linux-py3.9-production.txt index c4dc4bf5a..2c23468bd 100644 --- a/extra/requirements/linux-py3.9-production.txt +++ b/extra/requirements/linux-py3.9-production.txt @@ -8,6 +8,10 @@ amqp==5.1.1 \ --hash=sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2 \ --hash=sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359 # via kombu +asgiref==3.7.2 \ + --hash=sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e \ + --hash=sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed + # via django async-timeout==4.0.3 \ --hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \ --hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028 @@ -25,13 +29,13 @@ billiard==4.1.0 \ --hash=sha256:0f50d6be051c6b2b75bfbc8bfd85af195c5739c281d3f5b86a5640c65563614a \ --hash=sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5 # via celery -build==0.10.0 \ - --hash=sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171 \ - --hash=sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269 +build==1.0.3 \ + --hash=sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b \ + --hash=sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f # via pip-tools -celery==5.3.1 \ - --hash=sha256:27f8f3f3b58de6e0ab4f174791383bbd7445aff0471a43e99cfd77727940753f \ - --hash=sha256:f84d1c21a1520c116c2b7d26593926581191435a03aa74b77c941b93ca1c6210 +celery==5.3.4 \ + --hash=sha256:1e6ed40af72695464ce98ca2c201ad0ef8fd192246f6c9eac8bba343b980ad34 \ + --hash=sha256:9023df6a8962da79eb30c0c84d5f4863d9793a466354cc931d7f72423996de28 # via Inyoka (setup.py) certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ @@ -142,17 +146,17 @@ defusedxml==0.7.1 \ --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 # via Inyoka (setup.py) -django==2.2.28 \ - --hash=sha256:0200b657afbf1bc08003845ddda053c7641b9b24951e52acd51f6abda33a7413 \ - --hash=sha256:365429d07c1336eb42ba15aa79f45e1c13a0b04d5c21569e7d596696418a6a45 +django==3.2.21 \ + --hash=sha256:a5de4c484e7b7418e6d3e52a5b8794f0e6b9f9e4ce3c037018cf1c489fa87f3c \ + --hash=sha256:d31b06c58aa2cd73998ca5966bc3001243d3c4e77ee2d0c479bced124765fd99 # via # Inyoka (setup.py) # django-filter # django-guardian # django-redis -django-filter==21.1 \ - --hash=sha256:632a251fa8f1aadb4b8cceff932bb52fe2f826dd7dfe7f3eac40e5c463d6836e \ - --hash=sha256:f4a6737a30104c98d2e2a5fb93043f36dd7978e0c7ddc92f5998e85433ea5063 +django-filter==23.3 \ + --hash=sha256:015fe155582e1805b40629344e4a6cf3cc40450827d294d040b4b8c1749a9fa6 \ + --hash=sha256:65bc5d1d8f4fff3aaf74cb5da537b6620e9214fb4b3180f6c560776b1b6dccd0 # via Inyoka (setup.py) django-guardian==2.4.0 \ --hash=sha256:440ca61358427e575323648b25f8384739e54c38b3d655c81d75e0cd0d61b697 \ @@ -162,9 +166,9 @@ django-hosts==5.2 \ --hash=sha256:32be764dbb0714878a1e6ba5c771418946eb0a17079a14f12e1afa90f182f191 \ --hash=sha256:cc4128b3020f059faaad6adb0f8a6784a72b74f979ef2c0d640677d872422dbe # via Inyoka (setup.py) -django-redis==5.2.0 \ - --hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \ - --hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de +django-redis==5.3.0 \ + --hash=sha256:2d8660d39f586c41c9907d5395693c477434141690fd7eca9d32376af00b0aac \ + --hash=sha256:8bc5793ec06b28ea802aad85ec437e7646511d4e571e07ccad19cfed8b9ddd44 # via Inyoka (setup.py) feedparser==6.0.10 \ --hash=sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51 \ @@ -178,21 +182,25 @@ html5lib==1.1 \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f # via Inyoka (setup.py) -icalendar==5.0.7 \ - --hash=sha256:18ad51f9d1741d33795ddaf5c886c59f6575f287d30e5a145c2d42ef72910c7f \ - --hash=sha256:e306014a64dc4dcf638da0acb2487ee4ada57b871b03a62ed7b513dfc135655c +icalendar==5.0.8 \ + --hash=sha256:405c84f88bba535e9bb89acf51453d4e5d93dab959a1d561b951996438e44afb \ + --hash=sha256:6c69ebdaf290c1eed64cfc601e4385c9c7b26a725c7e21ee9a0e70637d1ddb8b # via Inyoka (setup.py) idna==3.4 \ --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 # via requests +importlib-metadata==6.8.0 \ + --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ + --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743 + # via build jinja2==3.1.2 \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 # via Inyoka (setup.py) -kombu==5.3.1 \ - --hash=sha256:48ee589e8833126fd01ceaa08f8a2041334e9f5894e5763c8486a550454551e9 \ - --hash=sha256:fbd7572d92c0bf71c112a6b45163153dea5a7b6a701ec16b568c27d0fd2370f2 +kombu==5.3.2 \ + --hash=sha256:0ba213f630a2cb2772728aef56ac6883dc3a2f13435e10048f6e97d48506dbbd \ + --hash=sha256:b753c9cfc9b1e976e637a7cbc1a65d446a22e45546cd996ea28f932082b7dc9e # via celery lxml==4.9.3 \ --hash=sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3 \ @@ -293,8 +301,11 @@ markupsafe==2.1.3 \ --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \ + --hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \ --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \ --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \ + --hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \ + --hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \ --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \ --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \ --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \ @@ -302,6 +313,7 @@ markupsafe==2.1.3 \ --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \ --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \ --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \ + --hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \ --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \ --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \ --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \ @@ -310,6 +322,7 @@ markupsafe==2.1.3 \ --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \ --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \ --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \ + --hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \ --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \ --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \ --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \ @@ -317,9 +330,12 @@ markupsafe==2.1.3 \ --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \ --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \ --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \ + --hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \ --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \ --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \ + --hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \ --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \ + --hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \ --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \ --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \ --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \ @@ -338,7 +354,9 @@ markupsafe==2.1.3 \ --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \ --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ - --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 + --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \ + --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \ + --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11 # via jinja2 packaging==23.1 \ --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ @@ -346,63 +364,61 @@ packaging==23.1 \ # via # build # gunicorn -pillow==10.0.0 \ - --hash=sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5 \ - --hash=sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530 \ - --hash=sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d \ - --hash=sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca \ - --hash=sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891 \ - --hash=sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992 \ - --hash=sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7 \ - --hash=sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3 \ - --hash=sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba \ - --hash=sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3 \ - --hash=sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3 \ - --hash=sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f \ - --hash=sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538 \ - --hash=sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 \ - --hash=sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d \ - --hash=sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c \ - --hash=sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017 \ - --hash=sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3 \ - --hash=sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223 \ - --hash=sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e \ - --hash=sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3 \ - --hash=sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6 \ - --hash=sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640 \ - --hash=sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334 \ - --hash=sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1 \ - --hash=sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba \ - --hash=sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa \ - --hash=sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0 \ - --hash=sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396 \ - --hash=sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d \ - --hash=sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 \ - --hash=sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf \ - --hash=sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43 \ - --hash=sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37 \ - --hash=sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2 \ - --hash=sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd \ - --hash=sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86 \ - --hash=sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967 \ - --hash=sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 \ - --hash=sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568 \ - --hash=sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed \ - --hash=sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f \ - --hash=sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551 \ - --hash=sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3 \ - --hash=sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614 \ - --hash=sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff \ - --hash=sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d \ - --hash=sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883 \ - --hash=sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684 \ - --hash=sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0 \ - --hash=sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de \ - --hash=sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b \ - --hash=sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3 \ - --hash=sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199 \ - --hash=sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51 \ - --hash=sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90 +pillow==10.0.1 \ + --hash=sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff \ + --hash=sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f \ + --hash=sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21 \ + --hash=sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635 \ + --hash=sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a \ + --hash=sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f \ + --hash=sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1 \ + --hash=sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d \ + --hash=sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db \ + --hash=sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849 \ + --hash=sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7 \ + --hash=sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876 \ + --hash=sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3 \ + --hash=sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317 \ + --hash=sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91 \ + --hash=sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d \ + --hash=sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b \ + --hash=sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd \ + --hash=sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed \ + --hash=sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500 \ + --hash=sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7 \ + --hash=sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a \ + --hash=sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a \ + --hash=sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0 \ + --hash=sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf \ + --hash=sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f \ + --hash=sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1 \ + --hash=sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088 \ + --hash=sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971 \ + --hash=sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a \ + --hash=sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205 \ + --hash=sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54 \ + --hash=sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08 \ + --hash=sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21 \ + --hash=sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d \ + --hash=sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08 \ + --hash=sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e \ + --hash=sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf \ + --hash=sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b \ + --hash=sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145 \ + --hash=sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2 \ + --hash=sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d \ + --hash=sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d \ + --hash=sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf \ + --hash=sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad \ + --hash=sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d \ + --hash=sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1 \ + --hash=sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4 \ + --hash=sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2 \ + --hash=sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19 \ + --hash=sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37 \ + --hash=sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4 \ + --hash=sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68 \ + --hash=sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1 # via Inyoka (setup.py) pip-tools==7.3.0 \ --hash=sha256:8717693288720a8c6ebd07149c93ab0be1fced0b5191df9e9decd3263e20d85e \ @@ -444,9 +460,9 @@ python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 # via Inyoka (setup.py) -pytz==2023.3 \ - --hash=sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588 \ - --hash=sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb +pytz==2023.3.post1 \ + --hash=sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b \ + --hash=sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7 # via # Inyoka (setup.py) # django @@ -546,9 +562,9 @@ pyzmq==25.1.1 \ --hash=sha256:f8115e303280ba09f3898194791a153862cbf9eef722ad8f7f741987ee2a97c7 \ --hash=sha256:fedbdc753827cf014c01dbbee9c3be17e5a208dcd1bf8641ce2cd29580d1f0d4 # via Inyoka (setup.py) -redis==5.0.0 \ - --hash=sha256:06570d0b2d84d46c21defc550afbaada381af82f5b83e5b3777600e05d8e2ed0 \ - --hash=sha256:5cea6c0d335c9a7332a460ed8729ceabb4d0c489c7285b0a86dbbf8a017bd120 +redis==4.6.0 \ + --hash=sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d \ + --hash=sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c # via # celery # django-redis @@ -556,9 +572,9 @@ requests==2.31.0 \ --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 # via Inyoka (setup.py) -sentry-sdk==1.29.2 \ - --hash=sha256:3e17215d8006612e2df02b0e73115eb8376c37e3f586d8436fa41644e605074d \ - --hash=sha256:a99ee105384788c3f228726a88baf515fe7b5f1d2d0f215a03d194369f158df7 +sentry-sdk==1.31.0 \ + --hash=sha256:64a7141005fb775b9db298a30de93e3b83e0ddd1232dc6f36eb38aebc1553291 \ + --hash=sha256:6de2e88304873484207fed836388e422aeff000609b104c802749fd89d56ba5b # via Inyoka (setup.py) sgmllib3k==1.0.0 \ --hash=sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9 @@ -585,10 +601,12 @@ transifex-client==0.12.5 \ --hash=sha256:139867ffaf340aa2b74b0c44fa2d6525bf641357d04b7961a5b10ebe468678d8 \ --hash=sha256:23c88c55d1469b62a771646d4f202b6fe5f4abbcdbe61bda3a3b08c44aaa7a78 # via Inyoka (setup.py) -typing-extensions==4.7.1 \ - --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ - --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 - # via kombu +typing-extensions==4.8.0 \ + --hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \ + --hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef + # via + # asgiref + # kombu tzdata==2023.3 \ --hash=sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a \ --hash=sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda @@ -623,13 +641,17 @@ wheel==0.41.2 \ --hash=sha256:0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985 \ --hash=sha256:75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8 # via pip-tools +zipp==3.17.0 \ + --hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \ + --hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: pip==23.2.1 \ --hash=sha256:7ccf472345f20d35bdc9d1841ff5f313260c2c33fe417f48c30ac46cccabf5be \ --hash=sha256:fb0bd5435b3200c602b5bf61d2d43c2f13c02e29c1707567ae7fbc514eb9faf2 # via pip-tools -setuptools==68.1.2 \ - --hash=sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d \ - --hash=sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b +setuptools==68.2.2 \ + --hash=sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87 \ + --hash=sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a # via pip-tools diff --git a/inyoka/default_settings.py b/inyoka/default_settings.py index 28fc77f07..9a64c8a6a 100644 --- a/inyoka/default_settings.py +++ b/inyoka/default_settings.py @@ -35,6 +35,8 @@ }, } +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' + # Local time zone for this installation. Choices can be found here: # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # although not all choices may be avilable on all operating systems. diff --git a/inyoka/forum/constants.py b/inyoka/forum/constants.py index e3896737d..10faf50fe 100644 --- a/inyoka/forum/constants.py +++ b/inyoka/forum/constants.py @@ -9,7 +9,7 @@ :license: BSD, see LICENSE for more details. """ from PIL import Image -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from inyoka.portal.utils import get_ubuntu_versions @@ -23,18 +23,18 @@ CACHE_PAGES_COUNT = 5 UBUNTU_DISTROS = { - 'none': ugettext_lazy('No Ubuntu'), - 'edubuntu': ugettext_lazy('Edubuntu'), - 'kubuntu': ugettext_lazy('Kubuntu'), - 'server': ugettext_lazy('Server'), - 'ubuntu': ugettext_lazy('Ubuntu'), - 'xubuntu': ugettext_lazy('Xubuntu'), - 'lubuntu': ugettext_lazy('Lubuntu'), - 'gnome': ugettext_lazy('Ubuntu GNOME'), - 'touch': ugettext_lazy('Ubuntu Touch'), - 'mate': ugettext_lazy('Ubuntu MATE'), - 'budgie': ugettext_lazy('Ubuntu Budgie'), - 'unity': ugettext_lazy('Ubuntu Unity'), + 'none': gettext_lazy('No Ubuntu'), + 'edubuntu': gettext_lazy('Edubuntu'), + 'kubuntu': gettext_lazy('Kubuntu'), + 'server': gettext_lazy('Server'), + 'ubuntu': gettext_lazy('Ubuntu'), + 'xubuntu': gettext_lazy('Xubuntu'), + 'lubuntu': gettext_lazy('Lubuntu'), + 'gnome': gettext_lazy('Ubuntu GNOME'), + 'touch': gettext_lazy('Ubuntu Touch'), + 'mate': gettext_lazy('Ubuntu MATE'), + 'budgie': gettext_lazy('Ubuntu Budgie'), + 'unity': gettext_lazy('Ubuntu Unity'), } UBUNTU_DISTROS_SELECT_EXCLUDE = ( @@ -47,7 +47,7 @@ def get_simple_version_choices(): def get_version_choices(): - return [('', ugettext_lazy('Version'))] + get_simple_version_choices() + return [('', gettext_lazy('Version'))] + get_simple_version_choices() def get_distro_choices(exclude: bool=False): @@ -57,6 +57,6 @@ def get_distro_choices(exclude: bool=False): for key in UBUNTU_DISTROS_SELECT_EXCLUDE: UBUNTU_DISTROS_SELECT.pop(key) - return [('', ugettext_lazy('Distribution'))] + list(UBUNTU_DISTROS_SELECT.items()) + return [('', gettext_lazy('Distribution'))] + list(UBUNTU_DISTROS_SELECT.items()) - return [('', ugettext_lazy('Distribution'))] + list(UBUNTU_DISTROS.items()) + return [('', gettext_lazy('Distribution'))] + list(UBUNTU_DISTROS.items()) diff --git a/inyoka/forum/forms.py b/inyoka/forum/forms.py index 92bc40e4e..31d236bbc 100644 --- a/inyoka/forum/forms.py +++ b/inyoka/forum/forms.py @@ -10,8 +10,8 @@ """ from django import forms from django.conf import settings -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from inyoka.forum.constants import get_distro_choices, get_version_choices from inyoka.forum.models import Forum @@ -237,7 +237,7 @@ class AddAttachmentForm(forms.Form): attachment = forms.FileField() filename = forms.CharField(max_length=512, required=False) override = forms.BooleanField(required=False) - comment = forms.CharField(label=ugettext_lazy('Description'), required=False, + comment = forms.CharField(label=gettext_lazy('Description'), required=False, widget=forms.TextInput(attrs={'size': '60'})) use_required_attribute = False @@ -259,7 +259,7 @@ class ReportTopicForm(forms.Form): It's only field is a text field where the user can write why he thinks that the moderators should have a look at this topic. """ - text = forms.CharField(label=ugettext_lazy('Reason'), + text = forms.CharField(label=gettext_lazy('Reason'), widget=forms.Textarea(attrs={'spellcheck': 'true'})) @@ -290,19 +290,19 @@ class Meta: def clean_welcome_title(self): data = self.cleaned_data if data.get('welcome_text') and not data.get('welcome_title'): - raise forms.ValidationError(ugettext_lazy('You must enter a title ' + raise forms.ValidationError(gettext_lazy('You must enter a title ' 'in order to set the welcome message')) return data['welcome_title'] def clean_welcome_msg_text(self): data = self.cleaned_data if data.get('welcome_title') and not data.get('welcome_text'): - raise forms.ValidationError(ugettext_lazy('You must enter a text ' + raise forms.ValidationError(gettext_lazy('You must enter a text ' 'in order to set the welcome message')) return data['welcome_text'] def clean_slug(self): data = slugify(self.cleaned_data['slug']) if data == 'new': - raise forms.ValidationError(ugettext_lazy('“new” is not a valid forum slug')) + raise forms.ValidationError(gettext_lazy('“new” is not a valid forum slug')) return data diff --git a/inyoka/forum/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/forum/locale/de_DE/LC_MESSAGES/django.mo index b281ef010..73329477b 100644 Binary files a/inyoka/forum/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/forum/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/forum/locale/de_DE/LC_MESSAGES/django.po b/inyoka/forum/locale/de_DE/LC_MESSAGES/django.po index 26e384b8e..551a575f8 100644 --- a/inyoka/forum/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/forum/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-01-03 22:22+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2020-11-07 18:23+0100\n" "Last-Translator: Christoph Volkert <>\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.8.0\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(site)s forum" @@ -340,7 +340,7 @@ msgid "There is no “%(slug)s” anymore." msgstr "Es gibt kein „%(slug)s“ mehr." #, python-format -msgid "This post is currently beeing edited by “%(user)s”!" +msgid "This post is currently being edited by “%(user)s”!" msgstr "Diese Beitrag wird momentan von „%(user)s“ bearbeitet!" msgid "This report has already been claimed." @@ -386,6 +386,9 @@ msgstr "Ubuntu MATE" msgid "Ubuntu Touch" msgstr "Ubuntu Touch" +msgid "Ubuntu Unity" +msgstr "Ubuntu Unity" + msgid "Unanswered topics" msgstr "Unbeantwortete Themen" diff --git a/inyoka/forum/locale/django.pot b/inyoka/forum/locale/django.pot index b9a110626..01a1d0e9e 100644 --- a/inyoka/forum/locale/django.pot +++ b/inyoka/forum/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2021. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.24.5\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-01-03 22:22+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.8.0\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(site)s forum" @@ -385,6 +385,9 @@ msgstr "" msgid "Ubuntu Touch" msgstr "" +msgid "Ubuntu Unity" +msgstr "" + msgid "Unanswered topics" msgstr "" diff --git a/inyoka/forum/models.py b/inyoka/forum/models.py index 0b68fb9b6..81336025e 100644 --- a/inyoka/forum/models.py +++ b/inyoka/forum/models.py @@ -26,11 +26,11 @@ from django.contrib.auth.models import Group from django.core.cache import cache from django.db import models, transaction -from django.db.models import F, Count, Max, Sum -from django.utils.encoding import DjangoUnicodeDecodeError, force_text +from django.db.models import Count, F, Max, Sum +from django.utils.encoding import DjangoUnicodeDecodeError, force_str from django.utils.html import escape, format_html -from django.utils.translation import ugettext as _ -from django.utils.translation import pgettext, ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import pgettext, gettext_lazy from werkzeug.utils import secure_filename from inyoka.forum.constants import ( @@ -274,42 +274,42 @@ class Forum(models.Model): objects = ForumManager() name = models.CharField( - verbose_name=ugettext_lazy('Name'), + verbose_name=gettext_lazy('Name'), max_length=100) slug = models.SlugField( - verbose_name=ugettext_lazy('Slug'), + verbose_name=gettext_lazy('Slug'), max_length=100, unique=True) description = models.CharField( - verbose_name=ugettext_lazy('Description'), + verbose_name=gettext_lazy('Description'), max_length=500, blank=True) position = models.IntegerField( - verbose_name=ugettext_lazy('Position'), + verbose_name=gettext_lazy('Position'), default=0, db_index=True) newtopic_default_text = models.TextField( - verbose_name=ugettext_lazy('Default text for new topics'), + verbose_name=gettext_lazy('Default text for new topics'), null=True, blank=True) user_count_posts = models.BooleanField( - verbose_name=ugettext_lazy('Count user posts'), - help_text=ugettext_lazy('If not set then posts of users in this forum are ' + verbose_name=gettext_lazy('Count user posts'), + help_text=gettext_lazy('If not set then posts of users in this forum are ' 'ignored in the post counter of the user.'), default=True) force_version = models.BooleanField( - verbose_name=ugettext_lazy('Force version'), + verbose_name=gettext_lazy('Force version'), default=False) parent = models.ForeignKey( 'self', - verbose_name=ugettext_lazy('Parent forum'), + verbose_name=gettext_lazy('Parent forum'), null=True, blank=True, related_name='_children', @@ -323,20 +323,20 @@ class Forum(models.Model): support_group = models.ForeignKey( Group, - verbose_name=ugettext_lazy('Support group'), + verbose_name=gettext_lazy('Support group'), on_delete=models.SET_NULL, null=True, blank=True, related_name='forums') welcome_title = models.CharField( - verbose_name=ugettext_lazy('Welcome title'), + verbose_name=gettext_lazy('Welcome title'), max_length=120, null=True, blank=True) welcome_text = InyokaMarkupField( - verbose_name=ugettext_lazy('Welcome text'), + verbose_name=gettext_lazy('Welcome text'), application='forum', null=True, blank=True) @@ -344,8 +344,8 @@ class Forum(models.Model): welcome_read_users = models.ManyToManyField(User) class Meta: - verbose_name = ugettext_lazy('Forum') - verbose_name_plural = ugettext_lazy('Forums') + verbose_name = gettext_lazy('Forum') + verbose_name_plural = gettext_lazy('Forums') permissions = ( ('delete_topic_forum', 'Can delete Topics from Forum'), ('add_topic_forum', 'Can add Topic in Forum'), @@ -549,7 +549,7 @@ def topic_count(self): class Topic(models.Model): """A topic symbolizes a bunch of posts (at least one) that is located - insside a forum. Wen creating a new topic, a new post is added to it + inside a forum. When creating a new topic, a new post is added to it automatically. """ objects = TopicManager() @@ -580,8 +580,8 @@ class Topic(models.Model): on_delete=models.PROTECT) class Meta: - verbose_name = ugettext_lazy('Topic') - verbose_name_plural = ugettext_lazy('Topics') + verbose_name = gettext_lazy('Topic') + verbose_name_plural = gettext_lazy('Topics') permissions = ( ('manage_reported_topic', 'Can manage reported Topics'), ) @@ -594,7 +594,7 @@ def touch(self): Topic.objects.filter(id=self.id).update(view_count=F('view_count') + 1) def move(self, new_forum): - """Move the topic to an other forum.""" + """Move the topic to another forum.""" old_forums = [parent for parent in self.forum.parents] old_forums.append(self.forum) new_forums = [parent for parent in new_forum.parents] @@ -654,7 +654,7 @@ def delete(self, *args, **kwargs): self.save() # We need to call the delete() method explicitly to delete attachments - # too. Otherwise only the database entries are deleted. + # too. Otherwise, only the database entries are deleted. for post in self.posts.all(): post.delete() @@ -719,8 +719,8 @@ def get_version_info(self, default=None): if self.ubuntu_distro: out.append(UBUNTU_DISTROS[self.ubuntu_distro]) if self.ubuntu_version and self.ubuntu_version != 'none': - out.append(force_text(self.get_ubuntu_version())) - return ' '.join(force_text(x) for x in out) + out.append(force_str(self.get_ubuntu_version())) + return ' '.join(force_str(x) for x in out) def get_read_status(self, user): if user.is_anonymous: @@ -814,8 +814,8 @@ class Post(models.Model, LockableObject): on_delete=models.PROTECT) class Meta: - verbose_name = ugettext_lazy('Post') - verbose_name_plural = ugettext_lazy('Posts') + verbose_name = gettext_lazy('Post') + verbose_name_plural = gettext_lazy('Posts') def get_text(self): if self.is_plaintext: @@ -1202,7 +1202,7 @@ def create(name, uploaded_file, mime, attachments, override=False, **kwargs): exists = False if not exists: - # create a temporary filename so we can identify the attachment + # create a temporary filename, so we can identify the attachment # on binding to the posts fn = md5((str(time()) + name).encode('utf-8')).hexdigest() attachment = Attachment(name=name, mimetype=mime, **kwargs) @@ -1336,7 +1336,7 @@ def thumbnail(): contents = self.contents if contents is not None: try: - highlighted = highlight_code(force_text(contents), mimetype=self.mimetype) + highlighted = highlight_code(force_str(contents), mimetype=self.mimetype) return format_html('
{}
', highlighted) except DjangoUnicodeDecodeError: pass diff --git a/inyoka/forum/notifications.py b/inyoka/forum/notifications.py index 36a3fad19..1b1b5806f 100644 --- a/inyoka/forum/notifications.py +++ b/inyoka/forum/notifications.py @@ -11,7 +11,7 @@ from celery import shared_task from django.conf import settings from django.utils import translation -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.portal.user import User from inyoka.utils import ctype diff --git a/inyoka/forum/services.py b/inyoka/forum/services.py index a2508cd55..9c3fea1f7 100644 --- a/inyoka/forum/services.py +++ b/inyoka/forum/services.py @@ -68,12 +68,15 @@ def toggle_categories(request): def toggle_category(request): if request.user.is_anonymous: return False + try: category_id = int(request.GET.get('id')) except TypeError: return False + hidden_categories = request.user.settings.get('hidden_forum_categories', []) state = request.GET.get('state') + if state == 'hide': hidden_categories.append(category_id) elif state == 'show': @@ -83,6 +86,7 @@ def toggle_category(request): return False else: return False + request.user.settings['hidden_forum_categories'] = tuple(set(hidden_categories)) request.user.save() return True @@ -93,17 +97,17 @@ def toggle_category(request): @dispatcher.register() def subscription_action(request, action=None): assert action is not None and action in ('subscribe', 'unsubscribe') - type = request.POST['type'] + + subscription_type = request.POST['type'] slug = request.POST['slug'] cls = None - if type == 'forum': + if subscription_type == 'forum': cls = Forum - elif type == 'topic': + elif subscription_type == 'topic': cls = Topic obj = cls.objects.get(slug=slug) - if isinstance(obj, Topic): forum = obj.forum else: @@ -112,6 +116,7 @@ def subscription_action(request, action=None): if request.user.is_anonymous \ or not request.user.has_perm('forum.view_forum', forum): return abort_access_denied(request) + try: subscription = Subscription.objects.get_for_user(request.user, obj) except Subscription.DoesNotExist: @@ -128,10 +133,13 @@ def subscription_action(request, action=None): def change_status(request, solved=None): if 'slug' not in request.POST: return + topic = Topic.objects.get(slug=request.POST['slug']) can_read = request.user.has_perm('forum.view_forum', topic.forum) + if request.user.is_anonymous or not can_read: return abort_access_denied(request) + if solved is not None: topic.solved = solved topic.save() diff --git a/inyoka/forum/urls.py b/inyoka/forum/urls.py index 4e3baf221..e760e9f56 100644 --- a/inyoka/forum/urls.py +++ b/inyoka/forum/urls.py @@ -9,103 +9,103 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, path, re_path from . import views from ..utils.http import global_not_found, server_error urlpatterns = [ - url(r'^$', views.index), - url(r'^topic/(?P[^/]+)/$', views.viewtopic), - url(r'^topic/(?P[^/]+)/(?P\d+|last)/$', views.viewtopic), - url(r'^topic/(?P[^/]+)/reply/$', views.edit), - url(r'^topic/(?P[^/]+)/first_unread/$', views.first_unread_post), - url(r'^topic/(?P[^/]+)/last_post/$', views.last_post), - url(r'^topic/(?P[^/]+)/(?Pdelete|hide)/$', views.delete_topic), - url(r'^topic/(?P[^/]+)/restore/$', views.restore_topic), - url(r'^topic/(?P[^/]+)/split/$', views.splittopic), - url(r'^topic/(?P[^/]+)/split/(?P\d+)/$', views.splittopic), - url(r'^topic/(?P[^/]+)/move/$', views.movetopic), - url(r'^topic/(?P[^/]+)/(?P\d+/)?solve/$', views.solve_topic, {'solved': True}), - url(r'^topic/(?P[^/]+)/(?P\d+/)?unsolve/$', views.solve_topic, {'solved': False}), - url(r'^topic/(?P[^/]+)/(?P\d+/)?lock/$', views.lock_topic, {'locked': True}), - url(r'^topic/(?P[^/]+)/(?P\d+/)?unlock/$', views.lock_topic, {'locked': False}), - url(r'^topic/(?P[^/]+)/(?P\d+/)?report/$', views.report), - url(r'^topic/(?P[^/]+)/subscribe', views.subscribe_topic), - url(r'^topic/(?P[^/]+)/unsubscribe', views.unsubscribe_topic), - url(r'^topic/(?P[^/]+)/next/$', views.next_topic), - url(r'^topic/(?P[^/]+)/previous/$', views.previous_topic), - url(r'^reported_topics/$', views.reportlist), - url(r'^reported_topics/(?P(un)?subscribe)/$', views.reported_topics_subscription), - url(r'^post/(?P\d+)/$', views.post), - url(r'^post/(?P\d+)/edit/$', views.edit), - url(r'^post/(?P\d+)/quote/$', views.edit), - url(r'^post/(?P\d+)/restore/$', views.restore_post), - url(r'^post/(?P\d+)/(?Pdelete|hide)/$', views.delete_post), - url(r'^post/(?P\d+)/(?Pham|spam)/$', views.mark_ham_spam), - url(r'^post/(?P\d+)/revisions/$', views.revisions), - url(r'^revision/(?P\d+)/restore/$', views.restore_revision), - url(r'^forum/new/$', views.ForumCreateView.as_view()), - url(r'^forum/(?P[^/]+)/$', views.forum), - url(r'^forum/(?P[^/]+)/edit/$', views.ForumUpdateView.as_view()), - url(r'^forum/(?P[^/]+)/subscribe/$', views.subscribe_forum), - url(r'^forum/(?P[^/]+)/unsubscribe/$', views.unsubscribe_forum), - url(r'^forum/(?P[^/]+)/(?P\d+)/$', views.forum), - url(r'^forum/(?P[^/]+)/newtopic/$', views.edit), - url(r'^feeds/(?P[a-z]+)/(?P\d+)/$', views.forum_feed, {'slug': None}), - url(r'^feeds/forum/(?P[^/]+)/(?P[a-z]+)/(?P\d+)/$', views.forum_feed), - url(r'^feeds/topic/(?P[^/]+)/(?P[a-z]+)/(?P\d+)/$', views.topic_feed), - url(r'^category/(?P[^/]+)/$', views.index), - url(r'^new_discussion/(?P.+)/$', views.edit), - url(r'^markread/$', views.markread), - url(r'^category/(?P[^/]+)/markread/$', views.markread), - url(r'^forum/(?P[^/]+)/markread/$', views.markread), + path('', views.index), + path('topic//', views.viewtopic), + re_path(r'^topic/(?P[^/]+)/(?P\d+|last)/$', views.viewtopic), + path('topic//reply/', views.edit), + path('topic//first_unread/', views.first_unread_post), + path('topic//last_post/', views.last_post), + re_path(r'^topic/(?P[^/]+)/(?Pdelete|hide)/$', views.delete_topic), + path('topic//restore/', views.restore_topic), + path('topic//split/', views.splittopic), + path('topic//split//', views.splittopic), + path('topic//move/', views.movetopic), + re_path(r'^topic/(?P[^/]+)/(?P\d+/)?solve/$', views.solve_topic, {'solved': True}), + re_path(r'^topic/(?P[^/]+)/(?P\d+/)?unsolve/$', views.solve_topic, {'solved': False}), + re_path(r'^topic/(?P[^/]+)/(?P\d+/)?lock/$', views.lock_topic, {'locked': True}), + re_path(r'^topic/(?P[^/]+)/(?P\d+/)?unlock/$', views.lock_topic, {'locked': False}), + re_path(r'^topic/(?P[^/]+)/(?P\d+/)?report/$', views.report), + re_path(r'^topic/(?P[^/]+)/subscribe', views.subscribe_topic), + re_path(r'^topic/(?P[^/]+)/unsubscribe', views.unsubscribe_topic), + path('topic//next/', views.next_topic), + path('topic//previous/', views.previous_topic), + path('reported_topics/', views.reportlist), + re_path(r'^reported_topics/(?P(un)?subscribe)/$', views.reported_topics_subscription), + path('post//', views.post), + path('post//edit/', views.edit), + path('post//quote/', views.edit), + path('post//restore/', views.restore_post), + re_path(r'^post/(?P\d+)/(?Pdelete|hide)/$', views.delete_post), + re_path(r'^post/(?P\d+)/(?Pham|spam)/$', views.mark_ham_spam), + path('post//revisions/', views.revisions), + path('revision//restore/', views.restore_revision), + path('forum/new/', views.ForumCreateView.as_view()), + path('forum//', views.forum), + path('forum//edit/', views.ForumUpdateView.as_view()), + path('forum//subscribe/', views.subscribe_forum), + path('forum//unsubscribe/', views.unsubscribe_forum), + path('forum///', views.forum), + path('forum//newtopic/', views.edit), + re_path(r'^feeds/(?P[a-z]+)/(?P\d+)/$', views.forum_feed, {'slug': None}), + re_path(r'^feeds/forum/(?P[^/]+)/(?P[a-z]+)/(?P\d+)/$', views.forum_feed), + re_path(r'^feeds/topic/(?P[^/]+)/(?P[a-z]+)/(?P\d+)/$', views.topic_feed), + path('category//', views.index), + path('new_discussion//', views.edit), + path('markread/', views.markread), + path('category//markread/', views.markread), + path('forum//markread/', views.markread), # special searches - url(r'^newposts/$', views.topiclist, {'action': 'newposts'}), - url(r'^newposts/(?P\d+)/$', views.topiclist, {'action': 'newposts'}), - url(r'^newposts/(?P[^/]+)/$', views.topiclist, {'action': 'newposts'}), - url(r'^newposts/(?P[^/]+)/(?P\d+)/$', views.topiclist, {'action': 'newposts'}), + path('newposts/', views.topiclist, {'action': 'newposts'}), + path('newposts//', views.topiclist, {'action': 'newposts'}), + path('newposts//', views.topiclist, {'action': 'newposts'}), + path('newposts///', views.topiclist, {'action': 'newposts'}), - url(r'^last(?P\d+)/$', views.topiclist, {'action': 'last'}), - url(r'^last(?P\d+)/(?P\d+)/$', views.topiclist, {'action': 'last'}), - url(r'^last(?P\d+)/(?P[^/]+)/$', views.topiclist, {'action': 'last'}), - url(r'^last(?P\d+)/(?P[^/]+)/(?P\d+)/$', views.topiclist, {'action': 'last'}), + path('last/', views.topiclist, {'action': 'last'}), + path('last//', views.topiclist, {'action': 'last'}), + path('last//', views.topiclist, {'action': 'last'}), + path('last///', views.topiclist, {'action': 'last'}), - url(r'^unanswered/$', views.topiclist, {'action': 'unanswered'}), - url(r'^unanswered/(?P\d+)/$', views.topiclist, {'action': 'unanswered'}), - url(r'^unanswered/(?P[^/]+)/$', views.topiclist, {'action': 'unanswered'}), - url(r'^unanswered/(?P[^/]+)/(?P\d+)/$', views.topiclist, {'action': 'unanswered'}), + path('unanswered/', views.topiclist, {'action': 'unanswered'}), + path('unanswered//', views.topiclist, {'action': 'unanswered'}), + path('unanswered//', views.topiclist, {'action': 'unanswered'}), + path('unanswered///', views.topiclist, {'action': 'unanswered'}), - url(r'^unsolved/$', views.topiclist, {'action': 'unsolved'}), - url(r'^unsolved/(?P\d+)/$', views.topiclist, {'action': 'unsolved'}), - url(r'^unsolved/(?P[^/]+)/$', views.topiclist, {'action': 'unsolved'}), - url(r'^unsolved/(?P[^/]+)/(?P\d+)/$', views.topiclist, {'action': 'unsolved'}), + path('unsolved/', views.topiclist, {'action': 'unsolved'}), + path('unsolved//', views.topiclist, {'action': 'unsolved'}), + path('unsolved//', views.topiclist, {'action': 'unsolved'}), + path('unsolved///', views.topiclist, {'action': 'unsolved'}), - url(r'^egosearch/$', views.topiclist, {'action': 'author'}), - url(r'^egosearch/(?P\d+)/$', views.topiclist, {'action': 'author'}), - url(r'^egosearch/(?P[^/]+)/$', views.topiclist, {'action': 'author'}), - url(r'^egosearch/(?P[^/]+)/(?P\d+)/$', views.topiclist, {'action': 'author'}), + path('egosearch/', views.topiclist, {'action': 'author'}), + path('egosearch//', views.topiclist, {'action': 'author'}), + path('egosearch//', views.topiclist, {'action': 'author'}), + path('egosearch///', views.topiclist, {'action': 'author'}), - url(r'^author/(?P[^/]+)/$', views.postlist), - url(r'^author/(?P[^/]+)/(?P\d+)/$', views.postlist), - url(r'^author/(?P[^/]+)/topic/(?P[^/]+)/$', views.postlist), - url(r'^author/(?P[^/]+)/topic/(?P[^/]+)/(?P\d+)/$', views.postlist), - url(r'^author/(?P[^/]+)/forum/(?P[^/]+)/$', views.postlist), - url(r'^author/(?P[^/]+)/forum/(?P[^/]+)/(?P\d+)/$', views.postlist), + path('author//', views.postlist), + path('author///', views.postlist), + path('author//topic//', views.postlist), + path('author//topic///', views.postlist), + path('author//forum//', views.postlist), + path('author//forum///', views.postlist), - url(r'^topic_author/(?P[^/]+)/$', views.topiclist, {'action': 'topic_author'}), - url(r'^topic_author/(?P[^/]+)/(?P\d+)/$', views.topiclist, {'action': 'topic_author'}), - url(r'^topic_author/(?P[^/]+)/(?P[^/]+)/$', views.topiclist, {'action': 'topic_author'}), - url(r'^topic_author/(?P[^/]+)/(?P[^/]+)/(?P\d+)/$', views.topiclist, {'action': 'topic_author'}), + path('topic_author//', views.topiclist, {'action': 'topic_author'}), + path('topic_author///', views.topiclist, {'action': 'topic_author'}), + path('topic_author///', views.topiclist, {'action': 'topic_author'}), + path('topic_author////', views.topiclist, {'action': 'topic_author'}), - url(r'^category/(?P[^/]+)/welcome/$', views.WelcomeMessageView.as_view()), - url(r'^forum/(?P[^/]+)/welcome/$', views.WelcomeMessageView.as_view()), + path('category//welcome/', views.WelcomeMessageView.as_view()), + path('forum//welcome/', views.WelcomeMessageView.as_view()), ] if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) handler404 = global_not_found diff --git a/inyoka/forum/views.py b/inyoka/forum/views.py index a869514e1..31ea6f50c 100644 --- a/inyoka/forum/views.py +++ b/inyoka/forum/views.py @@ -21,9 +21,9 @@ from django.core.exceptions import ObjectDoesNotExist from django.db.models import F, Q from django.http import Http404, HttpResponseRedirect -from django.shortcuts import redirect, get_object_or_404 +from django.shortcuts import get_object_or_404, redirect from django.utils.text import Truncator -from django.utils.translation import ugettext as _, ugettext_lazy +from django.utils.translation import gettext as _, gettext_lazy from django.views.generic import CreateView, DetailView, UpdateView from guardian.mixins import PermissionRequiredMixin as GuardianPermissionRequiredMixin @@ -762,9 +762,9 @@ def edit(request, forum_slug=None, topic_slug=None, post_id=None, } -@confirm_action(message=ugettext_lazy('Do you want to (un)lock the topic?'), - confirm=ugettext_lazy('(Un)lock'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to (un)lock the topic?'), + confirm=gettext_lazy('(Un)lock'), + cancel=gettext_lazy('Cancel')) @login_required def lock_topic(request, topic_slug, locked, page=1): """Lock/unlock a topic and redirect to it""" @@ -885,21 +885,21 @@ def unsubscriber(request, **kwargs): subscribe_forum = _generate_subscriber(Forum, 'slug', 'forum', - (ugettext_lazy('Notifications on new topics within this forum will be sent to you.'))) + (gettext_lazy('Notifications on new topics within this forum will be sent to you.'))) unsubscribe_forum = _generate_unsubscriber(Forum, 'slug', 'forum', - (ugettext_lazy('No notifications on new topics within this forum will be sent to you ' + (gettext_lazy('No notifications on new topics within this forum will be sent to you ' 'any more.'))) subscribe_topic = _generate_subscriber(Topic, 'topic_slug', 'topic', - (ugettext_lazy('Notifications on new posts in this topic will be sent to you.'))) + (gettext_lazy('Notifications on new posts in this topic will be sent to you.'))) unsubscribe_topic = _generate_unsubscriber(Topic, 'topic_slug', 'topic', - (ugettext_lazy('No notifications on new posts in this topic will be sent to you any ' + (gettext_lazy('No notifications on new posts in this topic will be sent to you any ' 'more'))) @@ -1243,9 +1243,9 @@ def splittopic(request, topic_slug, page=1): } -@confirm_action(message=ugettext_lazy('Do you want to restore this post?'), - confirm=ugettext_lazy('Restore'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to restore this post?'), + confirm=gettext_lazy('Restore'), + cancel=gettext_lazy('Cancel')) def restore_post(request, post_id): """ This function removes the hidden flag of a post to make it visible for @@ -1261,9 +1261,9 @@ def restore_post(request, post_id): return HttpResponseRedirect(url_for(post)) -@confirm_action(message=ugettext_lazy('Do you really want to hide / delete this post?'), - confirm=ugettext_lazy('Hide / Delete'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you really want to hide / delete this post?'), + confirm=gettext_lazy('Hide / Delete'), + cancel=gettext_lazy('Cancel')) def delete_post(request, post_id, action='hide'): """ Sets the hidden flag of a post to True if action == 'hide'. which has the @@ -1315,9 +1315,9 @@ def delete_post(request, post_id, action='hide'): post.page)) -@confirm_action(message=ugettext_lazy('Do you really want to mark this post as ham / spam?'), - confirm=ugettext_lazy('Mark as ham / spam'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you really want to mark this post as ham / spam?'), + confirm=gettext_lazy('Mark as ham / spam'), + cancel=gettext_lazy('Cancel')) def mark_ham_spam(request, post_id, action='spam'): post = Post.objects.select_related('topic__forum').get(id=post_id) topic = post.topic @@ -1355,9 +1355,9 @@ def revisions(request, post_id): } -@confirm_action(message=ugettext_lazy('Do you want to restore the revision of the post?'), - confirm=ugettext_lazy('Restore'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to restore the revision of the post?'), + confirm=gettext_lazy('Restore'), + cancel=gettext_lazy('Cancel')) def restore_revision(request, rev_id): rev = PostRevision.objects.select_related('post__topic__forum').get(id=rev_id) if not request.user.has_perm('forum.moderate_forum', rev.post.topic.forum): @@ -1367,9 +1367,9 @@ def restore_revision(request, rev_id): return HttpResponseRedirect(href('forum', 'post', rev.post_id)) -@confirm_action(message=ugettext_lazy('Do you want to restore the topic?'), - confirm=ugettext_lazy('Restore'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to restore the topic?'), + confirm=gettext_lazy('Restore'), + cancel=gettext_lazy('Cancel')) def restore_topic(request, topic_slug): """ This function removes the hidden flag of a topic to make it visible for diff --git a/inyoka/ikhaya/forms.py b/inyoka/ikhaya/forms.py index bc2f452ff..dfb80869d 100644 --- a/inyoka/ikhaya/forms.py +++ b/inyoka/ikhaya/forms.py @@ -12,7 +12,7 @@ from django import forms from django.utils.timezone import get_current_timezone -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy import pytz @@ -42,8 +42,8 @@ class Meta: class EditCommentForm(forms.Form): - text = StrippedCharField(label=ugettext_lazy('Text'), widget=forms.Textarea, - help_text=ugettext_lazy('To refer to another comment, you ' + text = StrippedCharField(label=gettext_lazy('Text'), widget=forms.Textarea, + help_text=gettext_lazy('To refer to another comment, you ' 'can write @commentnumber.
' 'Clicking on “reply” will automatically insert this code.')) @@ -64,9 +64,9 @@ def __init__(self, *args, **kwargs): for field in ('subject', 'intro', 'text'): self.fields[field].widget.attrs['readonly'] = True - author = UserField(label=ugettext_lazy('Author'), required=True) - updated = DateTimeField(label=ugettext_lazy('Last update'), - help_text=ugettext_lazy('If you keep this field empty, the ' + author = UserField(label=gettext_lazy('Author'), required=True) + updated = DateTimeField(label=gettext_lazy('Last update'), + help_text=gettext_lazy('If you keep this field empty, the ' 'publication date will be used.'), localize=True, required=False) @@ -78,7 +78,7 @@ def save(self): instance.pub_time = self.cleaned_data['pub_time'] if self.cleaned_data.get('updated', None): instance.updated = self.cleaned_data['updated'] - elif set(('pub_date', 'pub_time')) in set(self.cleaned_data.keys()): + elif {'pub_date', 'pub_time'} in set(self.cleaned_data.keys()): instance.updated = date_time_to_datetime( self.cleaned_data['pub_date'], self.cleaned_data['pub_time']) @@ -94,7 +94,7 @@ def clean_slug(self): if self.instance.pk: q = q.exclude(id=self.instance.pk) if q.exists(): - raise forms.ValidationError(ugettext_lazy('There already ' + raise forms.ValidationError(gettext_lazy('There already ' 'exists an article with this slug!')) return slug @@ -177,14 +177,14 @@ def clean(self): startdate = cleaned_data.get('date') enddate = cleaned_data.get('enddate') if startdate and enddate and enddate < startdate: - self._errors['enddate'] = self.error_class([ugettext_lazy('The ' + self._errors['enddate'] = self.error_class([gettext_lazy('The ' 'end date must occur after the start date.')]) del cleaned_data['enddate'] elif startdate == enddate: starttime = cleaned_data.get('time') endtime = cleaned_data.get('endtime') if starttime and endtime and endtime < starttime: - self._errors['endtime'] = self.error_class([ugettext_lazy('The ' + self._errors['endtime'] = self.error_class([gettext_lazy('The ' 'end time must occur after the start time.')]) del cleaned_data['endtime'] @@ -202,7 +202,7 @@ class Meta: class EditEventForm(NewEventForm): - visible = forms.BooleanField(label=ugettext_lazy('Display event?'), + visible = forms.BooleanField(label=gettext_lazy('Display event?'), required=False) class Meta(NewEventForm.Meta): diff --git a/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.mo index 5f514a6bb..55e356bfc 100644 Binary files a/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.po b/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.po index d0b60f1ca..7c2b72b2e 100644 --- a/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/ikhaya/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-01-25 20:47+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2017-03-23 22:51+0000\n" "Last-Translator: Lyra\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(domain)s Ikhaya comments" diff --git a/inyoka/ikhaya/locale/django.pot b/inyoka/ikhaya/locale/django.pot index 19ec5074f..bf36af8b4 100644 --- a/inyoka/ikhaya/locale/django.pot +++ b/inyoka/ikhaya/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2019. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.17.6\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-01-25 20:47+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(domain)s Ikhaya comments" diff --git a/inyoka/ikhaya/models.py b/inyoka/ikhaya/models.py index ebd46f79d..85c5205ab 100644 --- a/inyoka/ikhaya/models.py +++ b/inyoka/ikhaya/models.py @@ -17,7 +17,7 @@ from django.db.models import Q from django.utils import datetime_safe from django.utils.html import escape -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from inyoka.portal.models import StaticFile from inyoka.portal.user import User @@ -160,10 +160,10 @@ def get_upcoming(self, count=10): class Category(models.Model): name = models.CharField(max_length=180) - slug = models.CharField(ugettext_lazy('Slug'), max_length=100, + slug = models.CharField(gettext_lazy('Slug'), max_length=100, blank=True, unique=True, db_index=True) icon = models.ForeignKey(StaticFile, blank=True, null=True, - verbose_name=ugettext_lazy('Icon'), on_delete=models.SET_NULL) + verbose_name=gettext_lazy('Icon'), on_delete=models.SET_NULL) def __str__(self): return self.name @@ -183,8 +183,8 @@ def save(self, *args, **kwargs): class Meta: ordering = ('name',) - verbose_name = ugettext_lazy('Category') - verbose_name_plural = ugettext_lazy('Categories') + verbose_name = gettext_lazy('Category') + verbose_name_plural = gettext_lazy('Categories') class Article(models.Model, LockableObject): @@ -193,26 +193,26 @@ class Article(models.Model, LockableObject): objects = ArticleManager(all=True) published = ArticleManager(public=True) - pub_date = models.DateField(ugettext_lazy('Date'), db_index=True) - pub_time = models.TimeField(ugettext_lazy('Time')) - updated = models.DateTimeField(ugettext_lazy('Last change'), blank=True, + pub_date = models.DateField(gettext_lazy('Date'), db_index=True) + pub_time = models.TimeField(gettext_lazy('Time')) + updated = models.DateTimeField(gettext_lazy('Last change'), blank=True, null=True, db_index=True) author = models.ForeignKey(User, related_name='article_set', - verbose_name=ugettext_lazy('Author'), on_delete=models.CASCADE) - subject = models.CharField(ugettext_lazy('Headline'), max_length=180) - category = models.ForeignKey(Category, verbose_name=ugettext_lazy('Category'), + verbose_name=gettext_lazy('Author'), on_delete=models.CASCADE) + subject = models.CharField(gettext_lazy('Headline'), max_length=180) + category = models.ForeignKey(Category, verbose_name=gettext_lazy('Category'), on_delete=models.PROTECT) icon = models.ForeignKey(StaticFile, blank=True, null=True, - verbose_name=ugettext_lazy('Icon'), on_delete=models.SET_NULL) - intro = InyokaMarkupField(verbose_name=ugettext_lazy('Introduction'), application='ikhaya') - text = InyokaMarkupField(verbose_name=ugettext_lazy('Text'), application='ikhaya') - public = models.BooleanField(ugettext_lazy('Public'), default=False) - slug = models.SlugField(ugettext_lazy('Slug'), max_length=100, - blank=True, db_index=True, help_text=ugettext_lazy('Unique URL-part for the article. If not given, the slug will be generated from title.')) - is_xhtml = models.BooleanField(ugettext_lazy('XHTML Markup'), + verbose_name=gettext_lazy('Icon'), on_delete=models.SET_NULL) + intro = InyokaMarkupField(verbose_name=gettext_lazy('Introduction'), application='ikhaya') + text = InyokaMarkupField(verbose_name=gettext_lazy('Text'), application='ikhaya') + public = models.BooleanField(gettext_lazy('Public'), default=False) + slug = models.SlugField(gettext_lazy('Slug'), max_length=100, + blank=True, db_index=True, help_text=gettext_lazy('Unique URL-part for the article. If not given, the slug will be generated from title.')) + is_xhtml = models.BooleanField(gettext_lazy('XHTML Markup'), default=False) comment_count = models.IntegerField(default=0) - comments_enabled = models.BooleanField(ugettext_lazy('Allow comments'), + comments_enabled = models.BooleanField(gettext_lazy('Allow comments'), default=True) def get_intro(self): @@ -333,8 +333,8 @@ def delete(self): self.id = id class Meta: - verbose_name = ugettext_lazy('Article') - verbose_name_plural = ugettext_lazy('Articles') + verbose_name = gettext_lazy('Article') + verbose_name_plural = gettext_lazy('Articles') ordering = ['-pub_date', '-pub_time', 'author'] unique_together = ('pub_date', 'slug') permissions = ( @@ -369,11 +369,11 @@ class Suggestion(models.Model): author = models.ForeignKey(User, related_name='suggestion_set', on_delete=models.CASCADE) pub_date = models.DateTimeField('Datum', default=datetime.utcnow) - title = models.CharField(ugettext_lazy('Title'), max_length=100) - text = InyokaMarkupField(verbose_name=ugettext_lazy('Text'), application='ikhaya') - intro = InyokaMarkupField(verbose_name=ugettext_lazy('Introduction'), application='ikhaya') + title = models.CharField(gettext_lazy('Title'), max_length=100) + text = InyokaMarkupField(verbose_name=gettext_lazy('Text'), application='ikhaya') + intro = InyokaMarkupField(verbose_name=gettext_lazy('Introduction'), application='ikhaya') notes = InyokaMarkupField( - verbose_name=ugettext_lazy('Annotations to the team'), + verbose_name=gettext_lazy('Annotations to the team'), blank=True, default='', application='ikhaya') @@ -381,8 +381,8 @@ class Suggestion(models.Model): null=True, blank=True, on_delete=models.CASCADE) class Meta: - verbose_name = ugettext_lazy('Article suggestion') - verbose_name_plural = ugettext_lazy('Article suggestions') + verbose_name = gettext_lazy('Article suggestion') + verbose_name_plural = gettext_lazy('Article suggestions') def get_absolute_url(self): return href('ikhaya', 'suggestions', _anchor=self.id) @@ -432,9 +432,9 @@ class Event(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) location = models.CharField(max_length=128, blank=True) location_town = models.CharField(max_length=56, blank=True) - location_lat = models.FloatField(ugettext_lazy('Degree of latitude'), + location_lat = models.FloatField(gettext_lazy('Degree of latitude'), blank=True, null=True) - location_long = models.FloatField(ugettext_lazy('Degree of longitude'), + location_long = models.FloatField(gettext_lazy('Degree of longitude'), blank=True, null=True) visible = models.BooleanField(default=False) diff --git a/inyoka/ikhaya/notifications.py b/inyoka/ikhaya/notifications.py index f87891da4..d47563294 100644 --- a/inyoka/ikhaya/notifications.py +++ b/inyoka/ikhaya/notifications.py @@ -8,7 +8,7 @@ :copyright: (c) 2007-2023 by the Inyoka Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ -from django.utils.translation import ugettext +from django.utils.translation import gettext from inyoka.utils import ctype from inyoka.utils.notification import queue_notifications @@ -22,7 +22,7 @@ def send_new_suggestion_notifications(user, suggestion): 'suggestion_url': suggestion.get_absolute_url()} queue_notifications.delay(user, 'new_suggestion', - ugettext('New article suggestion “%(suggestion)s”') % { + gettext('New article suggestion “%(suggestion)s”') % { 'suggestion': data.get('suggestion_title')}, data, filter={'content_type_id': ctype(Suggestion).pk}) @@ -39,7 +39,7 @@ def send_comment_notifications(user, comment, article): 'comment_url': comment.get_absolute_url()} queue_notifications.delay(user, 'new_comment', - ugettext('New comment on article “%(article)s”') % { + gettext('New comment on article “%(article)s”') % { 'article': data.get('article_subject')}, data, filter={'content_type_id': ctype(Article).pk, diff --git a/inyoka/ikhaya/urls.py b/inyoka/ikhaya/urls.py index b237bd8b0..5bc55cc73 100644 --- a/inyoka/ikhaya/urls.py +++ b/inyoka/ikhaya/urls.py @@ -9,87 +9,87 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, path, re_path from . import views from ..utils.http import global_not_found, server_error urlpatterns = [ - url(r'^$', views.index), - url(r'^full/$', views.index, {'full': True}), - url(r'^(?P\d+)/$', views.index), - url(r'^full/(?P\d+)/$', views.index, {'full': True}), - url(r'^(?P\d+)/(?P\d+)/$', views.index), - url(r'^(?P\d+)/(?P\d+)/full/$', views.index, {'full': True}), - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/$', views.index), - url(r'^(?P\d+)/(?P\d+)/full/(?P\d+)/$', views.index, {'full': True}), - url(r'^category/new/$', views.category_edit), - url(r'^category/(?P[^/]+)/$', views.index), - url(r'^category/(?P[^/]+)/full/$', views.index, {'full': True}), - url(r'^category/(?P[^/]+)/(?P\d+)/$', views.index), - url(r'^category/(?P[^/]+)/full/(?P\d+)/$', views.index, {'full': True}), - url(r'^category/(?P[^/]+)/edit/$', views.category_edit), + path('', views.index), + path('full/', views.index, {'full': True}), + path('/', views.index), + path('full//', views.index, {'full': True}), + path('//', views.index), + path('//full/', views.index, {'full': True}), + path('///', views.index), + path('//full//', views.index, {'full': True}), + path('category/new/', views.category_edit), + path('category//', views.index), + path('category//full/', views.index, {'full': True}), + path('category///', views.index), + path('category//full//', views.index, {'full': True}), + path('category//edit/', views.category_edit), #: article related urls - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/$', views.detail), - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/delete/$', + path('////', views.detail), + path('////delete/', views.article_delete), - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/edit/$', + path('////edit/', views.article_edit), - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/subscribe/$', + path('////subscribe/', views.article_subscribe), - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/unsubscribe/$', + path('////unsubscribe/', views.article_unsubscribe), - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/reports/$', + path('////reports/', views.reports), - url(r'^(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/new_report/$', + path('////new_report/', views.report_new), - url(r'^article/new/$', views.article_edit), - url(r'^article/new/(?P\d+)/$', views.article_edit), + path('article/new/', views.article_edit), + path('article/new//', views.article_edit), #: comment related urls - url(r'^comment/(?P\d+)/edit/$', views.comment_edit), - url(r'^comment/(?P\d+)/hide/$', views.comment_hide), - url(r'^comment/(?P\d+)/restore/$', views.comment_restore), + path('comment//edit/', views.comment_edit), + path('comment//hide/', views.comment_hide), + path('comment//restore/', views.comment_restore), #: report related urls - url(r'^report/(?P\d+)/hide/$', views.report_hide), - url(r'^report/(?P\d+)/restore/$', views.report_restore), - url(r'^report/(?P\d+)/solve/$', views.report_solve), - url(r'^report/(?P\d+)/unsolve/$', views.report_unsolve), - url(r'^report/(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/new/$', + path('report//hide/', views.report_hide), + path('report//restore/', views.report_restore), + path('report//solve/', views.report_solve), + path('report//unsolve/', views.report_unsolve), + path('report/////new/', views.report_new), - url(r'^reports/(?P\d+)/(?P\d+)/(?P\d+)/(?P[^/]+)/$', + path('reports/////', views.reports), - url(r'^reports/$', views.reportlist), + path('reports/', views.reportlist), - url(r'^archive/$', views.archive), + path('archive/', views.archive), - url(r'^suggest/(?P\d+)/assign/(?P[^/]+)/$', views.suggest_assign_to), - url(r'^suggest/(?P\d+)/delete/$', views.suggest_delete), - url(r'^suggest/new/$', views.suggest_edit), - url(r'^suggestions/$', views.suggestions), - url(r'^suggestions/subscribe/$', views.suggestions_subscribe), - url(r'^suggestions/unsubscribe/$', views.suggestions_unsubscribe), + path('suggest//assign//', views.suggest_assign_to), + path('suggest//delete/', views.suggest_delete), + path('suggest/new/', views.suggest_edit), + path('suggestions/', views.suggestions), + path('suggestions/subscribe/', views.suggestions_subscribe), + path('suggestions/unsubscribe/', views.suggestions_unsubscribe), - url(r'^feeds/comments/(?P\w+)/(?P\d+)/$', views.feed_comment, {'id': None}), - url(r'^feeds/comments/(?P\d+)/(?P\w+)/(?P\d+)/$', views.feed_comment), - url(r'^feeds/(?P\w+)/(?P\d+)/$', views.feed_article, {'slug': None}), - url(r'^feeds/(?P[^/]+)/(?P\w+)/(?P\d+)/$', views.feed_article), + re_path(r'^feeds/comments/(?P\w+)/(?P\d+)/$', views.feed_comment, {'id': None}), + re_path(r'^feeds/comments/(?P\d+)/(?P\w+)/(?P\d+)/$', views.feed_comment), + re_path(r'^feeds/(?P\w+)/(?P\d+)/$', views.feed_article, {'slug': None}), + re_path(r'^feeds/(?P[^/]+)/(?P\w+)/(?P\d+)/$', views.feed_article), - url(r'^events/$', views.events), - url(r'^events/all/$', views.events, {'show_all': True}), - url(r'^events/invisible/$', views.events, {'invisible': True}), - url(r'^event/suggest/$', views.event_suggest), - url(r'^event/new/$', views.event_edit), - url(r'^event/(?P\d+)/delete/$', views.event_delete), - url(r'^event/(?P\d+)/edit/$', views.event_edit), + path('events/', views.events), + path('events/all/', views.events, {'show_all': True}), + path('events/invisible/', views.events, {'invisible': True}), + path('event/suggest/', views.event_suggest), + path('event/new/', views.event_edit), + path('event//delete/', views.event_delete), + path('event//edit/', views.event_edit), ] if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) handler404 = global_not_found diff --git a/inyoka/ikhaya/views.py b/inyoka/ikhaya/views.py index 04b4bdcfa..52bd109e6 100644 --- a/inyoka/ikhaya/views.py +++ b/inyoka/ikhaya/views.py @@ -22,7 +22,7 @@ from django.utils.html import escape from django.utils.text import Truncator from django.utils.timezone import get_current_timezone -from django.utils.translation import ugettext as _, ugettext_lazy +from django.utils.translation import gettext as _, gettext_lazy from inyoka.ikhaya.forms import ( EditArticleForm, @@ -467,36 +467,36 @@ def _change_report_status(request, report_id, action, msg): @permission_required('ikhaya.change_article', raise_exception=True) -@confirm_action(message=ugettext_lazy('Do you want to hide this report?'), - confirm=ugettext_lazy('Hide'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to hide this report?'), + confirm=gettext_lazy('Hide'), + cancel=gettext_lazy('Cancel')) def report_hide(request, report_id): return _change_report_status(request, report_id, 'hide', _('The report was hidden.')) @permission_required('ikhaya.change_article', raise_exception=True) -@confirm_action(message=ugettext_lazy('Do you want to restore this report?'), - confirm=ugettext_lazy('Restore'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to restore this report?'), + confirm=gettext_lazy('Restore'), + cancel=gettext_lazy('Cancel')) def report_restore(request, report_id): return _change_report_status(request, report_id, 'restore', _('The report was restored.')) @permission_required('ikhaya.change_article', raise_exception=True) -@confirm_action(message=ugettext_lazy('Do you want to mark this report as solved?'), - confirm=ugettext_lazy('Mark as solved'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to mark this report as solved?'), + confirm=gettext_lazy('Mark as solved'), + cancel=gettext_lazy('Cancel')) def report_solve(request, report_id): return _change_report_status(request, report_id, 'solve', _('The report was marked as solved.')) @permission_required('ikhaya.change_article', raise_exception=True) -@confirm_action(message=ugettext_lazy('Do you want to mark this report as unsolved?'), - confirm=ugettext_lazy('Mark as unsolved'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to mark this report as unsolved?'), + confirm=gettext_lazy('Mark as unsolved'), + cancel=gettext_lazy('Cancel')) def report_unsolve(request, report_id): return _change_report_status(request, report_id, 'unsolve', _('The report was marked as unsolved.')) @@ -560,17 +560,17 @@ def _change_comment_status(request, comment_id, hide, msg): return HttpResponseRedirect(url_for(c.article)) -@confirm_action(message=ugettext_lazy('Do you want to hide this comment?'), - confirm=ugettext_lazy('Hide'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to hide this comment?'), + confirm=gettext_lazy('Hide'), + cancel=gettext_lazy('Cancel')) def comment_hide(request, comment_id): return _change_comment_status(request, comment_id, True, _('The comment was hidden.')) -@confirm_action(message=ugettext_lazy('Do you want to restore this comment?'), - confirm=ugettext_lazy('Restore'), - cancel=ugettext_lazy('Cancel')) +@confirm_action(message=gettext_lazy('Do you want to restore this comment?'), + confirm=gettext_lazy('Restore'), + cancel=gettext_lazy('Cancel')) def comment_restore(request, comment_id): return _change_comment_status(request, comment_id, False, _('The comment was restored.')) diff --git a/inyoka/locale/babel_django_templates.py b/inyoka/locale/babel_django_templates.py new file mode 100644 index 000000000..b196786e3 --- /dev/null +++ b/inyoka/locale/babel_django_templates.py @@ -0,0 +1,206 @@ +""" + inyoka.locale.babel_django_templates + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + A babel extractor for translation strings inside django templates. + +taken from +https://github.com/Zegocover/enmerkar/blob/d2c54f15ef60396a030c2319501860d2ae2d8b63/enmerkar/extract.py + +Copyright (C) 2013-2014 django-babel Team +Copyright (C) 2019 Extracover Holdings Limited + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from django.template.base import Lexer +from django.template.base import TokenType + +from django.utils.translation import trim_whitespace +from django.utils.encoding import smart_str + +from django.utils.translation.template import ( + inline_re, block_re, endblock_re, plural_re, constant_re) + + +TOKEN_TEXT = TokenType.TEXT +TOKEN_VAR = TokenType.VAR +TOKEN_BLOCK = TokenType.BLOCK + + +def join_tokens(tokens, trim=False): + message = ''.join(tokens) + if trim: + message = trim_whitespace(message) + return message + + +def strip_quotes(s): + if (s[0] == s[-1]) and s.startswith(("'", '"')): + return s[1:-1] + return s + + +def extract_django(fileobj, keywords, comment_tags, options): + """Extract messages from Django template files. + + :param fileobj: the file-like object the messages should be extracted from + :param keywords: a list of keywords (i.e. function names) that should + be recognized as translation functions + :param comment_tags: a list of translator tags to search for and + include in the results + :param options: a dictionary of additional options (optional) + :return: an iterator over ``(lineno, funcname, message, comments)`` + tuples + :rtype: ``iterator`` + """ + intrans = False + inplural = False + trimmed = False + message_context = None + singular = [] + plural = [] + lineno = 1 + + encoding = options.get('encoding', 'utf8') + text = fileobj.read().decode(encoding) + + text_lexer = Lexer(text) + + for t in text_lexer.tokenize(): + lineno += t.contents.count('\n') + if intrans: + if t.token_type == TOKEN_BLOCK: + endbmatch = endblock_re.match(t.contents) + pluralmatch = plural_re.match(t.contents) + if endbmatch: + if inplural: + if message_context: + yield ( + lineno, + 'npgettext', + [smart_str(message_context), + smart_str(join_tokens(singular, trimmed)), + smart_str(join_tokens(plural, trimmed))], + [], + ) + else: + yield ( + lineno, + 'ngettext', + (smart_str(join_tokens(singular, trimmed)), + smart_str(join_tokens(plural, trimmed))), + []) + else: + if message_context: + yield ( + lineno, + 'pgettext', + [smart_str(message_context), + smart_str(join_tokens(singular, trimmed))], + [], + ) + else: + yield ( + lineno, + None, + smart_str(join_tokens(singular, trimmed)), + []) + + intrans = False + inplural = False + message_context = None + singular = [] + plural = [] + elif pluralmatch: + inplural = True + else: + raise SyntaxError('Translation blocks must not include ' + 'other block tags: %s' % t.contents) + elif t.token_type == TOKEN_VAR: + if inplural: + plural.append('%%(%s)s' % t.contents) + else: + singular.append('%%(%s)s' % t.contents) + elif t.token_type == TOKEN_TEXT: + if inplural: + plural.append(t.contents) + else: + singular.append(t.contents) + else: + if t.token_type == TOKEN_BLOCK: + imatch = inline_re.match(t.contents) + bmatch = block_re.match(t.contents) + cmatches = constant_re.findall(t.contents) + if imatch: + g = imatch.group(1) + g = strip_quotes(g) + message_context = imatch.group(3) + if message_context: + # strip quotes + message_context = message_context[1:-1] + yield ( + lineno, + 'pgettext', + [smart_str(message_context), smart_str(g)], + [], + ) + message_context = None + else: + yield lineno, None, smart_str(g), [] + elif bmatch: + if bmatch.group(2): + message_context = bmatch.group(2)[1:-1] + for fmatch in constant_re.findall(t.contents): + stripped_fmatch = strip_quotes(fmatch) + yield lineno, None, smart_str(stripped_fmatch), [] + intrans = True + inplural = False + trimmed = 'trimmed' in t.split_contents() + singular = [] + plural = [] + elif cmatches: + for cmatch in cmatches: + stripped_cmatch = strip_quotes(cmatch) + yield lineno, None, smart_str(stripped_cmatch), [] + elif t.token_type == TOKEN_VAR: + parts = t.contents.split('|') + cmatch = constant_re.match(parts[0]) + if cmatch: + stripped_cmatch = strip_quotes(cmatch.group(1)) + yield lineno, None, smart_str(stripped_cmatch), [] + for p in parts[1:]: + if p.find(':_(') >= 0: + p1 = p.split(':', 1)[1] + if p1[0] == '_': + p1 = p1[1:] + if p1[0] == '(': + p1 = p1.strip('()') + p1 = strip_quotes(p1) + yield lineno, None, smart_str(p1), [] diff --git a/inyoka/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/locale/de_DE/LC_MESSAGES/django.mo index 5ecf42fdc..bf9efafe2 100644 Binary files a/inyoka/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/locale/de_DE/LC_MESSAGES/django.po b/inyoka/locale/de_DE/LC_MESSAGES/django.po index 9220ab025..1a4e9858a 100644 --- a/inyoka/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2020-11-07 18:18+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2020-11-07 18:24+0100\n" "Last-Translator: Christoph Volkert <>\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "\"%(fingerprint)s\" is not a valid GPG Fingerprint." diff --git a/inyoka/locale/django.pot b/inyoka/locale/django.pot index e803afe3e..4acf512a4 100644 --- a/inyoka/locale/django.pot +++ b/inyoka/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2020. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.23.0\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2020-11-07 18:18+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "\"%(fingerprint)s\" is not a valid GPG Fingerprint." diff --git a/inyoka/markup/base.py b/inyoka/markup/base.py index 3a8fdc8e8..887275495 100644 --- a/inyoka/markup/base.py +++ b/inyoka/markup/base.py @@ -11,7 +11,7 @@ from urllib.parse import urlsplit from functools import partial -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.markup import nodes from inyoka.markup.constants import HTML_COLORS diff --git a/inyoka/markup/lexer.py b/inyoka/markup/lexer.py index 370f0f791..3633724d1 100644 --- a/inyoka/markup/lexer.py +++ b/inyoka/markup/lexer.py @@ -13,7 +13,7 @@ import re -from django.utils.encoding import smart_text +from django.utils.encoding import smart_str from inyoka.markup.parsertools import TokenStream @@ -498,7 +498,7 @@ def tokenize(self, string): open_blocks = [False] def tokenize_buffer(): - for item in tokenize_block('\n'.join(smart_text(obj) for obj in buffer)): + for item in tokenize_block('\n'.join(smart_str(obj) for obj in buffer)): yield item del buffer[:] diff --git a/inyoka/markup/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/markup/locale/de_DE/LC_MESSAGES/django.mo index 6f3b74a0e..27339a2ee 100644 Binary files a/inyoka/markup/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/markup/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/markup/locale/de_DE/LC_MESSAGES/django.po b/inyoka/markup/locale/de_DE/LC_MESSAGES/django.po index 9b2c0b3bb..c72813f90 100644 --- a/inyoka/markup/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/markup/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-01-25 20:47+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2017-03-23 22:51+0000\n" "Last-Translator: Lyra\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" msgid "Conflict End" msgstr "Konlikt Ende" diff --git a/inyoka/markup/locale/django.pot b/inyoka/markup/locale/django.pot index 12adb5d14..388e09782 100644 --- a/inyoka/markup/locale/django.pot +++ b/inyoka/markup/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2019. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.17.6\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-01-25 20:47+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" msgid "Conflict End" msgstr "" diff --git a/inyoka/markup/machine.py b/inyoka/markup/machine.py index 9a529e9c0..86dab4df9 100644 --- a/inyoka/markup/machine.py +++ b/inyoka/markup/machine.py @@ -13,7 +13,7 @@ """ from pickle import dumps, loads, HIGHEST_PROTOCOL -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.utils import get_request_context diff --git a/inyoka/markup/macros.py b/inyoka/markup/macros.py index 0f806d521..f336113ee 100644 --- a/inyoka/markup/macros.py +++ b/inyoka/markup/macros.py @@ -27,7 +27,7 @@ """ from datetime import datetime -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.markup import nodes from inyoka.markup.utils import debug_repr, filter_style, ArgumentCollector diff --git a/inyoka/markup/nodes.py b/inyoka/markup/nodes.py index b57a5d2cd..5c2203859 100644 --- a/inyoka/markup/nodes.py +++ b/inyoka/markup/nodes.py @@ -18,19 +18,19 @@ :copyright: (c) 2007-2023 by the Inyoka Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ -from urllib.parse import urlparse, urlunparse +from urllib.parse import urlparse, urlunparse, quote_plus from django.apps import apps from django.conf import settings from django.utils.html import escape, smart_urlquote -from django.utils.translation import ugettext_lazy, ugettext as _ +from django.utils.translation import gettext_lazy, gettext as _ from inyoka.markup.machine import NodeRenderer, NodeCompiler, NodeQueryInterface from inyoka.markup.utils import debug_repr from inyoka.utils.html import striptags, build_html_tag from inyoka.utils.templating import render_template from inyoka.utils.text import slugify, get_pagetitle, normalize_pagename -from inyoka.utils.urls import href, urlquote_plus +from inyoka.utils.urls import href def error_box(title, message): @@ -465,7 +465,7 @@ def prepare_html(self): self.existing = Page.objects.exists(self.page) url = href('wiki', self.page) if self.anchor: - url += '#' + urlquote_plus(self.anchor) + url += '#' + quote_plus(self.anchor) yield build_html_tag('a', href=url, id=self.id, @@ -717,7 +717,7 @@ class Edited(Element): allowed_in_signatures = False #: Title message for the edited box - msg = ugettext_lazy('Edited by') + msg = gettext_lazy('Edited by') #: CSS Class used for styling css_class = 'edited' @@ -742,7 +742,7 @@ class Moderated(Edited): """ Text that describes a moderation action. """ - msg = ugettext_lazy('Moderated by') + msg = gettext_lazy('Moderated by') css_class = 'moderated' diff --git a/inyoka/markup/templates.py b/inyoka/markup/templates.py index 08a0df000..b03edd867 100644 --- a/inyoka/markup/templates.py +++ b/inyoka/markup/templates.py @@ -30,8 +30,8 @@ import operator from functools import total_ordering, partial -from django.utils.encoding import smart_text -from django.utils.translation import ugettext as _ +from django.utils.encoding import smart_str +from django.utils.translation import gettext as _ from inyoka.markup.base import escape, unescape_string from inyoka.markup.parsertools import TokenStream @@ -110,7 +110,7 @@ def tokenize(self, code): return TokenStream.from_tuple_iter(self._tokenize(code)) def _tokenize(self, code): - code = '\n'.join(smart_text(obj) for obj in code.splitlines()) + code = '\n'.join(smart_str(obj) for obj in code.splitlines()) pos = 0 end = len(code) stack = ['root'] diff --git a/inyoka/markup/transformers.py b/inyoka/markup/transformers.py index 29a7051cf..862ed85f3 100644 --- a/inyoka/markup/transformers.py +++ b/inyoka/markup/transformers.py @@ -18,7 +18,7 @@ import re from django.conf import settings -from django.utils.encoding import smart_text +from django.utils.encoding import smart_str from django.utils.functional import cached_property from inyoka.markup import nodes @@ -187,7 +187,7 @@ def smiley_re(self): As DEFAULT_TRANSFORMERS instances this class and it's passed around, this property will be cached until the python process dies. """ - helper = '|'.join(re.escape(smart_text(s)) for s in self.smilies) + helper = '|'.join(re.escape(smart_str(s)) for s in self.smilies) helper += '|\{(?P[a-z]{2}|[A-Z]{2})\}' regex = ( '(?.*)$', view, {'document_root': settings.MEDIA_ROOT}), + re_path(r'^(?P.*)$', view, {'document_root': settings.MEDIA_ROOT}), ] if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) handler404 = global_not_found diff --git a/inyoka/middlewares/auth.py b/inyoka/middlewares/auth.py index 6e50a5d5c..734dae205 100644 --- a/inyoka/middlewares/auth.py +++ b/inyoka/middlewares/auth.py @@ -14,7 +14,7 @@ from django.utils.crypto import constant_time_compare from django.utils.deprecation import MiddlewareMixin from django.utils.html import escape -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.portal.user import User from inyoka.utils.sessions import set_session_info diff --git a/inyoka/pastebin/forms.py b/inyoka/pastebin/forms.py index 529661f89..ef77e2bed 100644 --- a/inyoka/pastebin/forms.py +++ b/inyoka/pastebin/forms.py @@ -9,64 +9,64 @@ :license: BSD, see LICENSE for more details. """ from django import forms -from django.utils.translation import ugettext, ugettext_lazy +from django.utils.translation import gettext, gettext_lazy from inyoka.pastebin.models import Entry # languages for highlighting. We do not use the full list of pygments # lexers because that is just insane ;-) LANGUAGES = [ - ('text', ugettext_lazy('Plain text')), - ('apache', ugettext_lazy('Apache Config (.htaccess)')), - ('bash', ugettext_lazy('Bash')), - ('bat', ugettext_lazy('Batch (.bat)')), - ('c', ugettext_lazy('C')), - ('csharp', ugettext_lazy('C#')), - ('cpp', ugettext_lazy('C++')), - ('css', ugettext_lazy('CSS')), - ('d', ugettext_lazy('D')), - ('html+django', ugettext_lazy('Django / Jinja Templates')), - ('rhtml', ugettext_lazy('eRuby / rhtml')), - ('html+genshi', ugettext_lazy('Genshi Templates')), - ('haskell', ugettext_lazy('Haskell')), - ('html', ugettext_lazy('HTML')), - ('irc', ugettext_lazy('IRC Logs')), - ('java', ugettext_lazy('Java')), - ('js', ugettext_lazy('JavaScript')), - ('jsp', ugettext_lazy('JSP')), - ('lua', ugettext_lazy('Lua')), - ('html+mako', ugettext_lazy('Mako Templates')), - ('minid', ugettext_lazy('MiniD')), - ('html+myghty', ugettext_lazy('Myghty Templates')), - ('ocaml', ugettext_lazy('OCaml')), - ('perl', ugettext_lazy('Perl')), - ('html+php', ugettext_lazy('PHP')), - ('python', ugettext_lazy('Python')), - ('pycon', ugettext_lazy('Python Console Sessions')), - ('pytb', ugettext_lazy('Python Tracebacks')), - ('rst', ugettext_lazy('reStructuredText')), - ('ruby', ugettext_lazy('Ruby')), - ('scheme', ugettext_lazy('Scheme')), - ('smarty', ugettext_lazy('Smarty')), - ('sourceslist', ugettext_lazy('sources.list')), - ('sql', ugettext_lazy('SQL')), - ('squidconf', ugettext_lazy('SquidConf')), - ('tex', ugettext_lazy('TeX / LaTeX')), - ('diff', ugettext_lazy('Unified Diff')), - ('vim', ugettext_lazy('Vim Scripts')), - ('xml', ugettext_lazy('XML')), + ('text', gettext_lazy('Plain text')), + ('apache', gettext_lazy('Apache Config (.htaccess)')), + ('bash', gettext_lazy('Bash')), + ('bat', gettext_lazy('Batch (.bat)')), + ('c', gettext_lazy('C')), + ('csharp', gettext_lazy('C#')), + ('cpp', gettext_lazy('C++')), + ('css', gettext_lazy('CSS')), + ('d', gettext_lazy('D')), + ('html+django', gettext_lazy('Django / Jinja Templates')), + ('rhtml', gettext_lazy('eRuby / rhtml')), + ('html+genshi', gettext_lazy('Genshi Templates')), + ('haskell', gettext_lazy('Haskell')), + ('html', gettext_lazy('HTML')), + ('irc', gettext_lazy('IRC Logs')), + ('java', gettext_lazy('Java')), + ('js', gettext_lazy('JavaScript')), + ('jsp', gettext_lazy('JSP')), + ('lua', gettext_lazy('Lua')), + ('html+mako', gettext_lazy('Mako Templates')), + ('minid', gettext_lazy('MiniD')), + ('html+myghty', gettext_lazy('Myghty Templates')), + ('ocaml', gettext_lazy('OCaml')), + ('perl', gettext_lazy('Perl')), + ('html+php', gettext_lazy('PHP')), + ('python', gettext_lazy('Python')), + ('pycon', gettext_lazy('Python Console Sessions')), + ('pytb', gettext_lazy('Python Tracebacks')), + ('rst', gettext_lazy('reStructuredText')), + ('ruby', gettext_lazy('Ruby')), + ('scheme', gettext_lazy('Scheme')), + ('smarty', gettext_lazy('Smarty')), + ('sourceslist', gettext_lazy('sources.list')), + ('sql', gettext_lazy('SQL')), + ('squidconf', gettext_lazy('SquidConf')), + ('tex', gettext_lazy('TeX / LaTeX')), + ('diff', gettext_lazy('Unified Diff')), + ('vim', gettext_lazy('Vim Scripts')), + ('xml', gettext_lazy('XML')), ] class AddPasteForm(forms.ModelForm): - title = forms.CharField(max_length=40, required=False, label=ugettext_lazy('Title')) - lang = forms.ChoiceField(widget=forms.Select, label=ugettext_lazy('Language'), + title = forms.CharField(max_length=40, required=False, label=gettext_lazy('Title')) + lang = forms.ChoiceField(widget=forms.Select, label=gettext_lazy('Language'), choices=LANGUAGES) def save(self, user, commit=True): entry = super(AddPasteForm, self).save(commit=False) entry.author = user - entry.title = entry.title or ugettext('Untitled') + entry.title = entry.title or gettext('Untitled') if commit: entry.save() return entry diff --git a/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.mo index 30fa4aa7e..a3f9049f7 100644 Binary files a/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.po b/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.po index 43c866cbc..5122b2d7e 100644 --- a/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/pastebin/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2020-11-07 18:18+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2017-03-23 22:51+0000\n" "Last-Translator: Lyra\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" msgid "Apache Config (.htaccess)" msgstr "Apache Config (.htaccess)" diff --git a/inyoka/pastebin/locale/django.pot b/inyoka/pastebin/locale/django.pot index e9a3f7196..1cc39fa87 100644 --- a/inyoka/pastebin/locale/django.pot +++ b/inyoka/pastebin/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2019. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.17.6\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-01-25 20:47+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" msgid "Apache Config (.htaccess)" msgstr "" diff --git a/inyoka/pastebin/models.py b/inyoka/pastebin/models.py index 2496ff53e..cac5d9d20 100644 --- a/inyoka/pastebin/models.py +++ b/inyoka/pastebin/models.py @@ -11,7 +11,7 @@ from datetime import datetime from django.db import models -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from inyoka.portal.user import User from inyoka.utils.database import PygmentsField @@ -19,16 +19,16 @@ class Entry(models.Model): - title = models.CharField(ugettext_lazy('Title'), max_length=40) - lang = models.CharField(ugettext_lazy('Language'), max_length=20) + title = models.CharField(gettext_lazy('Title'), max_length=40) + lang = models.CharField(gettext_lazy('Language'), max_length=20) code = PygmentsField(application='pastebin') - pub_date = models.DateTimeField(ugettext_lazy('Date'), db_index=True, + pub_date = models.DateTimeField(gettext_lazy('Date'), db_index=True, default=datetime.utcnow) - author = models.ForeignKey(User, verbose_name=ugettext_lazy('Author'), on_delete=models.CASCADE) + author = models.ForeignKey(User, verbose_name=gettext_lazy('Author'), on_delete=models.CASCADE) class Meta: - verbose_name = ugettext_lazy('Entry') - verbose_name_plural = ugettext_lazy('Entries') + verbose_name = gettext_lazy('Entry') + verbose_name_plural = gettext_lazy('Entries') ordering = ('-id',) def get_absolute_url(self, action='show'): diff --git a/inyoka/pastebin/urls.py b/inyoka/pastebin/urls.py index 604ab3c5f..385ac326d 100644 --- a/inyoka/pastebin/urls.py +++ b/inyoka/pastebin/urls.py @@ -9,23 +9,23 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, path, re_path from . import views from ..utils.http import global_not_found, server_error urlpatterns = [ - url(r'^$', views.browse), - url(r'^(\d+)/$', views.display), - url(r'^raw/(\d+)/$', views.raw), - url(r'^delete/(\d+)/$', views.delete), - url(r'^add/$', views.add), + path('', views.browse), + re_path(r'^(\d+)/$', views.display), + re_path(r'^raw/(\d+)/$', views.raw), + re_path(r'^delete/(\d+)/$', views.delete), + path('add/', views.add), ] if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) handler404 = global_not_found diff --git a/inyoka/pastebin/views.py b/inyoka/pastebin/views.py index 874b128e9..5d9cbdd3d 100644 --- a/inyoka/pastebin/views.py +++ b/inyoka/pastebin/views.py @@ -12,7 +12,7 @@ from django.contrib.auth.decorators import login_required, permission_required from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404 -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.pastebin.forms import AddPasteForm from inyoka.pastebin.models import Entry diff --git a/inyoka/planet/forms.py b/inyoka/planet/forms.py index 206b99b5a..2d8b8fdf3 100644 --- a/inyoka/planet/forms.py +++ b/inyoka/planet/forms.py @@ -10,7 +10,7 @@ """ from django import forms from django.core.validators import URLValidator -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from inyoka.utils.forms import UserField from inyoka.planet.models import Blog @@ -18,15 +18,15 @@ class SuggestBlogForm(forms.Form): """Form to suggest a new blog url for the planet.""" - name = forms.CharField(label=ugettext_lazy('Name of the blog')) - url = forms.URLField(label=ugettext_lazy('URL')) - feed_url = forms.URLField(label=ugettext_lazy('Feed URL'), required=False) - description = forms.CharField(label=ugettext_lazy('Description'), + name = forms.CharField(label=gettext_lazy('Name of the blog')) + url = forms.URLField(label=gettext_lazy('URL')) + feed_url = forms.URLField(label=gettext_lazy('Feed URL'), required=False) + description = forms.CharField(label=gettext_lazy('Description'), widget=forms.Textarea) - mine = forms.BooleanField(label=ugettext_lazy('This is my own blog'), + mine = forms.BooleanField(label=gettext_lazy('This is my own blog'), required=False) contact_email = forms.EmailField( - label=ugettext_lazy('Email address of the blog author'), + label=gettext_lazy('Email address of the blog author'), required=False) diff --git a/inyoka/planet/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/planet/locale/de_DE/LC_MESSAGES/django.mo index 7c6532eab..eda91757e 100644 Binary files a/inyoka/planet/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/planet/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/planet/locale/de_DE/LC_MESSAGES/django.po b/inyoka/planet/locale/de_DE/LC_MESSAGES/django.po index 6b9dacca7..7ec9a541b 100644 --- a/inyoka/planet/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/planet/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-01-25 20:47+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2017-03-23 22:51+0000\n" "Last-Translator: Lyra\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(sitename)s planet" diff --git a/inyoka/planet/locale/django.pot b/inyoka/planet/locale/django.pot index b4f916794..99cf1c54d 100644 --- a/inyoka/planet/locale/django.pot +++ b/inyoka/planet/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2019. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.17.6\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2019-01-25 20:47+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(sitename)s planet" diff --git a/inyoka/planet/models.py b/inyoka/planet/models.py index 208650cdb..d1945de9d 100644 --- a/inyoka/planet/models.py +++ b/inyoka/planet/models.py @@ -11,7 +11,7 @@ from django.conf import settings from django.core.cache import cache from django.db import models -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from inyoka.portal.user import User from inyoka.utils.html import striptags @@ -31,15 +31,15 @@ def get_latest_entries(self, count=10): class Blog(models.Model): - name = models.CharField(ugettext_lazy('Name of the blog'), max_length=40) - description = models.TextField(ugettext_lazy('Description'), blank=True, null=True) - blog_url = models.URLField(ugettext_lazy('URL of the blog')) - feed_url = models.URLField(ugettext_lazy('URL of the feed')) - user = models.ForeignKey(User, verbose_name=ugettext_lazy('User'), + name = models.CharField(gettext_lazy('Name of the blog'), max_length=40) + description = models.TextField(gettext_lazy('Description'), blank=True, null=True) + blog_url = models.URLField(gettext_lazy('URL of the blog')) + feed_url = models.URLField(gettext_lazy('URL of the feed')) + user = models.ForeignKey(User, verbose_name=gettext_lazy('User'), blank=True, null=True, on_delete=models.CASCADE) - icon = models.ImageField(ugettext_lazy('Icon'), upload_to='planet/icons', blank=True) + icon = models.ImageField(gettext_lazy('Icon'), upload_to='planet/icons', blank=True) last_sync = models.DateTimeField(blank=True, null=True) - active = models.BooleanField(ugettext_lazy('Index the blog'), default=True) + active = models.BooleanField(gettext_lazy('Index the blog'), default=True) @property def icon_url(self): @@ -113,8 +113,8 @@ def delete(self): super(Entry, self).delete() class Meta: - verbose_name = ugettext_lazy('Entry') - verbose_name_plural = ugettext_lazy('Entries') + verbose_name = gettext_lazy('Entry') + verbose_name_plural = gettext_lazy('Entries') get_latest_by = 'pub_date' ordering = ('-pub_date',) permissions = ( diff --git a/inyoka/planet/tasks.py b/inyoka/planet/tasks.py index fde3e6bff..e626a19d7 100644 --- a/inyoka/planet/tasks.py +++ b/inyoka/planet/tasks.py @@ -26,7 +26,7 @@ import feedparser from celery import shared_task from dateutil.parser import parse as dateutil_parse -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.html import escape # Secure XML libraries till a python solution exists. @@ -161,7 +161,7 @@ def sync(): except AttributeError: max_length = None if isinstance(locals()[n], str): - setattr(entry, n, force_text(locals()[n][:max_length])) + setattr(entry, n, force_str(locals()[n][:max_length])) else: setattr(entry, n, locals()[n]) try: diff --git a/inyoka/planet/urls.py b/inyoka/planet/urls.py index 86668c451..d6e1015c0 100644 --- a/inyoka/planet/urls.py +++ b/inyoka/planet/urls.py @@ -9,28 +9,28 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, path, re_path from . import views from ..utils.http import global_not_found, server_error urlpatterns = [ - url(r'^$', views.index), - url(r'^(\d+)/$', views.index), - url(r'^hide/(?P\d+)/$', views.hide_entry), - url(r'^suggest/$', views.suggest), - url(r'^feeds/(?P[a-z]+)/(?P\d+)/$', views.feed), - url(r'^blogs/$', views.blog_list), - url(r'^blogs/(?P\d)/$', views.blog_list), - url(r'^blogs/export/(?P[a-z]+)/$', views.export), - url(r'^blog/new/$', views.blog_edit), - url(r'^blog/(?P\d+)/edit/$', views.blog_edit), + path('', views.index), + re_path(r'^(\d+)/$', views.index), + path('hide//', views.hide_entry), + path('suggest/', views.suggest), + re_path(r'^feeds/(?P[a-z]+)/(?P\d+)/$', views.feed), + path('blogs/', views.blog_list), + re_path(r'^blogs/(?P\d)/$', views.blog_list), + re_path(r'^blogs/export/(?P[a-z]+)/$', views.export), + path('blog/new/', views.blog_edit), + path('blog//edit/', views.blog_edit), ] if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) handler404 = global_not_found diff --git a/inyoka/planet/views.py b/inyoka/planet/views.py index 9d795c0cb..2589f0d5d 100644 --- a/inyoka/planet/views.py +++ b/inyoka/planet/views.py @@ -16,7 +16,7 @@ from django.db.models import Max from django.utils.html import escape, smart_urlquote from django.utils.text import Truncator -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.planet.forms import EditBlogForm, SuggestBlogForm from inyoka.planet.models import Blog, Entry diff --git a/inyoka/portal/auth.py b/inyoka/portal/auth.py index 5382b704b..d88e4b82e 100644 --- a/inyoka/portal/auth.py +++ b/inyoka/portal/auth.py @@ -9,17 +9,18 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings +from django.contrib.auth.backends import BaseBackend from django.contrib.auth.models import Permission from inyoka.portal.user import User, UserBanned -class InyokaAuthBackend(object): +class InyokaAuthBackend(BaseBackend): """ Customized authentication backend to support Inyoka specific features: * user banning - * workaround for case (in)sensitive user names + * workaround for case (in)sensitive usernames * login by username or email * anonymous permissions """ diff --git a/inyoka/portal/filters.py b/inyoka/portal/filters.py index 4904e2d3f..22467405d 100644 --- a/inyoka/portal/filters.py +++ b/inyoka/portal/filters.py @@ -10,8 +10,8 @@ """ from itertools import chain -from django.utils.encoding import force_text -from django.utils.translation import ugettext_lazy +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy from django_filters import FilterSet, ChoiceFilter from django_filters.widgets import LinkWidget as BaseLinkWidget @@ -21,17 +21,17 @@ SUPPORTED_SUBSCRIPTION_TYPES = { - 'topic': ugettext_lazy('Topic'), - 'forum': ugettext_lazy('Forum'), - 'article': ugettext_lazy('Ikhaya article'), - 'page': ugettext_lazy('Wiki page') + 'topic': gettext_lazy('Topic'), + 'forum': gettext_lazy('Forum'), + 'article': gettext_lazy('Ikhaya article'), + 'page': gettext_lazy('Wiki page') } class LinkWidget(BaseLinkWidget): def render_options(self, choices, selected_choices, name): - selected_choices = set(force_text(v) for v in selected_choices) + selected_choices = set(force_str(v) for v in selected_choices) output = [] for option_value, option_label in chain(self.choices, choices): if option_label: @@ -39,9 +39,9 @@ def render_options(self, choices, selected_choices, name): return '\n'.join(output) def render_option(self, name, selected_choices, option_value, option_label): - option_value = force_text(option_value) + option_value = force_str(option_value) if option_label == '': - option_label = ugettext_lazy('All types') + option_label = gettext_lazy('All types') data = self.data.copy() data[name] = option_value selected = data == self.data or option_value in selected_choices @@ -52,7 +52,7 @@ def render_option(self, name, selected_choices, option_value, option_label): return self.option_string() % { 'attrs': selected and ' class="selected"' or '', 'query_string': url, - 'label': force_text(option_label) + 'label': force_str(option_label) } def option_string(self): @@ -62,7 +62,7 @@ def option_string(self): class SubscriptionFilter(FilterSet): content_type = ChoiceFilter(field_name='content_type__model', label='', choices=tuple(SUPPORTED_SUBSCRIPTION_TYPES.items()), - widget=LinkWidget, empty_label=ugettext_lazy('All types')) + widget=LinkWidget, empty_label=gettext_lazy('All types')) class Meta: model = Subscription diff --git a/inyoka/portal/forms.py b/inyoka/portal/forms.py index 4855ff988..21aec043b 100644 --- a/inyoka/portal/forms.py +++ b/inyoka/portal/forms.py @@ -32,8 +32,8 @@ from django.db.models.functions import Concat from django.forms import HiddenInput, modelformset_factory from django.utils.safestring import mark_safe -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from guardian.shortcuts import assign_perm, remove_perm, get_perms from inyoka.forum.constants import get_simple_version_choices @@ -75,14 +75,14 @@ } NOTIFY_BY_CHOICES = ( - ('mail', ugettext_lazy('Mail')), - ('jabber', ugettext_lazy('Jabber')), + ('mail', gettext_lazy('Mail')), + ('jabber', gettext_lazy('Jabber')), ) NOTIFICATION_CHOICES = ( - ('topic_move', ugettext_lazy('A subscribed topic was moved')), - ('topic_split', ugettext_lazy('A subscribed topic was split')), - ('pm_new', ugettext_lazy('I received a message')) + ('topic_move', gettext_lazy('A subscribed topic was moved')), + ('topic_split', gettext_lazy('A subscribed topic was split')), + ('pm_new', gettext_lazy('I received a message')) ) @@ -91,11 +91,11 @@ class LoginForm(forms.Form): """Simple form for the login dialog""" - username = forms.CharField(label=ugettext_lazy('Username or email address'), + username = forms.CharField(label=gettext_lazy('Username or email address'), widget=forms.TextInput(attrs={'tabindex': '1'})) - password = forms.CharField(label=ugettext_lazy('Password'), required=False, + password = forms.CharField(label=gettext_lazy('Password'), required=False, widget=forms.PasswordInput(render_value=False, attrs={'tabindex': '1'}),) - permanent = forms.BooleanField(label=ugettext_lazy('Keep logged in'), + permanent = forms.BooleanField(label=gettext_lazy('Keep logged in'), required=False, widget=forms.CheckboxInput(attrs={'tabindex': '1'})) def clean(self): @@ -119,18 +119,18 @@ class RegisterForm(forms.Form): techniques for bot catching included e.g a CAPTCHA and a hidden captcha for bots that just fill out everything. """ - username = forms.CharField(label=ugettext_lazy('Username'), max_length=20) - email = EmailField(label=ugettext_lazy('E-mail'), - help_text=ugettext_lazy('We need your email ' + username = forms.CharField(label=gettext_lazy('Username'), max_length=20) + email = EmailField(label=gettext_lazy('E-mail'), + help_text=gettext_lazy('We need your email ' 'address to send you a new password if you forgot it. It is not ' 'visible to other users. For more information, check out our ' 'privacy policy.') % { 'link': href('portal', 'datenschutz')}) - password = forms.CharField(label=ugettext_lazy('Password'), + password = forms.CharField(label=gettext_lazy('Password'), widget=forms.PasswordInput(render_value=False)) - confirm_password = forms.CharField(label=ugettext_lazy('Confirm password'), + confirm_password = forms.CharField(label=gettext_lazy('Confirm password'), widget=forms.PasswordInput(render_value=False)) - captcha = CaptchaField(label=ugettext_lazy('CAPTCHA')) + captcha = CaptchaField(label=gettext_lazy('CAPTCHA')) terms_of_usage = forms.BooleanField() use_required_attribute = False @@ -225,12 +225,12 @@ def get_users(self, email): class ChangePasswordForm(forms.Form): """Simple form for changing the password.""" - old_password = forms.CharField(label=ugettext_lazy('Old password'), + old_password = forms.CharField(label=gettext_lazy('Old password'), widget=forms.PasswordInput) - new_password = forms.CharField(label=ugettext_lazy('New password'), + new_password = forms.CharField(label=gettext_lazy('New password'), widget=forms.PasswordInput) new_password_confirm = forms.CharField( - label=ugettext_lazy('Confirm new password'), + label=gettext_lazy('Confirm new password'), widget=forms.PasswordInput) @@ -239,37 +239,37 @@ class UserCPSettingsForm(forms.Form): Form used for the user control panel – dialog. """ notify = forms.MultipleChoiceField( - label=ugettext_lazy('Notify via'), required=False, + label=gettext_lazy('Notify via'), required=False, choices=NOTIFY_BY_CHOICES, widget=forms.CheckboxSelectMultiple) notifications = forms.MultipleChoiceField( - label=ugettext_lazy('Notify me if'), required=False, + label=gettext_lazy('Notify me if'), required=False, choices=NOTIFICATION_CHOICES, widget=forms.CheckboxSelectMultiple) ubuntu_version = forms.MultipleChoiceField( - label=ugettext_lazy('Notifications on topics with a specific Ubuntu version'), + label=gettext_lazy('Notifications on topics with a specific Ubuntu version'), required=False, widget=forms.CheckboxSelectMultiple) - timezone = forms.ChoiceField(label=ugettext_lazy('Timezone'), required=True, + timezone = forms.ChoiceField(label=gettext_lazy('Timezone'), required=True, choices=list(zip(TIMEZONES, TIMEZONES))) - hide_profile = forms.BooleanField(label=ugettext_lazy('Hide online status'), + hide_profile = forms.BooleanField(label=gettext_lazy('Hide online status'), required=False) - hide_avatars = forms.BooleanField(label=ugettext_lazy('Hide avatars'), + hide_avatars = forms.BooleanField(label=gettext_lazy('Hide avatars'), required=False) - hide_signatures = forms.BooleanField(label=ugettext_lazy('Hide signatures'), + hide_signatures = forms.BooleanField(label=gettext_lazy('Hide signatures'), required=False) autosubscribe = forms.BooleanField(required=False, - label=ugettext_lazy('Subscribe to a topic when replying')) + label=gettext_lazy('Subscribe to a topic when replying')) show_preview = forms.BooleanField(required=False, - label=ugettext_lazy('Attachment preview')) + label=gettext_lazy('Attachment preview')) show_thumbnails = forms.BooleanField(required=False, - label=ugettext_lazy('Picture preview'), - help_text=ugettext_lazy('No effect if “attachment preview” is disabled')) + label=gettext_lazy('Picture preview'), + help_text=gettext_lazy('No effect if “attachment preview” is disabled')) highlight_search = forms.BooleanField(required=False, - label=ugettext_lazy('Highlight search')) + label=gettext_lazy('Highlight search')) mark_read_on_logout = forms.BooleanField(required=False, - label=ugettext_lazy('Mark all forums as “read” on logout')) - reduce_motion = forms.BooleanField(required=False, label=ugettext_lazy('Reduced motion'), - help_text=ugettext_lazy('If enabled, less animations are used.')) + label=gettext_lazy('Mark all forums as “read” on logout')) + reduce_motion = forms.BooleanField(required=False, label=gettext_lazy('Reduced motion'), + help_text=gettext_lazy('If enabled, less animations are used.')) def __init__(self, *args, **kwargs): super(UserCPSettingsForm, self).__init__(*args, **kwargs) @@ -287,16 +287,16 @@ def clean_notify(self): class UserCPProfileForm(forms.ModelForm): - use_gravatar = forms.BooleanField(label=ugettext_lazy('Use Gravatar'), required=False) - email = EmailField(label=ugettext_lazy('Email'), required=True) + use_gravatar = forms.BooleanField(label=gettext_lazy('Use Gravatar'), required=False) + email = EmailField(label=gettext_lazy('Email'), required=True) show_email = forms.BooleanField(required=False) show_jabber = forms.BooleanField(required=False) - coordinates = forms.CharField(label=ugettext_lazy('Coordinates (latitude, longitude)'), + coordinates = forms.CharField(label=gettext_lazy('Coordinates (latitude, longitude)'), required=False) gpgkey = forms.CharField(validators=[validate_gpgkey], min_length=40, max_length=255, - label=ugettext_lazy('GPG fingerprint'), required=False) + label=gettext_lazy('GPG fingerprint'), required=False) userpage = forms.CharField(widget=forms.Textarea, required=False) @@ -455,7 +455,7 @@ class EditUserGroupsForm(forms.Form): 'class': 'portal-user-groupselector'} ) groups = forms.ModelMultipleChoiceField( - label=ugettext_lazy('Please select the groups for this user.'), + label=gettext_lazy('Please select the groups for this user.'), required=False, queryset=Group.objects.all().order_by('name'), widget=groupWidget) def clean_groups(self): @@ -485,14 +485,14 @@ def __init__(self, *args, **kwargs): class CreateUserForm(forms.Form): - username = forms.CharField(label=ugettext_lazy('Username'), max_length=30) - password = forms.CharField(label=ugettext_lazy('Password'), + username = forms.CharField(label=gettext_lazy('Username'), max_length=30) + password = forms.CharField(label=gettext_lazy('Password'), widget=forms.PasswordInput(render_value=False)) - confirm_password = forms.CharField(label=ugettext_lazy('Confirm password'), + confirm_password = forms.CharField(label=gettext_lazy('Confirm password'), widget=forms.PasswordInput(render_value=False)) - email = EmailField(label=ugettext_lazy('Email')) - authenticate = forms.BooleanField(label=ugettext_lazy('Authenticate'), initial=True, - required=False, help_text=(ugettext_lazy('The user will be send a confirmation ' + email = EmailField(label=gettext_lazy('Email')) + authenticate = forms.BooleanField(label=gettext_lazy('Authenticate'), initial=True, + required=False, help_text=(gettext_lazy('The user will be send a confirmation ' 'mail and set to “inactive”.'))) def clean_username(self): @@ -564,9 +564,9 @@ def clean(self): class EditUserPasswordForm(forms.Form): - new_password = forms.CharField(label=ugettext_lazy('New password'), + new_password = forms.CharField(label=gettext_lazy('New password'), required=False, widget=forms.PasswordInput(render_value=False)) - confirm_password = forms.CharField(label=ugettext_lazy('Confirm new password'), + confirm_password = forms.CharField(label=gettext_lazy('Confirm new password'), required=False, widget=forms.PasswordInput(render_value=False)) def clean_confirm_password(self): @@ -588,16 +588,16 @@ def clean_confirm_password(self): class UserMailForm(forms.Form): text = forms.CharField( - label=ugettext_lazy('Text'), + label=gettext_lazy('Text'), widget=forms.Textarea(), - help_text=ugettext_lazy( + help_text=gettext_lazy( 'The message will be send as “plain text”. Your username ' 'will be noted as sender.'), ) class EditGroupForm(forms.ModelForm): - name = forms.CharField(label=ugettext_lazy('Groupname'), required=True) + name = forms.CharField(label=gettext_lazy('Groupname'), required=True) class Meta: model = Group @@ -733,32 +733,32 @@ class GroupGlobalPermissionForm(forms.Form): auth_permissions = forms.MultipleChoiceField( choices=make_permission_choices('auth', AUTH_FILTERED_PERMISSIONS), widget=forms.CheckboxSelectMultiple, - label=ugettext_lazy('Auth'), + label=gettext_lazy('Auth'), required=False) ikhaya_permissions = forms.MultipleChoiceField( choices=make_permission_choices('ikhaya', IKHAYA_FILTERED_PERMISSIONS), widget=forms.CheckboxSelectMultiple, - label=ugettext_lazy('Ikhaya'), + label=gettext_lazy('Ikhaya'), required=False) portal_permissions = forms.MultipleChoiceField( choices=make_permission_choices('portal', PORTAL_FILTERED_PERMISSIONS), widget=forms.CheckboxSelectMultiple, - label=ugettext_lazy('Portal'), + label=gettext_lazy('Portal'), required=False) pastebin_permissions = forms.MultipleChoiceField( choices=make_permission_choices('pastebin', PASTEBIN_FILTERED_PERMISSIONS), widget=forms.CheckboxSelectMultiple, - label=ugettext_lazy('Pastebin'), + label=gettext_lazy('Pastebin'), required=False) planet_permissions = forms.MultipleChoiceField( choices=make_permission_choices('planet', PLANET_FILTERED_PERMISSIONS), widget=forms.CheckboxSelectMultiple, - label=ugettext_lazy('Planet'), + label=gettext_lazy('Planet'), required=False) forum_permissions = forms.MultipleChoiceField( choices=make_permission_choices('forum', FORUM_FILTERED_PERMISSIONS), widget=forms.CheckboxSelectMultiple, - label=ugettext_lazy('Forum'), + label=gettext_lazy('Forum'), required=False) def _clean_permissions(self, modulename): @@ -903,13 +903,13 @@ def save(self, commit=True): class PrivateMessageForm(forms.Form): """Form for writing a new private message""" - recipient = forms.CharField(label=ugettext_lazy('To'), required=False, - help_text=ugettext_lazy('Separate multiple names by semicolon')) - group_recipient = forms.CharField(label=ugettext_lazy('Groups'), required=False, - help_text=ugettext_lazy('Separate multiple groups by semicolon')) - subject = forms.CharField(label=ugettext_lazy('Subject'), + recipient = forms.CharField(label=gettext_lazy('To'), required=False, + help_text=gettext_lazy('Separate multiple names by semicolon')) + group_recipient = forms.CharField(label=gettext_lazy('Groups'), required=False, + help_text=gettext_lazy('Separate multiple groups by semicolon')) + subject = forms.CharField(label=gettext_lazy('Subject'), widget=forms.TextInput(attrs={'size': 50})) - text = forms.CharField(label=ugettext_lazy('Message'), widget=forms.Textarea) + text = forms.CharField(label=gettext_lazy('Message'), widget=forms.Textarea) def clean(self): d = self.cleaned_data @@ -954,13 +954,13 @@ class FeedSelectorForm(forms.Form): count = forms.IntegerField(initial=10, widget=forms.TextInput(attrs={'size': 2, 'maxlength': 3, 'class': 'feed_count'}), - label=ugettext_lazy('Number of entries in the feed'), - help_text=ugettext_lazy('The number will be round off to keep the server ' + label=gettext_lazy('Number of entries in the feed'), + help_text=gettext_lazy('The number will be round off to keep the server ' 'load low.')) mode = forms.ChoiceField(initial='short', - choices=(('full', ugettext_lazy('Full article')), - ('short', ugettext_lazy('Only introduction')), - ('title', ugettext_lazy('Only title'))), + choices=(('full', gettext_lazy('Full article')), + ('short', gettext_lazy('Only introduction')), + ('title', gettext_lazy('Only title'))), widget=forms.RadioSelect(attrs={'class': 'radioul'})) def clean(self): @@ -982,7 +982,7 @@ def clean_forum(self): class IkhayaFeedSelectorForm(FeedSelectorForm): - category = forms.ChoiceField(label=ugettext_lazy('Category')) + category = forms.ChoiceField(label=gettext_lazy('Category')) class PlanetFeedSelectorForm(FeedSelectorForm): @@ -993,7 +993,7 @@ class WikiFeedSelectorForm(FeedSelectorForm): #: `mode` is never used but needs to be overwritten because of that. mode = forms.ChoiceField(required=False) page = forms.CharField(label=_('Page name'), required=False, - help_text=(ugettext_lazy('If not given, the last changes will ' + help_text=(gettext_lazy('If not given, the last changes will ' 'be displayed.'))) @@ -1060,54 +1060,54 @@ def save(self, commit=True): class ConfigurationForm(forms.Form): - global_message = forms.CharField(label=ugettext_lazy('Global Message'), + global_message = forms.CharField(label=gettext_lazy('Global Message'), widget=forms.Textarea(attrs={'rows': 3}), required=False, - help_text=ugettext_lazy('This message will displayed on every page in the ' + help_text=gettext_lazy('This message will displayed on every page in the ' 'header. To disable it, leave the field empty.')) - welcome_message = forms.CharField(label=ugettext_lazy('Welcome Message'), + welcome_message = forms.CharField(label=gettext_lazy('Welcome Message'), widget=forms.Textarea(attrs={'rows': 5}), required=False, - help_text=ugettext_lazy('This is the welcome message displayed on the main page.')) - blocked_hosts = forms.CharField(label=ugettext_lazy('Blocked hosts for email addresses'), + help_text=gettext_lazy('This is the welcome message displayed on the main page.')) + blocked_hosts = forms.CharField(label=gettext_lazy('Blocked hosts for email addresses'), widget=forms.Textarea(attrs={'rows': 5}), required=False, - help_text=ugettext_lazy('Users cannot use email addresses from these hosts to ' + help_text=gettext_lazy('Users cannot use email addresses from these hosts to ' 'register an account.')) - team_icon = forms.ImageField(label=ugettext_lazy('Global team icon'), required=False, - help_text=ugettext_lazy('Please note the details on the maximum size below.')) + team_icon = forms.ImageField(label=gettext_lazy('Global team icon'), required=False, + help_text=gettext_lazy('Please note the details on the maximum size below.')) wiki_newpage_template = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 5}), - label=ugettext_lazy('Default text of new wiki pages')) + label=gettext_lazy('Default text of new wiki pages')) wiki_newpage_root = forms.CharField(required=False, - label=ugettext_lazy('Location of new wiki pages')) + label=gettext_lazy('Location of new wiki pages')) wiki_newpage_infopage = forms.CharField(required=False, - label=ugettext_lazy('Information page about new wiki pages'), - help_text=ugettext_lazy('Information page to which a “create” link should ' + label=gettext_lazy('Information page about new wiki pages'), + help_text=gettext_lazy('Information page to which a “create” link should ' 'redirect to.')) wiki_edit_note = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 5}), - label=ugettext_lazy('Wiki helptext'), - help_text=ugettext_lazy('This text appears above the wiki editor.')) - license_note = forms.CharField(required=False, label=ugettext_lazy('License note'), + label=gettext_lazy('Wiki helptext'), + help_text=gettext_lazy('This text appears above the wiki editor.')) + license_note = forms.CharField(required=False, label=gettext_lazy('License note'), widget=forms.Textarea(attrs={'rows': 2})) countdown_active = forms.BooleanField(required=False, - label=ugettext_lazy('Display countdown')) + label=gettext_lazy('Display countdown')) countdown_target_page = forms.CharField(required=False, - label=ugettext_lazy('Full path to the target link page')) + label=gettext_lazy('Full path to the target link page')) countdown_image_url = forms.CharField(required=False, - label=ugettext_lazy('Image URL'), - help_text=ugettext_lazy('The complete URL to the countdown banner. ' + label=gettext_lazy('Image URL'), + help_text=gettext_lazy('The complete URL to the countdown banner. ' 'Use %(remaining)s to be replaced by the ' 'remaining days or soon.')) - countdown_date = forms.DateField(label=ugettext_lazy('Release date'), + countdown_date = forms.DateField(label=gettext_lazy('Release date'), required=False, widget=DateWidget, localize=True) distri_versions = forms.CharField(required=False, widget=HiddenInput()) ikhaya_description = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 5}), - label=ugettext_lazy('Description about Ikhaya that will be used ' + label=gettext_lazy('Description about Ikhaya that will be used ' 'on the start page and in the feed aggregations.')) planet_description = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 5}), - label=ugettext_lazy('Description about the planet that will be used ' + label=gettext_lazy('Description about the planet that will be used ' 'on the planet page and in the feed aggregations.')) def clean_distri_versions(self): @@ -1132,7 +1132,7 @@ def clean_countdown_image_url(self): class TokenForm(forms.Form): token = forms.CharField( - label=ugettext_lazy('Please enter the string which was sent to you by email'), + label=gettext_lazy('Please enter the string which was sent to you by email'), widget=forms.Textarea()) def __init__(self, *args, **kwargs): diff --git a/inyoka/portal/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/portal/locale/de_DE/LC_MESSAGES/django.mo index 617c71c77..88b7a8ba0 100644 Binary files a/inyoka/portal/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/portal/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/portal/locale/de_DE/LC_MESSAGES/django.po b/inyoka/portal/locale/de_DE/LC_MESSAGES/django.po index 530c11231..64979a454 100644 --- a/inyoka/portal/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/portal/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2020-11-07 18:18+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2020-11-07 18:27+0100\n" "Last-Translator: Christoph Volkert <>\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(sitename)s - Message from %(username)s" @@ -413,9 +413,6 @@ msgstr "Wohnort" msgid "Restore" msgstr "Wiederherstellen" -msgid "Send" -msgstr "Senden" - msgid "Sent" msgstr "Gesendet" @@ -782,4 +779,3 @@ msgstr "leer lassen, um dauerhaft zu sperren (wirkt nur, wenn Status = gesperrt) msgid "not yet activated" msgstr "noch nicht aktiviert" - diff --git a/inyoka/portal/locale/django.pot b/inyoka/portal/locale/django.pot index 61e4f0d03..19e11bdb9 100644 --- a/inyoka/portal/locale/django.pot +++ b/inyoka/portal/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2020. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.23.0\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2020-11-07 18:18+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(sitename)s - Message from %(username)s" @@ -412,9 +412,6 @@ msgstr "" msgid "Restore" msgstr "" -msgid "Send" -msgstr "" - msgid "Sent" msgstr "" diff --git a/inyoka/portal/management/commands/create_superuser.py b/inyoka/portal/management/commands/create_superuser.py index 0e8560506..72f010d5c 100644 --- a/inyoka/portal/management/commands/create_superuser.py +++ b/inyoka/portal/management/commands/create_superuser.py @@ -5,7 +5,7 @@ This module provides a command to the Django ``manage.py`` file to add a new user to the user table with full permissions on all forums that exist - and will all rights to modify e.g. users or user content (e.g forum, + and will all rights to modify e.g. users or user content (e.g. forum, ikhaya, wiki, etc.) :copyright: (c) 2011-2023 by the Inyoka Team, see AUTHORS for more details. diff --git a/inyoka/portal/management/commands/makemessages.py b/inyoka/portal/management/commands/makemessages.py index 05c75aa76..7172e6a96 100644 --- a/inyoka/portal/management/commands/makemessages.py +++ b/inyoka/portal/management/commands/makemessages.py @@ -28,8 +28,8 @@ def handle(self, *args, **options): babel_cfg_path = path.abspath('extra/babel.cfg') args_extract = [ 'pybabel', 'extract', '-F', babel_cfg_path, - '-k', '_', '-k', 'gettext', '-k', 'pgettext:1c,2', '-k', - 'ugettext', '-k', 'ugettext_lazy', '-k', 'ungettext_lazy', + '-k', '_', '-k', 'gettext', '-k', 'pgettext:1c,2', + '-k', 'gettext_lazy', '-k', 'ngettext_lazy', '--no-wrap', '--no-location', '--sort-output', '--copyright-holder=Inyoka Team (see AUTHORS)', '--project=Inyoka Project', '--version=' + INYOKA_VERSION @@ -70,7 +70,7 @@ def _make_theme_messages(self, args_extract, args_update): cwd = path.normpath(path.join(base_path, '..')) basename = path.basename(base_path) locale_dir = path.join(basename, 'locale') - template_dir = path.join(basename, 'templates') + template_dir = path.join(basename, 'jinja2') args = args_extract + [ '-o', path.join(locale_dir, 'django.pot'), template_dir, diff --git a/inyoka/portal/management/commands/renameusers.py b/inyoka/portal/management/commands/renameusers.py index 33f768960..b4d4faf31 100644 --- a/inyoka/portal/management/commands/renameusers.py +++ b/inyoka/portal/management/commands/renameusers.py @@ -13,7 +13,7 @@ import json from django.core.management.base import BaseCommand -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.portal.user import User diff --git a/inyoka/portal/models.py b/inyoka/portal/models.py index 622251b33..096bbb754 100644 --- a/inyoka/portal/models.py +++ b/inyoka/portal/models.py @@ -19,7 +19,7 @@ from django.core.cache import cache from django.core.validators import RegexValidator from django.db import models, transaction -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from werkzeug import cached_property from inyoka.portal.user import User @@ -79,10 +79,10 @@ def mark_read_list(cls, user_id, ids): PRIVMSG_FOLDERS_DATA = ( - (0, 'sent', ugettext_lazy('Sent')), - (1, 'inbox', ugettext_lazy('Inbox')), - (2, 'trash', ugettext_lazy('Trash')), - (3, 'archive', ugettext_lazy('Archive'))) + (0, 'sent', gettext_lazy('Sent')), + (1, 'inbox', gettext_lazy('Inbox')), + (2, 'trash', gettext_lazy('Trash')), + (3, 'archive', gettext_lazy('Archive'))) PRIVMSG_FOLDERS = {} @@ -96,9 +96,9 @@ class PrivateMessage(models.Model): This model represent one of these messages. """ author = models.ForeignKey(User, on_delete=models.CASCADE) - subject = models.CharField(ugettext_lazy('Title'), max_length=255) - pub_date = models.DateTimeField(ugettext_lazy('Date')) - text = InyokaMarkupField(verbose_name=ugettext_lazy('Text'), application='portal') + subject = models.CharField(gettext_lazy('Title'), max_length=255) + pub_date = models.DateTimeField(gettext_lazy('Date')) + text = InyokaMarkupField(verbose_name=gettext_lazy('Text'), application='portal') class Meta: ordering = ('-pub_date',) @@ -146,8 +146,8 @@ class PrivateMessageEntry(models.Model): """ message = models.ForeignKey('PrivateMessage', on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE) - read = models.BooleanField(ugettext_lazy('Read'), default=False) - folder = models.SmallIntegerField(ugettext_lazy('Folder'), + read = models.BooleanField(gettext_lazy('Read'), default=False) + folder = models.SmallIntegerField(gettext_lazy('Folder'), null=True, choices=[(f[0], f[1]) for f in PRIVMSG_FOLDERS_DATA]) @@ -220,21 +220,21 @@ class StaticPage(models.Model): """ Stores static pages (imprint, license, etc.) """ - key = models.SlugField(ugettext_lazy('Key'), + key = models.SlugField(gettext_lazy('Key'), max_length=25, primary_key=True, unique=True, db_index=True, - help_text=ugettext_lazy('Will be used to generate the URL. ' + help_text=gettext_lazy('Will be used to generate the URL. ' 'Cannot be changed later.')) - title = models.CharField(ugettext_lazy('Title'), max_length=200) + title = models.CharField(gettext_lazy('Title'), max_length=200) content = InyokaMarkupField( - verbose_name=ugettext_lazy('Content'), - help_text=ugettext_lazy('Inyoka syntax required.'), + verbose_name=gettext_lazy('Content'), + help_text=gettext_lazy('Inyoka syntax required.'), application='portal', ) class Meta: - verbose_name = ugettext_lazy('Static page') - verbose_name_plural = ugettext_lazy('Static pages') + verbose_name = gettext_lazy('Static page') + verbose_name_plural = gettext_lazy('Static pages') def __repr__(self): return '<%s:%s "%s">' % ( @@ -255,18 +255,18 @@ def get_absolute_url(self, action='show'): class StaticFile(models.Model): - identifier = models.CharField(ugettext_lazy('Identifier'), + identifier = models.CharField(gettext_lazy('Identifier'), max_length=100, unique=True, db_index=True) - file = models.FileField(ugettext_lazy('File'), upload_to='portal/files') + file = models.FileField(gettext_lazy('File'), upload_to='portal/files') is_ikhaya_icon = models.BooleanField( - ugettext_lazy('Is Ikhaya icon'), + gettext_lazy('Is Ikhaya icon'), default=False, - help_text=ugettext_lazy('Choose this if the file should appear ' + help_text=gettext_lazy('Choose this if the file should appear ' 'as a article or category icon possibility')) class Meta: - verbose_name = ugettext_lazy('Static file') - verbose_name_plural = ugettext_lazy('Static files') + verbose_name = gettext_lazy('Static file') + verbose_name_plural = gettext_lazy('Static files') def __str__(self): return self.identifier @@ -288,7 +288,7 @@ class Subscription(models.Model): objects = SubscriptionManager() user = models.ForeignKey(User, on_delete=models.CASCADE) notified = models.BooleanField( - ugettext_lazy('User was already notified'), + gettext_lazy('User was already notified'), default=False) ubuntu_version = models.CharField(max_length=5, null=True) @@ -436,12 +436,12 @@ class Linkmap(models.Model): CACHE_KEY_CSS = 'portal:linkmap:css-filname' token_validator = RegexValidator(regex=r'^[a-z\-_]+[1-9]*$', - message=ugettext_lazy(u'Only lowercase letters, - and _ allowed. Numbers as postfix.')) + message=gettext_lazy(u'Only lowercase letters, - and _ allowed. Numbers as postfix.')) - token = models.CharField(ugettext_lazy(u'Token'), max_length=128, unique=True, + token = models.CharField(gettext_lazy(u'Token'), max_length=128, unique=True, validators=[token_validator]) - url = models.URLField(ugettext_lazy(u'Link')) - icon = models.ImageField(ugettext_lazy(u'Icon'), upload_to='linkmap/icons', blank=True) + url = models.URLField(gettext_lazy(u'Link')) + icon = models.ImageField(gettext_lazy(u'Icon'), upload_to='linkmap/icons', blank=True) objects = LinkmapManager() diff --git a/inyoka/portal/services.py b/inyoka/portal/services.py index 19c1943f1..996d0c9ac 100644 --- a/inyoka/portal/services.py +++ b/inyoka/portal/services.py @@ -34,7 +34,7 @@ def autocompletable(string): """ Returns `True` if `string` is autocompletable, e.g. at least - as long than `MIN_AUTOCOMPLETE_CHARS`. + as long as `MIN_AUTOCOMPLETE_CHARS`. """ return len(string) >= MIN_AUTOCOMPLETE_CHARS diff --git a/inyoka/portal/urls.py b/inyoka/portal/urls.py index 6951960b8..1e31e2118 100644 --- a/inyoka/portal/urls.py +++ b/inyoka/portal/urls.py @@ -9,92 +9,92 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, path, re_path from . import views from ..utils.http import global_not_found, server_error urlpatterns = [ - url(r'^$', views.index), - url(r'^login/$', views.login), - url(r'^logout/$', views.logout), - url(r'^users/$', views.memberlist), - url(r'^users/(?P\d+)/$', views.memberlist), - url(r'^user/new/$', views.user_new), - url(r'^user/(?P[^/]+)/$', views.profile), - url(r'^user/(?P[^/]+)/subscribe/$', views.subscribe_user), - url(r'^user/(?P[^/]+)/unsubscribe/$', views.unsubscribe_user), - url(r'^user/(?P[^/]+)/edit/$', views.user_edit), - url(r'^user/(?P[^/]+)/edit/profile/$', views.user_edit_profile), - url(r'^user/(?P[^/]+)/edit/settings/$', views.user_edit_settings), - url(r'^user/(?P[^/]+)/edit/groups/$', views.user_edit_groups), - url(r'^user/(?P[^/]+)/edit/status/$', views.user_edit_status), - url(r'^user/(?P[^/]+)/mail/$', views.user_mail), - url(r'^users/resend_activation_mail/$', views.admin_resend_activation_mail), - url(r'^groups/$', views.grouplist), - url(r'^groups/(?P\d+)/$', views.grouplist), - url(r'^group/new/$', views.group_new), - url(r'^group/(?P[^/]+)/$', views.group), - url(r'^group/(?P[^/]+)/edit/$', views.group_edit), - url(r'^group/(?P[^/]+)/edit/global_permissions/$', views.group_edit_global_permissions), - url(r'^group/(?P[^/]+)/edit/forum_permissions/$', views.group_edit_forum_permissions), - url(r'^group/(?P[^/]+)/(?P\d+)/$', views.group), - url(r'^usercp/$', views.usercp), - url(r'^usercp/settings/$', views.usercp_settings), - url(r'^usercp/profile/$', views.usercp_profile), - url(r'^usercp/password/$', views.usercp_password), - url(r'^usercp/subscriptions/$', views.usercp_subscriptions), - url(r'^usercp/subscriptions/(?P\d+)/$', views.usercp_subscriptions), - url(r'^usercp/deactivate/$', views.usercp_deactivate), - url(r'^privmsg/$', views.privmsg), - url(r'^privmsg/new/$', views.privmsg_new), - url(r'^privmsg/new/(?P.+)/$', views.privmsg_new), - url(r'^privmsg/(?P[a-z]+)/$', views.privmsg), - url(r'^privmsg/(?P[a-z]+)/page/$', views.privmsg), - url(r'^privmsg/(?P[a-z]+)/page/(?P\d+)/$', views.privmsg), - url(r'^privmsg/(?P[a-z]+)/all/$', views.privmsg, {'one_page': True}), - url(r'^privmsg/(?P\d+)/$', views.privmsg), - url(r'^privmsg/(?P[a-z]+)/(?P\d+)/$', views.privmsg), - url(r'^map/$', views.usermap), - url(r'^whoisonline/$', views.whoisonline), - url(r'^inyoka/$', views.about_inyoka), - url(r'^register/$', views.register), - url(r'^(?Pactivate|delete)/(?P[^/]+)/(?P.*?)/$', views.activate), - url(r'^confirm/(?Preactivate_user|set_new_email|reset_email)/$', views.confirm), - url(r'^lost_password/$', views.InyokaPasswordResetView.as_view()), - url(r'^lost_password/(?P[0-9A-Za-z_\-]+)/(?P.+)/$', views.InyokaPasswordResetConfirmView.as_view()), - url(r'^feeds/$', views.feedselector), - url(r'^feeds/(?P[^/]+)/$', views.feedselector), - url(r'^calendar/$', views.calendar_overview), - url(r'^calendar/(?P\d{4})/(?P(0?\d|1[0-2]))/$', views.calendar_month), - url(r'^calendar/(?P.*?)/ics/$', views.calendar_ical), - url(r'^calendar/(?P.*?)/$', views.calendar_detail), - url(r'^config/$', views.config), - url(r'^linkmap/$', views.linkmap_edit), - url(r'^linkmap/export/$', views.linkmap_export), + path('', views.index), + path('login/', views.login), + path('logout/', views.logout), + path('users/', views.memberlist), + path('users//', views.memberlist), + path('user/new/', views.user_new), + path('user//', views.profile), + path('user//subscribe/', views.subscribe_user), + path('user//unsubscribe/', views.unsubscribe_user), + path('user//edit/', views.user_edit), + path('user//edit/profile/', views.user_edit_profile), + path('user//edit/settings/', views.user_edit_settings), + path('user//edit/groups/', views.user_edit_groups), + path('user//edit/status/', views.user_edit_status), + path('user//mail/', views.user_mail), + path('users/resend_activation_mail/', views.admin_resend_activation_mail), + path('groups/', views.grouplist), + path('groups//', views.grouplist), + path('group/new/', views.group_new), + path('group//', views.group), + path('group//edit/', views.group_edit), + path('group//edit/global_permissions/', views.group_edit_global_permissions), + path('group//edit/forum_permissions/', views.group_edit_forum_permissions), + path('group///', views.group), + path('usercp/', views.usercp), + path('usercp/settings/', views.usercp_settings), + path('usercp/profile/', views.usercp_profile), + path('usercp/password/', views.usercp_password), + path('usercp/subscriptions/', views.usercp_subscriptions), + path('usercp/subscriptions//', views.usercp_subscriptions), + path('usercp/deactivate/', views.usercp_deactivate), + path('privmsg/', views.privmsg), + path('privmsg/new/', views.privmsg_new), + path('privmsg/new//', views.privmsg_new), + re_path(r'^privmsg/(?P[a-z]+)/$', views.privmsg), + re_path(r'^privmsg/(?P[a-z]+)/page/$', views.privmsg), + re_path(r'^privmsg/(?P[a-z]+)/page/(?P\d+)/$', views.privmsg), + re_path(r'^privmsg/(?P[a-z]+)/all/$', views.privmsg, {'one_page': True}), + path('privmsg//', views.privmsg), + re_path(r'^privmsg/(?P[a-z]+)/(?P\d+)/$', views.privmsg), + path('map/', views.usermap), + path('whoisonline/', views.whoisonline), + path('inyoka/', views.about_inyoka), + path('register/', views.register), + re_path(r'^(?Pactivate|delete)/(?P[^/]+)/(?P.*?)/$', views.activate), + re_path(r'^confirm/(?Preactivate_user|set_new_email|reset_email)/$', views.confirm), + path('lost_password/', views.InyokaPasswordResetView.as_view()), + re_path(r'^lost_password/(?P[0-9A-Za-z_\-]+)/(?P.+)/$', views.InyokaPasswordResetConfirmView.as_view()), + path('feeds/', views.feedselector), + path('feeds//', views.feedselector), + path('calendar/', views.calendar_overview), + re_path(r'^calendar/(?P\d{4})/(?P(0?\d|1[0-2]))/$', views.calendar_month), + re_path(r'^calendar/(?P.*?)/ics/$', views.calendar_ical), + re_path(r'^calendar/(?P.*?)/$', views.calendar_detail), + path('config/', views.config), + path('linkmap/', views.linkmap_edit), + path('linkmap/export/', views.linkmap_export), # shortcuts - url(r'^ikhaya/(\d+)/$', views.ikhaya_redirect), + re_path(r'^ikhaya/(\d+)/$', views.ikhaya_redirect), # static files - url(r'^files/$', views.files), - url(r'^files/(?P\d+)/$', views.files), - url(r'^files/new/$', views.file_edit), - url(r'^files/(?P.+)/edit/$', views.file_edit), - url(r'^files/(?P.+)/delete/$', views.file_delete), + path('files/', views.files), + path('files//', views.files), + path('files/new/', views.file_edit), + path('files//edit/', views.file_edit), + path('files//delete/', views.file_delete), # static pages - url(r'^pages/$', views.pages), - url(r'^page/new/$', views.page_edit), + path('pages/', views.pages), + path('page/new/', views.page_edit), ] urlpatterns.extend([ - url(r'^([^/]+)/$', views.static_page), - url(r'^([^/]+)/edit/$', views.page_edit), - url(r'^(?P[^/]+)/delete/$', views.page_delete), + re_path(r'^([^/]+)/$', views.static_page), + re_path(r'^([^/]+)/edit/$', views.page_edit), + path('/delete/', views.page_delete), ]) if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) handler404 = global_not_found diff --git a/inyoka/portal/user.py b/inyoka/portal/user.py index 96f26e3fa..32773ee15 100644 --- a/inyoka/portal/user.py +++ b/inyoka/portal/user.py @@ -27,8 +27,8 @@ from django.db import models, transaction from django.dispatch import receiver from django.utils.html import escape -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from guardian.mixins import GuardianUserMixin from guardian.shortcuts import get_perms @@ -183,7 +183,7 @@ def send_activation_mail(user): class UserManager(BaseUserManager): def get_by_username_or_email(self, name): - """Get a user by it's username or email address""" + """Get a user by its username or email address""" try: user = User.objects.get(username__iexact=name) except User.DoesNotExist as exc: @@ -198,10 +198,12 @@ def create_user(self, username, email, password=None): now = datetime.utcnow() user = self.model(username=username, email=email.strip().lower(), status=User.STATUS_INACTIVE, date_joined=now, last_login=now) + if password: user.set_password(password) else: user.set_unusable_password() + user.save() return user @@ -260,50 +262,50 @@ class User(AbstractBaseUser, PermissionsMixin, GuardianUserMixin): STATUS_BANNED = 2 STATUS_DELETED = 3 STATUS_CHOICES = ( - (STATUS_INACTIVE, ugettext_lazy('not yet activated')), - (STATUS_ACTIVE, ugettext_lazy('active')), - (STATUS_BANNED, ugettext_lazy('banned')), - (STATUS_DELETED, ugettext_lazy('deleted himself')), + (STATUS_INACTIVE, gettext_lazy('not yet activated')), + (STATUS_ACTIVE, gettext_lazy('active')), + (STATUS_BANNED, gettext_lazy('banned')), + (STATUS_DELETED, gettext_lazy('deleted himself')), ) #: Assign the `username` field USERNAME_FIELD = 'username' objects = UserManager() - username = models.CharField(verbose_name=ugettext_lazy('Username'), + username = models.CharField(verbose_name=gettext_lazy('Username'), max_length=30, unique=True, db_index=True) - email = models.EmailField(verbose_name=ugettext_lazy('Email address'), + email = models.EmailField(verbose_name=gettext_lazy('Email address'), unique=True, db_index=True) - status = models.IntegerField(verbose_name=ugettext_lazy('Activation status'), + status = models.IntegerField(verbose_name=gettext_lazy('Activation status'), default=STATUS_INACTIVE, choices=STATUS_CHOICES) - date_joined = models.DateTimeField(verbose_name=ugettext_lazy('Member since'), + date_joined = models.DateTimeField(verbose_name=gettext_lazy('Member since'), default=datetime.utcnow) - banned_until = models.DateTimeField(verbose_name=ugettext_lazy('Banned until'), + banned_until = models.DateTimeField(verbose_name=gettext_lazy('Banned until'), null=True, blank=True, - help_text=ugettext_lazy('leave empty to ban permanent')) + help_text=gettext_lazy('leave empty to ban permanent')) # profile attributes - avatar = models.ImageField(ugettext_lazy('Avatar'), upload_to=upload_to_avatar, + avatar = models.ImageField(gettext_lazy('Avatar'), upload_to=upload_to_avatar, blank=True, null=True) - jabber = models.CharField(ugettext_lazy('Jabber'), max_length=200, blank=True) - signature = InyokaMarkupField(verbose_name=ugettext_lazy('Signature'), blank=True) - location = models.CharField(ugettext_lazy('Residence'), max_length=200, blank=True) - gpgkey = models.CharField(ugettext_lazy('GPG fingerprint'), max_length=255, blank=True) - website = models.URLField(ugettext_lazy('Website'), blank=True) - launchpad = models.CharField(ugettext_lazy('Launchpad username'), max_length=50, blank=True) - settings = JSONField(ugettext_lazy('Settings'), default={}) + jabber = models.CharField(gettext_lazy('Jabber'), max_length=200, blank=True) + signature = InyokaMarkupField(verbose_name=gettext_lazy('Signature'), blank=True) + location = models.CharField(gettext_lazy('Residence'), max_length=200, blank=True) + gpgkey = models.CharField(gettext_lazy('GPG fingerprint'), max_length=255, blank=True) + website = models.URLField(gettext_lazy('Website'), blank=True) + launchpad = models.CharField(gettext_lazy('Launchpad username'), max_length=50, blank=True) + settings = JSONField(gettext_lazy('Settings'), default={}) # forum attribute - forum_read_status = models.BinaryField(ugettext_lazy('Read posts'), blank=True) + forum_read_status = models.BinaryField(gettext_lazy('Read posts'), blank=True) # member title - member_title = models.CharField(ugettext_lazy('Team affiliation / Member title'), + member_title = models.CharField(gettext_lazy('Team affiliation / Member title'), blank=True, null=True, max_length=200) # member icon - icon = models.FilePathField(ugettext_lazy('Group icon'), + icon = models.FilePathField(gettext_lazy('Group icon'), path=os.path.join(inyoka_settings.MEDIA_ROOT, 'portal/team_icons'), match='.*\.png', blank=True, null=True, recursive=True) diff --git a/inyoka/portal/utils.py b/inyoka/portal/utils.py index 80c786b20..05da85ebd 100644 --- a/inyoka/portal/utils.py +++ b/inyoka/portal/utils.py @@ -15,7 +15,7 @@ from django.db import transaction from django.db.models import Q from django.http import HttpResponseRedirect -from django.utils.http import urlquote_plus +from urllib.parse import quote_plus from inyoka.utils.http import AccessDeniedResponse from inyoka.utils.storage import storage @@ -77,7 +77,7 @@ def google_calendarize(event): dates += '%2F' + end.strftime(tfmt) else: dates += '%2F' + start.strftime(tfmt) - name = urlquote_plus(event.name) + name = quote_plus(event.name) s = ('https://www.google.com/calendar/event?action=TEMPLATE&' + 'text=' + name + '&' + @@ -85,10 +85,10 @@ def google_calendarize(event): 'sprop=website:ubuntuusers.de') if event.description: - s += s + '&details=' + urlquote_plus(event.description) + s += s + '&details=' + quote_plus(event.description) if event.location: - s = s + '&location=' + urlquote_plus(event.simple_coordinates) + s = s + '&location=' + quote_plus(event.simple_coordinates) return s + '&trp=false' diff --git a/inyoka/portal/views.py b/inyoka/portal/views.py index 64e72ebe2..b8b43de93 100644 --- a/inyoka/portal/views.py +++ b/inyoka/portal/views.py @@ -32,8 +32,8 @@ from django.utils import timezone from django.utils.dates import MONTHS, WEEKDAYS from django.utils.html import escape -from django.utils.translation import ugettext as _ -from django.utils.translation import ungettext +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext from django.views.decorators.http import require_POST from PIL import Image @@ -319,11 +319,11 @@ def activate(request, action='', username='', activation_key=''): class InyokaPasswordResetView(SuccessMessageMixin, PasswordResetView): """ If a users has lost his password, it is here possible to send an email - with an one time link to his account-email-address. With this link he + with a one time link to his account-email-address. With this link he can set a new password at `InyokaPasswordResetConfirmView`. Customized to show an error, if the user is already logged in and - to show an success message. + to show a success message. """ template_name = 'portal/lost_password.html' email_template_name = 'mails/new_user_password.txt' @@ -668,7 +668,7 @@ def post(self, request, *args, **kwargs): if form.is_valid(): d = form.cleaned_data Subscription.objects.delete_list(request.user.id, d['select']) - msg = ungettext('A subscription was deleted.', + msg = ngettext('A subscription was deleted.', '%(n)d subscriptions were deleted.', len(d['select'])) messages.success(request, msg % {'n': len(d['select'])}) @@ -678,7 +678,7 @@ def post(self, request, *args, **kwargs): if form.is_valid(): d = form.cleaned_data Subscription.objects.mark_read_list(request.user.id, d['select']) - msg = ungettext('A subscription was marked as read.', + msg = ngettext('A subscription was marked as read.', '%(n)d subscriptions were marked as read.', len(d['select'])) messages.success(request, msg % {'n': len(d['select'])}) @@ -947,7 +947,7 @@ def privmsg(request, folder=None, entry_id=None, page=1, one_page=False): if form.is_valid(): d = form.cleaned_data PrivateMessageEntry.delete_list(request.user.id, d['delete']) - msg = ungettext('A message was deleted.', + msg = ngettext('A message was deleted.', '%(n)d messages were deleted.', len(d['delete'])) messages.success(request, msg % {'n': len(d['delete'])}) diff --git a/inyoka/static_urls.py b/inyoka/static_urls.py index a8af40b87..345f8b562 100644 --- a/inyoka/static_urls.py +++ b/inyoka/static_urls.py @@ -9,19 +9,19 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, path, re_path from django.views.static import serve as view from inyoka.utils.http import global_not_found, server_error urlpatterns = [ - url(r'^(?P.*)$', view, {'document_root': settings.STATIC_ROOT}), + re_path(r'^(?P.*)$', view, {'document_root': settings.STATIC_ROOT}), ] if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) handler404 = global_not_found diff --git a/inyoka/utils/cache.py b/inyoka/utils/cache.py index 285d0ef5c..83e704411 100644 --- a/inyoka/utils/cache.py +++ b/inyoka/utils/cache.py @@ -18,7 +18,7 @@ from django.conf import settings from django.core.cache import cache from django.db.models.aggregates import Count -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django_redis.cache import RedisCache as _RedisCache diff --git a/inyoka/utils/diff3.py b/inyoka/utils/diff3.py index cfd8aaca1..8dd4f7f95 100644 --- a/inyoka/utils/diff3.py +++ b/inyoka/utils/diff3.py @@ -17,7 +17,7 @@ import re from django.utils.html import escape -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ DEFAULT_MARKERS = ( '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<', diff --git a/inyoka/utils/feeds.py b/inyoka/utils/feeds.py index 78e37f0ea..8feeb1461 100644 --- a/inyoka/utils/feeds.py +++ b/inyoka/utils/feeds.py @@ -12,7 +12,7 @@ from django.conf import settings from django.http import Http404, HttpResponse from django.utils.cache import patch_response_headers -from django.utils.encoding import force_text +from django.utils.encoding import force_str from werkzeug.contrib.atom import AtomFeed MODES = frozenset(('full', 'short', 'title')) @@ -53,5 +53,5 @@ class AtomFeed(AtomFeed): def to_string(self): ret = [] for item in self.generate(): - ret.append(force_text(item)) + ret.append(force_str(item)) return ''.join(ret) diff --git a/inyoka/utils/flash_confirmation.py b/inyoka/utils/flash_confirmation.py index 12ab30a0a..644ac86c1 100644 --- a/inyoka/utils/flash_confirmation.py +++ b/inyoka/utils/flash_confirmation.py @@ -10,7 +10,7 @@ :license: BSD, see LICENSE for more details. """ from django.http import HttpResponseRedirect -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.forum.models import PostRevision from inyoka.utils.decorators import patch_wrapper diff --git a/inyoka/utils/forms.py b/inyoka/utils/forms.py index 247ccd64d..cd295ffe8 100644 --- a/inyoka/utils/forms.py +++ b/inyoka/utils/forms.py @@ -23,7 +23,7 @@ from django.forms import MultipleChoiceField from django.forms.widgets import Input, TextInput from django.utils.timezone import get_current_timezone -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.forum.models import Topic from inyoka.markup.base import StackExhaused, parse diff --git a/inyoka/utils/generic.py b/inyoka/utils/generic.py index b1d3e797e..09ea7828f 100644 --- a/inyoka/utils/generic.py +++ b/inyoka/utils/generic.py @@ -15,8 +15,8 @@ from django.core.exceptions import ObjectDoesNotExist from django.http import Http404, HttpResponseRedirect from django.utils.html import escape -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from django.views.generic import base, edit, list from inyoka.utils.database import get_simplified_queryset @@ -153,7 +153,7 @@ class BaseDeleteView(edit.BaseDeleteView): """ redirect_url = None template_name = None - message = ugettext_lazy('{verbose_name} “{object_name}” was deleted successfully!') + message = gettext_lazy('{verbose_name} “{object_name}” was deleted successfully!') def get_success_url(self): self.sucess_url = self.redirect_url diff --git a/inyoka/utils/html.py b/inyoka/utils/html.py index 836be8124..644c4856a 100644 --- a/inyoka/utils/html.py +++ b/inyoka/utils/html.py @@ -16,7 +16,7 @@ from xml.sax.saxutils import quoteattr import lxml.html.clean -from django.utils.encoding import force_text +from django.utils.encoding import force_str from html5lib import HTMLParser, treebuilders, treewalkers from html5lib.filters.optionaltags import Filter as OptionalTagsFilter from html5lib.serializer import HTMLSerializer @@ -120,7 +120,7 @@ def cleanup_html(string, sanitize=True, fragment=True, stream=False, """Clean up some html and convert it to HTML/XHTML.""" if not string.strip(): return '' - string = force_text(string) + string = force_str(string) if sanitize: string = lxml.html.clean.clean_html(string) tree = parse_html(string, fragment) @@ -139,7 +139,7 @@ def cleanup_html(string, sanitize=True, fragment=True, stream=False, rv = serializer.serialize(walker, 'utf-8') if stream: return rv - return force_text(b''.join(rv)) + return force_str(b''.join(rv)) class CleanupFilter(object): @@ -245,7 +245,7 @@ def walk(self, id_map, deferred_links): id_map[original_id] = element_id token['data'] = {} for k, v in attrs.items(): - token['data'][(None, force_text(k))] = force_text(v) # None is the namespace + token['data'][(None, force_str(k))] = force_str(v) # None is the namespace elif token['type'] == 'EndTag' and token['name'] in self.end_tags: token['name'] = self.end_tags[token['name']] yield token diff --git a/inyoka/utils/imaging.py b/inyoka/utils/imaging.py index 7282826af..9142f1ac0 100644 --- a/inyoka/utils/imaging.py +++ b/inyoka/utils/imaging.py @@ -12,7 +12,7 @@ from contextlib import closing from django.conf import settings -from django.utils.encoding import force_text +from django.utils.encoding import force_str from PIL import Image from inyoka.utils.urls import is_safe_domain @@ -95,7 +95,7 @@ def get_thumbnail(location, destination, width=None, height=None, force=False): format = 'png' # force unicode because of posixpath - destination = force_text(destination) + destination = force_str(destination) destination = '%s.%s' % (destination.rsplit('.', 1)[0], format) fn = os.path.join(settings.MEDIA_ROOT, destination) if os.path.exists(fn): diff --git a/inyoka/utils/pagination.py b/inyoka/utils/pagination.py index d73219814..2907d570e 100644 --- a/inyoka/utils/pagination.py +++ b/inyoka/utils/pagination.py @@ -56,7 +56,7 @@ from django.http import Http404 -from django.utils.encoding import force_text +from django.utils.encoding import force_str from inyoka.utils.urls import urlencode @@ -109,7 +109,7 @@ def __init__(self, request, query, page=1, per_page=10, link=None, total=None, # This unicode/utf-8 conversion exists because of some fancy hacker-bots # that try to fuzz the pagination with some extremly invalid unicode data. # Catching those here fixes vulerabilty of the whole application. - enc = lambda v: force_text(v).encode('utf-8') if isinstance(v, str) else v + enc = lambda v: force_str(v).encode('utf-8') if isinstance(v, str) else v self.params = {enc(k): enc(v) for k, v in self.request.GET.items()} def _get_base_link(self, link): diff --git a/inyoka/utils/sessions.py b/inyoka/utils/sessions.py index 9e34f4b0f..7ca5023d7 100644 --- a/inyoka/utils/sessions.py +++ b/inyoka/utils/sessions.py @@ -14,7 +14,7 @@ from django.core.cache import cache from django.forms import ValidationError -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from inyoka.utils.local import current_request from inyoka.utils.storage import storage @@ -64,7 +64,7 @@ class SurgeProtectionMixin(object): """ surge_protection_timeout = 15 - surge_protection_message = ugettext_lazy( + surge_protection_message = gettext_lazy( 'You cannot send data that fast in a row. ' 'Please wait a bit until you submit the form again.' ) diff --git a/inyoka/utils/spam.py b/inyoka/utils/spam.py index ffd958242..53f8418b3 100644 --- a/inyoka/utils/spam.py +++ b/inyoka/utils/spam.py @@ -11,7 +11,7 @@ import requests from django.conf import settings from django.contrib import messages -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from inyoka.utils.logger import logger diff --git a/inyoka/utils/templating.py b/inyoka/utils/templating.py index 5fddaca1e..ff33dedeb 100644 --- a/inyoka/utils/templating.py +++ b/inyoka/utils/templating.py @@ -10,6 +10,7 @@ """ import json from datetime import date +from urllib.parse import quote from django.apps import apps from django.conf import settings @@ -21,8 +22,9 @@ from django.template.backends.jinja2 import Jinja2 from django.template.backends.utils import csrf_input from django.utils import translation +from django.utils.http import urlencode -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.functional import Promise from django.utils.timesince import timesince import jinja2 @@ -37,7 +39,7 @@ from inyoka.utils.local import current_request from inyoka.utils.special_day import check_special_day from inyoka.utils.text import human_number -from inyoka.utils.urls import href, url_for, urlencode, urlquote +from inyoka.utils.urls import href, url_for def context_data(request): @@ -164,7 +166,7 @@ def urlencode_filter(value): """URL encode a string or dict.""" if isinstance(value, dict): return urlencode(value) - return urlquote(value) + return quote(value) def ischeckbox_filter(input): @@ -178,7 +180,7 @@ class LazyJSONEncoder(json.JSONEncoder): """ def default(self, obj): if isinstance(obj, Promise): - return force_text(obj) + return force_str(obj) return super(LazyJSONEncoder, self).default(obj) diff --git a/inyoka/utils/test.py b/inyoka/utils/test.py index 5fa1c98e8..1db4ac629 100644 --- a/inyoka/utils/test.py +++ b/inyoka/utils/test.py @@ -86,7 +86,7 @@ def login(self, **credentials): """Try to authenticate a user with username and password. :param username: The username of the :class:`~inyoka.portal.user.User` - to login + to log in :param password: The password of the user to login :type username: str :type password: str diff --git a/inyoka/utils/text.py b/inyoka/utils/text.py index 9f98c35bf..99c7e2ba7 100644 --- a/inyoka/utils/text.py +++ b/inyoka/utils/text.py @@ -15,7 +15,7 @@ from django.conf import settings from django.contrib.humanize.templatetags.humanize import apnumber -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.utils.translation import get_language, pgettext _str_num_re = re.compile(r'(?:[^\d]*(\d+)[^\d]*)+') diff --git a/inyoka/utils/urls.py b/inyoka/utils/urls.py index ef2c534ec..74e22503d 100644 --- a/inyoka/utils/urls.py +++ b/inyoka/utils/urls.py @@ -13,7 +13,8 @@ from django.conf import settings from django.contrib.auth.models import Group from django.utils.encoding import force_str -from django.utils.http import urlencode, urlquote, urlquote_plus, is_safe_url +from urllib.parse import quote, quote_plus +from django.utils.http import url_has_allowed_host_and_scheme, urlencode from django_hosts.resolvers import get_host, get_host_patterns @@ -21,7 +22,7 @@ def href(_module='portal', *parts, **query): """Generates an internal URL for different subdomains.""" anchor = query.pop('_anchor', None) append_slash = _module not in ['static', 'media'] - path = '/'.join(urlquote(force_str(x)) for x in parts if x is not None) + path = '/'.join(quote(force_str(x)) for x in parts if x is not None) if not append_slash: base_url = { @@ -38,7 +39,7 @@ def href(_module='portal', *parts, **query): path, append_slash and path and not path.endswith('/') and '/' or '', query and '?' + urlencode(query) or '', - anchor and '#' + urlquote_plus(force_str(anchor)) or '' + anchor and '#' + quote_plus(force_str(anchor)) or '' ) @@ -75,6 +76,6 @@ def is_safe_domain(url): safe_hostnames = ['{}.{}'.format(service, settings.BASE_DOMAIN_NAME).lstrip('.') for service in services] # Only one successfully matching is_safe_url() must match: for hostname in safe_hostnames: - if is_safe_url(url, allowed_hosts=hostname): + if url_has_allowed_host_and_scheme(url, allowed_hosts=hostname): return True return False diff --git a/inyoka/wiki/actions.py b/inyoka/wiki/actions.py index 7cc58547c..60f684816 100644 --- a/inyoka/wiki/actions.py +++ b/inyoka/wiki/actions.py @@ -26,7 +26,7 @@ from django.db import models, transaction from django.http import Http404, HttpResponse, HttpResponseRedirect from django.utils.html import escape -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.markup.base import RenderContext, parse from inyoka.portal.models import Subscription diff --git a/inyoka/wiki/forms.py b/inyoka/wiki/forms.py index 6882173d3..0cdce4ee0 100644 --- a/inyoka/wiki/forms.py +++ b/inyoka/wiki/forms.py @@ -11,8 +11,8 @@ from datetime import datetime from django import forms -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from inyoka.markup.base import StackExhaused, parse from inyoka.utils.diff3 import merge @@ -28,10 +28,10 @@ class NewArticleForm(SurgeProtectionMixin, forms.Form): """Form for creating new wiki articles.""" name = forms.CharField(widget=forms.TextInput(), required=True, - label=ugettext_lazy('The title of the article you want to ' + label=gettext_lazy('The title of the article you want to ' 'create.')) template = forms.ChoiceField(required=False, - label=ugettext_lazy('The template that this new article ' + label=gettext_lazy('The template that this new article ' 'should be using.')) def __init__(self, user=None, reserved_names=[], template_choices=[], @@ -117,7 +117,7 @@ class PageEditForm(SurgeProtectionMixin, forms.Form): revision. """ text = forms.CharField(widget=forms.Textarea(attrs={'rows': 20, 'cols': 50})) - note = forms.CharField(label=ugettext_lazy('Edit summary'), + note = forms.CharField(label=gettext_lazy('Edit summary'), widget=forms.TextInput(attrs={'size': 50, 'spellcheck': 'true'}), max_length=512, required=True, help_text=storage['wiki_edit_note_rendered']) @@ -221,16 +221,16 @@ class AddAttachmentForm(forms.Form): attachment = forms.FileField(required=True) filename = forms.CharField(max_length=512, required=False, - help_text=ugettext_lazy('Rename the file after upload')) + help_text=gettext_lazy('Rename the file after upload')) - override = forms.BooleanField(label=ugettext_lazy('Overwrite existing file with same name'), + override = forms.BooleanField(label=gettext_lazy('Overwrite existing file with same name'), required=False) - text = forms.CharField(label=ugettext_lazy('Description of attachment'), + text = forms.CharField(label=gettext_lazy('Description of attachment'), widget=forms.Textarea, required=False) - note = forms.CharField(label=ugettext_lazy('Edit summary'), max_length=512, required=False) + note = forms.CharField(label=gettext_lazy('Edit summary'), max_length=512, required=False) class EditAttachmentForm(forms.Form): @@ -239,10 +239,10 @@ class EditAttachmentForm(forms.Form): description, have a look at the AddAttachmentForm. """ attachment = forms.FileField(required=False) - text = forms.CharField(label=ugettext_lazy('Description of attachment'), + text = forms.CharField(label=gettext_lazy('Description of attachment'), widget=forms.Textarea, required=False) - note = forms.CharField(label=ugettext_lazy('Edit summary'), + note = forms.CharField(label=gettext_lazy('Edit summary'), max_length=512, required=False) @@ -253,8 +253,8 @@ class ManageDiscussionForm(forms.Form): class MvBaustelleForm(forms.Form): """Move page to the "Baustelle""" - new_name = forms.CharField(label=ugettext_lazy('New page name'), required=True) - user = UserField(label=ugettext_lazy('Edited by'), required=True) - completion_date = forms.DateField(label=ugettext_lazy('Completion date'), + new_name = forms.CharField(label=gettext_lazy('New page name'), required=True) + user = UserField(label=gettext_lazy('Edited by'), required=True) + completion_date = forms.DateField(label=gettext_lazy('Completion date'), required=False, widget=DateWidget, localize=True) diff --git a/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.mo b/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.mo index 035c1b604..59032df91 100644 Binary files a/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.mo and b/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.po b/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.po index 78f83ceb4..fcf6d4754 100644 --- a/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.po +++ b/inyoka/wiki/locale/de_DE/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Inyoka\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2020-11-07 18:18+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: 2019-01-25 20:45+0100\n" "Last-Translator: Lyra\n" "Language: de_DE\n" "Language-Team: German (Germany) (http://www.transifex.com/inyokaproject/inyoka/language/de_DE/)\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(note)s [Revision from %(date)s restored by %(user)s]note" diff --git a/inyoka/wiki/locale/django.pot b/inyoka/wiki/locale/django.pot index eff65a55d..a99d157e1 100644 --- a/inyoka/wiki/locale/django.pot +++ b/inyoka/wiki/locale/django.pot @@ -1,21 +1,21 @@ # Translations template for Inyoka Project. # Copyright (C) 2023 Inyoka Team (see AUTHORS) # This file is distributed under the same license as the Inyoka Project project. -# FIRST AUTHOR , 2020. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Inyoka Project v0.23.0\n" +"Project-Id-Version: Inyoka Project v0.29.0\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2020-11-07 18:18+0100\n" +"POT-Creation-Date: 2023-10-01 16:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.5.1\n" +"Generated-By: Babel 2.12.1\n" #, python-format msgid "%(note)s [Revision from %(date)s restored by %(user)s]note" diff --git a/inyoka/wiki/macros.py b/inyoka/wiki/macros.py index 5c1583112..932406380 100644 --- a/inyoka/wiki/macros.py +++ b/inyoka/wiki/macros.py @@ -12,7 +12,7 @@ import operator from django.conf import settings -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.markup import macros, nodes from inyoka.markup.parsertools import MultiMap, flatten_iterator diff --git a/inyoka/wiki/management/commands/generate_static_wiki.py b/inyoka/wiki/management/commands/generate_static_wiki.py index fd5cddc48..f8b14f3cf 100755 --- a/inyoka/wiki/management/commands/generate_static_wiki.py +++ b/inyoka/wiki/management/commands/generate_static_wiki.py @@ -24,7 +24,7 @@ from django.conf import settings from django.core.management.base import BaseCommand from django.template.defaultfilters import date -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.translation import activate from werkzeug.urls import url_unquote @@ -172,7 +172,7 @@ def save_file(self, url, is_main_page=False, is_static=False): rel_path = sub('\?v=v[\d\.]*', '', rel_path) if rel_path: abs_path = path.join(base, rel_path) - hash_code = sha1(force_text(rel_path).encode('utf-8')).hexdigest() + hash_code = sha1(force_str(rel_path).encode('utf-8')).hexdigest() if hash_code not in DONE_SRCS: ext = path.splitext(rel_path)[1] fname = '%s%s' % (hash_code, ext) diff --git a/inyoka/wiki/models.py b/inyoka/wiki/models.py index e166483e7..c927e4171 100644 --- a/inyoka/wiki/models.py +++ b/inyoka/wiki/models.py @@ -89,8 +89,8 @@ from django.db import models from django.db.models import Count, Max from django.utils.html import escape -from django.utils.translation import ugettext as _, to_locale, get_language -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _, to_locale, get_language +from django.utils.translation import gettext_lazy from functools import partial from hashlib import sha1 from werkzeug import cached_property @@ -536,11 +536,11 @@ def create(self, name, text, user=None, change_date=None, :Parameters: name - This must be a *normaliezd* version of the page name. The + This must be a *normalized* version of the page name. The default action dispatcher (`inyoka.wiki.views.show_page`) automatically normalizes incoming page names so this is no - issue from the web layer. However shell scripts, converters, - crons etc have to normalize this parameter themselves. + issue from the web layer. However, shell scripts, converters, + crons etc. have to normalize this parameter themselves. text Either a text object or a text that represents the text. If @@ -548,12 +548,12 @@ def create(self, name, text, user=None, change_date=None, a text with the same value in the database. user - If this paramter is `None` the inoyka system user will be the - author of the created revision. Otherwise it can either be a + If this parameter is `None` the inyoka system user will be the + author of the created revision. Otherwise, it can either be a User or an AnoymousUser object from the auth contrib module. change_date - If this is not provided the current date is used. Otherwise + If this is not provided the current date is used. Otherwise, it should be an UTC timestamp in form of a `datetime.datetime` object. @@ -571,7 +571,7 @@ def create(self, name, text, user=None, change_date=None, probably will support a file descriptor here. deleted - If this is `True` the page is created as an deleted page. + If this is `True` the page is created as a deleted page. This operation doesn't make sense and creates suprising displays in the revision log if the `note` is not changed to something reasonable. @@ -929,7 +929,7 @@ def update_meta(self): most recent revision, never on the revision attached to the page. If there is no revision in the database yet this method fails silently. - Thus the page create method has to call this after the revision was + Thus, the page create method has to call this after the revision was saved manually. """ try: @@ -1168,8 +1168,8 @@ def __repr__(self): class Meta: ordering = ['name'] - verbose_name = ugettext_lazy('Wiki page') - verbose_name_plural = ugettext_lazy('Wiki pages') + verbose_name = gettext_lazy('Wiki page') + verbose_name_plural = gettext_lazy('Wiki pages') class Attachment(models.Model): diff --git a/inyoka/wiki/notifications.py b/inyoka/wiki/notifications.py index 50877785c..c16700213 100644 --- a/inyoka/wiki/notifications.py +++ b/inyoka/wiki/notifications.py @@ -9,7 +9,7 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.utils import ctype from inyoka.utils.notification import queue_notifications diff --git a/inyoka/wiki/signals.py b/inyoka/wiki/signals.py index d08c0d2a8..cf4c06dad 100644 --- a/inyoka/wiki/signals.py +++ b/inyoka/wiki/signals.py @@ -10,7 +10,4 @@ """ import django.dispatch -build_picture_node = django.dispatch.Signal(providing_args=[ - 'context', - 'format' -]) +build_picture_node = django.dispatch.Signal() # arguments: 'context', 'format' diff --git a/inyoka/wiki/urls.py b/inyoka/wiki/urls.py index 777dfa66c..6833d36a6 100644 --- a/inyoka/wiki/urls.py +++ b/inyoka/wiki/urls.py @@ -9,65 +9,65 @@ :license: BSD, see LICENSE for more details. """ from django.conf import settings -from django.conf.urls import include, url +from django.urls import include, path, re_path from . import actions, views from ..utils.http import global_not_found, server_error urlpatterns = [ - url(r'^$', views.index), - url(r'^_image/$', views.get_image_resource), - url(r'^_newpage/$', views.redirect_new_page), - url(r'^_attachment/$', views.get_attachment), - url(r'^_feed/(?P\d+)/$', views.feed), - url(r'^(?P.+)/a/feed/$', views.feed, {'count': 10}), - url(r'^(?P.+)/a/feed/(?P\d+)/$', views.feed), - url(r'^wiki/recentchanges/$', views.recentchanges), - url(r'^wiki/missingpages/$', views.missingpages), - url(r'^wiki/randompages/$', views.randompages), - url(r'^wiki/tagcloud/$', views.show_tag_cloud), - url(r'^wiki/tags/$', views.show_tag_list), - url(r'^wiki/tags/(?P.+)/$', views.show_pages_by_tag) + path('', views.index), + path('_image/', views.get_image_resource), + path('_newpage/', views.redirect_new_page), + path('_attachment/', views.get_attachment), + path('_feed//', views.feed), + path('/a/feed/', views.feed, {'count': 10}), + path('/a/feed//', views.feed), + path('wiki/recentchanges/', views.recentchanges), + path('wiki/missingpages/', views.missingpages), + path('wiki/randompages/', views.randompages), + path('wiki/tagcloud/', views.show_tag_cloud), + path('wiki/tags/', views.show_tag_list), + path('wiki/tags//', views.show_pages_by_tag) ] if settings.DEBUG: import debug_toolbar urlpatterns.append( - url(r'^__debug__/', include(debug_toolbar.urls)), + path('__debug__/', include(debug_toolbar.urls)), ) urlpatterns.extend([ - url(r'^wiki/create/?$', actions.do_create), - url(r'^wiki/create/(?P.+)/$', actions.do_create), - url(r'^(?P.+)/a/attachments/$', actions.do_attach), - url(r'^(?P.+)/a/backlinks/$', actions.do_backlinks), - url(r'^(?P.+)/a/delete/$', actions.do_delete), - url(r'^(?P.+)/a/diff/(?P\d+)/(?P\d+)/$', actions.do_diff), - url(r'^(?P.+)/a/diff/(?P\d+)/$', actions.do_diff), - url(r'^(?P.+)/a/diff/$', actions.do_diff), - url(r'^(?P.+)/a/discussion/$', actions.do_manage_discussion), - url(r'^(?P.+)/a/edit/$', actions.do_edit), - url(r'^(?P.+)/a/edit/revision/(?P\d+)/$', actions.do_edit), - url(r'^(?P.+)/a/export/(?P(raw|html))/$', actions.do_export), - url(r'^(?P.+)/a/export/(?P(raw|html))/(?P\d+)/$', actions.do_export), - url(r'^(?P.+)/a/export/meta/$', actions.do_metaexport), - url(r'^(?P.+)/a/log/(?P\d+)/$', actions.do_log), - url(r'^(?P.+)/a/log/$', actions.do_log), - url(r'^(?P.+)/a/mv_back/$', actions.do_mv_back), - url(r'^(?P.+)/a/mv_baustelle/$', actions.do_mv_baustelle), - url(r'^(?P.+)/a/mv_discontinued/$', actions.do_mv_discontinued), - url(r'^(?P.+)/a/rename/$', actions.do_rename), - url(r'^(?P.+)/a/rename/force/$', actions.do_rename, {'force': True}), - url(r'^(?P.+)/a/revert/(?P\d+)/$', actions.do_revert), - url(r'^(?P.+)/a/revision/(?P\d+)/$', actions.do_show), - url(r'^(?P.+)/a/revision/(?P\d+)/no_redirect/$', actions.do_show, {'allow_redirect': False}), - url(r'^(?P.+)/a/subscribe/$', actions.do_subscribe), - url(r'^(?P.+)/a/udiff/(?P\d+)/(?P\d+)/$', actions.do_diff, {'udiff': True}), - url(r'^(?P.+)/a/udiff/(?P\d+)/$', actions.do_diff, {'udiff': True}), - url(r'^(?P.+)/a/udiff/$', actions.do_diff, {'udiff': True}), - url(r'^(?P.+)/a/unsubscribe/$', actions.do_unsubscribe), - url(r'^(?P.+)/no_redirect/$', actions.do_show, {'allow_redirect': False}), - url(r'^(?P.+)/$', actions.do_show), + re_path(r'^wiki/create/?$', actions.do_create), + path('wiki/create//', actions.do_create), + path('/a/attachments/', actions.do_attach), + path('/a/backlinks/', actions.do_backlinks), + path('/a/delete/', actions.do_delete), + path('/a/diff///', actions.do_diff), + path('/a/diff//', actions.do_diff), + path('/a/diff/', actions.do_diff), + path('/a/discussion/', actions.do_manage_discussion), + path('/a/edit/', actions.do_edit), + path('/a/edit/revision//', actions.do_edit), + re_path(r'^(?P.+)/a/export/(?P(raw|html))/$', actions.do_export), + re_path(r'^(?P.+)/a/export/(?P(raw|html))/(?P\d+)/$', actions.do_export), + path('/a/export/meta/', actions.do_metaexport), + path('/a/log//', actions.do_log), + path('/a/log/', actions.do_log), + path('/a/mv_back/', actions.do_mv_back), + path('/a/mv_baustelle/', actions.do_mv_baustelle), + path('/a/mv_discontinued/', actions.do_mv_discontinued), + path('/a/rename/', actions.do_rename), + path('/a/rename/force/', actions.do_rename, {'force': True}), + path('/a/revert//', actions.do_revert), + path('/a/revision//', actions.do_show), + path('/a/revision//no_redirect/', actions.do_show, {'allow_redirect': False}), + path('/a/subscribe/', actions.do_subscribe), + path('/a/udiff///', actions.do_diff, {'udiff': True}), + path('/a/udiff//', actions.do_diff, {'udiff': True}), + path('/a/udiff/', actions.do_diff, {'udiff': True}), + path('/a/unsubscribe/', actions.do_unsubscribe), + path('/no_redirect/', actions.do_show, {'allow_redirect': False}), + path('/', actions.do_show), ]) handler404 = global_not_found diff --git a/inyoka/wiki/views.py b/inyoka/wiki/views.py index ab043e703..c79d2d73b 100644 --- a/inyoka/wiki/views.py +++ b/inyoka/wiki/views.py @@ -23,9 +23,9 @@ from django.contrib import messages from django.core.cache import cache from django.http import Http404, HttpResponseRedirect -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.html import escape -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from inyoka.utils.dates import format_datetime from inyoka.utils.feeds import AtomFeed, atom_feed @@ -51,7 +51,7 @@ def redirect_new_page(request): base = request.GET.get('base', '') page = request.GET.get('page', '') options = {'action': 'edit'} - backref = request.META.get('HTTP_REFERER') + backref = request.headers.get('referer') if not backref or not is_safe_domain(backref): backref = href('wiki', settings.WIKI_MAIN_PAGE) @@ -99,7 +99,7 @@ def fetch_real_target(target, width=None, height=None, force=False): if page_filename is None: return - page_filename = force_text(page_filename).encode('utf-8') + page_filename = force_str(page_filename).encode('utf-8') partial_hash = sha1(page_filename).hexdigest() dimension = '%sx%s%s' % (width or '', diff --git a/setup.py b/setup.py index c1067e8a5..2b31e054a 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ packages=find_packages(include=('inyoka*',)), python_requires='>=3.9, <4', install_requires=[ - 'Django<2.3', + 'Django<4.0', 'pip-tools', 'Babel', @@ -51,7 +51,7 @@ 'celery[redis]', 'certifi', 'defusedxml', - 'django-filter<22', # last version to support django 2.2 + 'django-filter', 'django-guardian', 'django-hosts', 'django-redis', @@ -78,7 +78,9 @@ 'dev': ['allure-behave', 'bump2version', 'coverage', - 'django-debug-toolbar<3.3', # last version to support django 2.2 + 'django-codemod', + 'django-debug-toolbar', + 'django-upgrade', 'flake8==3.5.0', 'freezegun', 'isort', diff --git a/tests/apps/forum/test_models.py b/tests/apps/forum/test_models.py index c6bc40ce3..00266dc4b 100644 --- a/tests/apps/forum/test_models.py +++ b/tests/apps/forum/test_models.py @@ -154,7 +154,7 @@ def test_rendered_get_text(self): def test_plaintext_get_text(self): post = Post(text="'''test'''", is_plaintext=True) - self.assertEqual(post.get_text(), "'''test'''") + self.assertEqual(post.get_text(), "'''test'''") class TestPostRevisionModel(TestCase): diff --git a/tests/apps/forum/test_views.py b/tests/apps/forum/test_views.py index 94c16149b..8faa65d49 100644 --- a/tests/apps/forum/test_views.py +++ b/tests/apps/forum/test_views.py @@ -21,7 +21,7 @@ from django.test import RequestFactory from django.test.utils import override_settings from django.utils import translation -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from unittest.mock import patch from guardian.shortcuts import assign_perm from unittest import skip diff --git a/tests/apps/portal/test_views.py b/tests/apps/portal/test_views.py index ba610620b..3a690680a 100644 --- a/tests/apps/portal/test_views.py +++ b/tests/apps/portal/test_views.py @@ -17,7 +17,7 @@ from django.test.utils import override_settings from django.utils import translation from django.utils.timezone import now -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from guardian.shortcuts import assign_perm diff --git a/tests/utils/test_templating.py b/tests/utils/test_templating.py index 88ed2168f..9f81247a8 100644 --- a/tests/utils/test_templating.py +++ b/tests/utils/test_templating.py @@ -10,8 +10,8 @@ """ import unittest -from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy from inyoka.utils.templating import json_filter @@ -21,19 +21,19 @@ class TestTemplating(unittest.TestCase): def test_json_encoding(self): u = _('text') - l = ugettext_lazy('text') + l = gettext_lazy('text') t = '"text"' self.assertEqual(json_filter(u), t) self.assertEqual(json_filter(l), t) u = [_('e1'), _('e2')] - l = [ugettext_lazy('e1'), ugettext_lazy('e2')] + l = [gettext_lazy('e1'), gettext_lazy('e2')] t = '["e1", "e2"]' self.assertEqual(json_filter(u), t) self.assertEqual(json_filter(l), t) u = {1: _('v1'), 2: _('v2')} - l = {1: ugettext_lazy('v1'), 2: ugettext_lazy('v2')} + l = {1: gettext_lazy('v1'), 2: gettext_lazy('v2')} t = '{"1": "v1", "2": "v2"}' self.assertEqual(json_filter(u), t) self.assertEqual(json_filter(l), t)