diff --git a/Dockerfile b/Dockerfile index 699e279344..2c71a46068 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM ubuntu:20.04 +FROM ubuntu:24.04 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ build-essential \ @@ -7,7 +7,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ cppreference-doc-en-html \ fp-compiler \ git \ - haskell-platform \ + ghc \ libcap-dev \ libcups2-dev \ libffi-dev \ @@ -15,13 +15,13 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ libyaml-dev \ mono-mcs \ openjdk-8-jdk-headless \ - php7.4-cli \ + php-cli \ postgresql-client \ - python2 \ python3-pip \ - python3.8 \ - python3.8-dev \ + python3.12 \ + python3.12-dev \ rustc \ + shared-mime-info \ sudo \ wait-for-it \ zip @@ -39,8 +39,8 @@ COPY --chown=cmsuser:cmsuser requirements.txt dev-requirements.txt /home/cmsuser WORKDIR /home/cmsuser/cms -RUN sudo pip3 install -r requirements.txt -RUN sudo pip3 install -r dev-requirements.txt +RUN sudo pip3 install --break-system-packages -r requirements.txt +RUN sudo pip3 install --break-system-packages -r dev-requirements.txt COPY --chown=cmsuser:cmsuser . /home/cmsuser/cms diff --git a/cms/io/web_service.py b/cms/io/web_service.py index 41d2e2829c..21e1580514 100644 --- a/cms/io/web_service.py +++ b/cms/io/web_service.py @@ -21,6 +21,13 @@ import logging +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.wsgi as tornado_wsgi except ImportError: diff --git a/cms/server/admin/handlers/base.py b/cms/server/admin/handlers/base.py index e38be1fbbf..43df71b4b8 100644 --- a/cms/server/admin/handlers/base.py +++ b/cms/server/admin/handlers/base.py @@ -34,6 +34,13 @@ from datetime import datetime, timedelta from functools import wraps +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/admin/handlers/contestannouncement.py b/cms/server/admin/handlers/contestannouncement.py index 464ff0cced..20f87fe3d5 100644 --- a/cms/server/admin/handlers/contestannouncement.py +++ b/cms/server/admin/handlers/contestannouncement.py @@ -26,6 +26,13 @@ """ +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/admin/handlers/contestquestion.py b/cms/server/admin/handlers/contestquestion.py index 625248f376..57ad1f13b7 100644 --- a/cms/server/admin/handlers/contestquestion.py +++ b/cms/server/admin/handlers/contestquestion.py @@ -27,6 +27,13 @@ import logging +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/admin/handlers/contestuser.py b/cms/server/admin/handlers/contestuser.py index 1706ce8f50..9ec869039b 100644 --- a/cms/server/admin/handlers/contestuser.py +++ b/cms/server/admin/handlers/contestuser.py @@ -31,6 +31,13 @@ import logging +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/admin/handlers/dataset.py b/cms/server/admin/handlers/dataset.py index d01716a90c..5adb03d093 100644 --- a/cms/server/admin/handlers/dataset.py +++ b/cms/server/admin/handlers/dataset.py @@ -32,6 +32,13 @@ import re import zipfile +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/admin/handlers/task.py b/cms/server/admin/handlers/task.py index ff5d5e8e48..c9df69ff08 100644 --- a/cms/server/admin/handlers/task.py +++ b/cms/server/admin/handlers/task.py @@ -29,6 +29,13 @@ import logging import traceback +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/contest/handlers/base.py b/cms/server/contest/handlers/base.py index 00e24c273f..faeb031f58 100644 --- a/cms/server/contest/handlers/base.py +++ b/cms/server/contest/handlers/base.py @@ -32,6 +32,13 @@ import logging import traceback +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/contest/handlers/communication.py b/cms/server/contest/handlers/communication.py index 8bac98e539..572b13be64 100644 --- a/cms/server/contest/handlers/communication.py +++ b/cms/server/contest/handlers/communication.py @@ -29,6 +29,13 @@ import logging +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/contest/handlers/contest.py b/cms/server/contest/handlers/contest.py index 4fe6936ec4..724d5886b8 100644 --- a/cms/server/contest/handlers/contest.py +++ b/cms/server/contest/handlers/contest.py @@ -32,6 +32,13 @@ import ipaddress import logging +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/contest/handlers/main.py b/cms/server/contest/handlers/main.py index 6d2fb2a51d..3ea2129d01 100644 --- a/cms/server/contest/handlers/main.py +++ b/cms/server/contest/handlers/main.py @@ -33,6 +33,13 @@ import logging import re +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/contest/handlers/task.py b/cms/server/contest/handlers/task.py index 3f6f163a28..cfdfe1b69a 100644 --- a/cms/server/contest/handlers/task.py +++ b/cms/server/contest/handlers/task.py @@ -30,6 +30,13 @@ import logging +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/contest/handlers/tasksubmission.py b/cms/server/contest/handlers/tasksubmission.py index 9199c0bcd7..e233291a76 100644 --- a/cms/server/contest/handlers/tasksubmission.py +++ b/cms/server/contest/handlers/tasksubmission.py @@ -32,6 +32,13 @@ import logging import re +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/contest/handlers/taskusertest.py b/cms/server/contest/handlers/taskusertest.py index c78c87c1c8..07da1f9a59 100644 --- a/cms/server/contest/handlers/taskusertest.py +++ b/cms/server/contest/handlers/taskusertest.py @@ -31,6 +31,13 @@ import logging import re +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: import tornado4.web as tornado_web except ImportError: diff --git a/cms/server/util.py b/cms/server/util.py index 953d5eb1c3..7b787595cb 100644 --- a/cms/server/util.py +++ b/cms/server/util.py @@ -30,6 +30,13 @@ from functools import wraps from urllib.parse import quote, urlencode +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: from tornado4.web import RequestHandler except ImportError: diff --git a/cmscontrib/loaders/polygon.py b/cmscontrib/loaders/polygon.py index fb4a4b4ade..200dd38c8d 100644 --- a/cmscontrib/loaders/polygon.py +++ b/cmscontrib/loaders/polygon.py @@ -20,7 +20,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import imp import logging import os import subprocess @@ -145,10 +144,11 @@ def get_task(self, get_statement=True): task_cms_conf = None if os.path.exists(task_cms_conf_path): logger.info("Found additional CMS options for task %s.", name) - with open(task_cms_conf_path, 'rb') as f: - task_cms_conf = imp.load_module('cms_conf', f, - task_cms_conf_path, - ('.py', 'r', imp.PY_SOURCE)) + import importlib.util + spec = importlib.util.spec_from_file_location( + 'cms_conf', task_cms_conf_path) + task_cms_conf = importlib.util.module_from_spec(spec) + spec.loader.exec_module(task_cms_conf) if task_cms_conf is not None and hasattr(task_cms_conf, "general"): args.update(task_cms_conf.general) diff --git a/cmstestsuite/unit_tests/grading/ParameterTypesTest.py b/cmstestsuite/unit_tests/grading/ParameterTypesTest.py index 21e20ec38a..c7c56af41b 100755 --- a/cmstestsuite/unit_tests/grading/ParameterTypesTest.py +++ b/cmstestsuite/unit_tests/grading/ParameterTypesTest.py @@ -20,6 +20,13 @@ import unittest +import collections +try: + collections.MutableMapping +except: + # Monkey-patch: Tornado 4.5.3 does not work on Python 3.11 by default + collections.MutableMapping = collections.abc.MutableMapping + try: from tornado4.web import MissingArgumentError except ImportError: diff --git a/cmstestsuite/unit_tests/locale/locale_test.py b/cmstestsuite/unit_tests/locale/locale_test.py index 170a488473..e81d0fe458 100755 --- a/cmstestsuite/unit_tests/locale/locale_test.py +++ b/cmstestsuite/unit_tests/locale/locale_test.py @@ -103,20 +103,20 @@ def test_utc(self): self.assertEqual( ENGLISH.format_datetime(datetime(2018, 1, 1, 12, 34, 56), timezone=UTC), - "Jan 1, 2018, 12:34:56 PM") + "Jan 1, 2018, 12:34:56\N{Narrow No-Break Space}PM") def test_other_timezone_winter(self): # Other timezone, in winter (no DST). self.assertEqual( ENGLISH.format_datetime(datetime(2018, 1, 1, 12, 34, 56), timezone=ROME), - "Jan 1, 2018, 1:34:56 PM") + "Jan 1, 2018, 1:34:56\N{Narrow No-Break Space}PM") def test_other_timezone_summer(self): self.assertEqual( ENGLISH.format_datetime(datetime(2018, 7, 1, 12, 34, 56), timezone=ROME), - "Jul 1, 2018, 2:34:56 PM") + "Jul 1, 2018, 2:34:56\N{Narrow No-Break Space}PM") # As above, localized (use a language with a 24h clock and with a # different day/month/year order). @@ -146,19 +146,19 @@ def test_utc(self): # UTC, in English self.assertEqual(ENGLISH.format_time(datetime(2018, 1, 1, 12, 34, 56), timezone=UTC), - "12:34:56 PM") + "12:34:56\N{Narrow No-Break Space}PM") def test_other_timezone_winter(self): # Other timezone, in winter (no DST). self.assertEqual(ENGLISH.format_time(datetime(2018, 1, 1, 12, 34, 56), timezone=ROME), - "1:34:56 PM") + "1:34:56\N{Narrow No-Break Space}PM") def test_other_timezone_in_summer(self): # Other timezone, in summer (DST). self.assertEqual(ENGLISH.format_time(datetime(2018, 7, 1, 12, 34, 56), timezone=ROME), - "2:34:56 PM") + "2:34:56\N{Narrow No-Break Space}PM") # As above, localized (use Danish as they use periods rather # than colons and have a 24h clock). @@ -187,17 +187,17 @@ def test_utc(self): ENGLISH.format_datetime_smart(datetime(2018, 1, 1, 12, 34, 56), datetime(2018, 1, 1, 23, 30), timezone=UTC), - "12:34:56 PM") + "12:34:56\N{Narrow No-Break Space}PM") self.assertEqual( ENGLISH.format_datetime_smart(datetime(2018, 1, 1, 12, 34, 56), datetime(2018, 1, 2, 0, 30), timezone=UTC), - "Jan 1, 2018, 12:34:56 PM") + "Jan 1, 2018, 12:34:56\N{Narrow No-Break Space}PM") self.assertEqual( ENGLISH.format_datetime_smart(datetime(2018, 1, 1, 12, 34, 56), datetime(2017, 12, 31, 23, 30), timezone=UTC), - "Jan 1, 2018, 12:34:56 PM") + "Jan 1, 2018, 12:34:56\N{Narrow No-Break Space}PM") def test_other_timezone_winter(self): # Other timezone, in winter (no DST). @@ -205,17 +205,17 @@ def test_other_timezone_winter(self): ENGLISH.format_datetime_smart(datetime(2018, 1, 1, 12, 34, 56), datetime(2018, 1, 1, 22, 30), timezone=ROME), - "1:34:56 PM") + "1:34:56\N{Narrow No-Break Space}PM") self.assertEqual( ENGLISH.format_datetime_smart(datetime(2018, 1, 1, 12, 34, 56), datetime(2018, 1, 1, 23, 30), timezone=ROME), - "Jan 1, 2018, 1:34:56 PM") + "Jan 1, 2018, 1:34:56\N{Narrow No-Break Space}PM") self.assertEqual( ENGLISH.format_datetime_smart(datetime(2018, 1, 1, 12, 34, 56), datetime(2017, 12, 31, 22, 30), timezone=ROME), - "Jan 1, 2018, 1:34:56 PM") + "Jan 1, 2018, 1:34:56\N{Narrow No-Break Space}PM") def test_other_timezone_summer(self): # Other timezone, in summer (DST). @@ -223,17 +223,17 @@ def test_other_timezone_summer(self): ENGLISH.format_datetime_smart(datetime(2018, 7, 1, 12, 34, 56), datetime(2018, 7, 1, 21, 30), timezone=ROME), - "2:34:56 PM") + "2:34:56\N{Narrow No-Break Space}PM") self.assertEqual( ENGLISH.format_datetime_smart(datetime(2018, 7, 1, 12, 34, 56), datetime(2018, 7, 1, 22, 30), timezone=ROME), - "Jul 1, 2018, 2:34:56 PM") + "Jul 1, 2018, 2:34:56\N{Narrow No-Break Space}PM") self.assertEqual( ENGLISH.format_datetime_smart(datetime(2018, 7, 1, 12, 34, 56), datetime(2018, 6, 30, 21, 30), timezone=ROME), - "Jul 1, 2018, 2:34:56 PM") + "Jul 1, 2018, 2:34:56\N{Narrow No-Break Space}PM") # As above, localized. @@ -508,23 +508,23 @@ def test_large(self): def test_localized_zero(self): self.assertEqual(FRENCH.format_size(0), - "0 octet") + "0\N{No-Break Space}octet") def test_localized_small_values(self): self.assertEqual(FRENCH.format_size(1), - "1 octet") + "1\N{No-Break Space}octet") self.assertEqual(FRENCH.format_size(2), - "2 octets") + "2\N{No-Break Space}octets") def test_localized_cutoff_kib(self): self.assertEqual(FRENCH.format_size(999), - "999 octets") + "999\N{No-Break Space}octets") self.assertEqual(FRENCH.format_size(1000), - "1\N{NO-BREAK SPACE}000 octets") + "1\N{Narrow No-Break Space}000\N{No-Break Space}octets") self.assertEqual(FRENCH.format_size(1001), - "1\N{NO-BREAK SPACE}001 octets") + "1\N{Narrow No-Break Space}001\N{No-Break Space}octets") self.assertEqual(FRENCH.format_size(1023), - "1\N{NO-BREAK SPACE}023 octets") + "1\N{Narrow No-Break Space}023\N{No-Break Space}octets") self.assertEqual(FRENCH.format_size(1024), "1,00 Kio") self.assertEqual(FRENCH.format_size(1025), @@ -534,17 +534,16 @@ def test_localized_cutoff_mib(self): self.assertEqual(FRENCH.format_size(999 * 1024), "999 Kio") self.assertEqual(FRENCH.format_size(1000 * 1024), - "1\N{NO-BREAK SPACE}000 Kio") + "1\N{Narrow No-Break Space}000 Kio") self.assertEqual(FRENCH.format_size(1001 * 1024), - "1\N{NO-BREAK SPACE}001 Kio") + "1\N{Narrow No-Break Space}001 Kio") self.assertEqual(FRENCH.format_size(1023 * 1024), - "1\N{NO-BREAK SPACE}023 Kio") + "1\N{Narrow No-Break Space}023 Kio") self.assertEqual(FRENCH.format_size(1024 * 1024), "1,00 Mio") self.assertEqual(FRENCH.format_size(1025 * 1024), "1,00 Mio") - def test_localized_large(self): self.assertEqual(FRENCH.format_size(2_345_000), "2,24 Mio") @@ -553,7 +552,7 @@ def test_localized_large(self): self.assertEqual(FRENCH.format_size(456_789_000_000_000), "415 Tio") self.assertEqual(FRENCH.format_size(5_678_912_300_000_000), - "5\N{NO-BREAK SPACE}165 Tio") + "5\N{Narrow No-Break Space}165 Tio") class TestFormatDecimal(unittest.TestCase): @@ -594,7 +593,7 @@ class TestTranslateMimetype(unittest.TestCase): @unittest.skipIf(not os.path.isfile( "/usr/share/locale/it/LC_MESSAGES/shared-mime-info.mo"), - reason="need Italian shared-mime-info translation") + reason="need Italian shared-mime-info translation") def test_translate_mimetype(self): self.assertEqual(ENGLISH.translate_mimetype("PDF document"), "PDF document") diff --git a/codecov/.gitkeep b/codecov/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/Installation.rst b/docs/Installation.rst index 9ad179c2db..bf92fb67d3 100644 --- a/docs/Installation.rst +++ b/docs/Installation.rst @@ -49,7 +49,7 @@ All dependencies can be installed automatically on most Linux distributions. Ubuntu ------ -On Ubuntu 20.04, one will need to run the following script to satisfy all dependencies: +On Ubuntu 24.04, one will need to run the following script to satisfy all dependencies: .. sourcecode:: bash @@ -63,8 +63,8 @@ On Ubuntu 20.04, one will need to run the following script to satisfy all depend libffi-dev python3-pip # Optional - sudo apt-get install nginx-full python2.7 php7.4-cli php7.4-fpm \ - phppgadmin texlive-latex-base a2ps haskell-platform rustc mono-mcs + sudo apt-get install nginx-full python3 php-cli texlive-latex-base \ + a2ps ghc rustc mono-mcs The above commands provide a very essential Pascal environment. Consider installing the following packages for additional units: `fp-units-base`, `fp-units-fcl`, `fp-units-misc`, `fp-units-math` and `fp-units-rtl`. @@ -86,7 +86,7 @@ On Arch Linux, unofficial AUR packages can be found: `cms =4.5,<4.6 # http://www.tornadoweb.org/en/stable/releases.html -psycopg2>=2.8,<2.9 # http://initd.org/psycopg/articles/tag/release/ +tornado==4.5.3 # http://www.tornadoweb.org/en/stable/releases.html +psycopg2==2.9.7 # http://initd.org/psycopg/articles/tag/release/ sqlalchemy>=1.3,<1.4 # http://docs.sqlalchemy.org/en/latest/changelog/index.html netifaces>=0.10,<0.11 # https://bitbucket.org/al45tair/netifaces/src/ -pycryptodomex>=3.6,<3.7 # https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst +pycryptodomex==3.19.0 # https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst psutil>=5.5,<5.6 # https://github.com/giampaolo/psutil/blob/master/HISTORY.rst -requests>=2.22,<2.23 # https://pypi.python.org/pypi/requests -gevent==20.12.0 # http://www.gevent.org/changelog.html -# Limit greenlet version for binary compatibility with gevent 20.12 wheels -greenlet==1.0.0 -werkzeug>=0.16,<0.17 # https://github.com/pallets/werkzeug/blob/master/CHANGES +requests==2.32.3 # https://pypi.python.org/pypi/requests +gevent==23.9.0.post1 # http://www.gevent.org/changelog.html +werkzeug<1.0 # https://github.com/pallets/werkzeug/blob/master/CHANGES +backports.ssl-match-hostname==3.7.0.1 # required by tornado<5.0 +greenlet>=3.0rc1 patool>=1.12,<1.13 # https://github.com/wummel/patool/blob/master/doc/changelog.txt bcrypt>=3.1,<3.2 # https://github.com/pyca/bcrypt/ chardet>=3.0,<3.1 # https://pypi.python.org/pypi/chardet -babel>=2.6,<2.7 # http://babel.pocoo.org/en/latest/changelog.html +babel==2.12.1 # http://babel.pocoo.org/en/latest/changelog.html pyxdg>=0.26,<0.27 # https://freedesktop.org/wiki/Software/pyxdg/ Jinja2>=2.10,<2.11 # http://jinja.pocoo.org/docs/latest/changelog/ @@ -26,5 +24,5 @@ MarkupSafe==2.0.1 pyyaml>=5.3,<5.4 # http://pyyaml.org/wiki/PyYAML # Only for printing: -pycups>=1.9,<1.10 # https://pypi.python.org/pypi/pycups +pycups==2.0.4 # https://pypi.python.org/pypi/pycups PyPDF2>=1.26,<1.27 # https://github.com/mstamy2/PyPDF2/blob/master/CHANGELOG