From 03b702dbee5f57baad0c49c26d93bc629fd3abd1 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Tue, 12 Mar 2024 13:20:54 +0100 Subject: [PATCH 01/13] update to Django 4.2.0 Python 3.11 --- backend/Dockerfile | 2 +- backend/DockerfileDevelop | 2 +- backend/aml/base_settings.py | 8 +++ backend/requirements.in/base.txt | 4 +- backend/requirements/dev.txt | 91 ++++++++++++-------------------- backend/requirements/prod.txt | 22 ++++---- docker-compose-deploy.yml | 1 + docker-compose.yaml | 1 + 8 files changed, 57 insertions(+), 74 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 3203cdf09..52a7734fe 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/python:3.8 +FROM docker.io/python:3.11 ENV PYTHONUNBUFFERED 1 RUN apt-get -y update RUN apt-get install -y ffmpeg diff --git a/backend/DockerfileDevelop b/backend/DockerfileDevelop index 78f994f53..b3f91d863 100644 --- a/backend/DockerfileDevelop +++ b/backend/DockerfileDevelop @@ -1,4 +1,4 @@ -FROM docker.io/python:3.8 as base +FROM docker.io/python:3.11 as base ENV PYTHONUNBUFFERED 1 RUN apt-get -y update RUN apt-get install -y ffmpeg gettext diff --git a/backend/aml/base_settings.py b/backend/aml/base_settings.py index b5d44b06f..8cb48c468 100644 --- a/backend/aml/base_settings.py +++ b/backend/aml/base_settings.py @@ -15,6 +15,11 @@ from corsheaders.defaults import default_headers import sentry_sdk +# Workaround for deprecated ugettext_lazy in django-inline-actions +import django +from django.utils.translation import gettext_lazy +django.utils.translation.ugettext_lazy = gettext_lazy + logger = logging.getLogger(__name__) # Build paths inside the project like this: os.path.join(BASE_DIR, ...) @@ -154,6 +159,7 @@ "http://localhost:3000,http://127.0.0.1:3000,{}".format(HOMEPAGE) ).split(",") + # CORS CORS_ORIGIN_ALLOW_ALL = False CORS_ALLOW_CREDENTIALS = True @@ -163,6 +169,8 @@ 'baggage', ] +CSRF_TRUSTED_ORIGINS = [os.getenv('CSRF_TRUSTED_ORIGINS')] + SESSION_SAVE_EVERY_REQUEST = False # Do not set to True, because it will break session-based participant_id CSRF_USE_SESSIONS = False diff --git a/backend/requirements.in/base.txt b/backend/requirements.in/base.txt index e53e70cfc..18c6ff5a8 100644 --- a/backend/requirements.in/base.txt +++ b/backend/requirements.in/base.txt @@ -2,7 +2,7 @@ audioread # Django Framework -Django<4.0 +Django~=4.2.0 # Django inline actions, admin extension django-inline-actions @@ -18,7 +18,7 @@ python-dotenv IPToCC # PostgrSQL database client -psycopg2 +psycopg[binary] # to convert labels to Roman numerals roman diff --git a/backend/requirements/dev.txt b/backend/requirements/dev.txt index 9547baaef..2402377e6 100644 --- a/backend/requirements/dev.txt +++ b/backend/requirements/dev.txt @@ -1,16 +1,16 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile --output-file=requirements/dev.txt requirements.in/dev.txt # -asgiref==3.4.1 +asgiref==3.7.2 # via django -astroid==2.8.3 +astroid==3.1.0 # via pylint -audioread==2.1.9 - # via -r requirements.in\base.txt -autopep8==1.5.7 +audioread==3.0.1 + # via -r requirements.in/base.txt +autopep8==2.0.4 # via -r requirements.in/dev.txt bleach==6.1.0 # via django-markup @@ -26,19 +26,15 @@ click==8.1.7 # via # genbadge # pip-tools -colorama==0.4.6 - # via - # build - # click - # pylint - # tqdm coverage==7.3.2 - # via -r requirements.in\base.txt + # via -r requirements.in/base.txt defusedxml==0.7.1 # via genbadge -django==3.2.24 +dill==0.3.8 + # via pylint +django==4.2.11 # via - # -r requirements.in\base.txt + # -r requirements.in/base.txt # django-cors-headers # django-debug-toolbar # django-inline-actions @@ -49,13 +45,13 @@ django-debug-toolbar==4.3.0 # via -r requirements.in/dev.txt django-inline-actions==2.4.0 # via -r requirements.in/base.txt -django-markup[all_filter_dependencies]==1.8.1 +django-markup[all-filter-dependencies,all_filter_dependencies]==1.8.1 # via -r requirements.in/base.txt docutils==0.20.1 # via # django-markup # python-creole -flake8==4.0.1 +flake8==7.0.0 # via -r requirements.in/dev.txt genbadge[coverage]==1.1.1 # via -r requirements.in/base.txt @@ -63,19 +59,13 @@ html5lib==1.1 # via textile idna==3.3 # via requests -importlib-metadata==7.0.0 - # via - # build - # markdown iptocc==2.1.2 - # via -r requirements.in\base.txt -isort==5.9.3 + # via -r requirements.in/base.txt +isort==5.13.2 # via pylint -lazy-object-proxy==1.6.0 - # via astroid markdown==3.5.2 # via django-markup -mccabe==0.6.1 +mccabe==0.7.0 # via # flake8 # pylint @@ -89,26 +79,28 @@ pillow==10.2.0 # via genbadge pip-tools==7.3.0 # via -r requirements.in/dev.txt -platformdirs==2.4.0 +platformdirs==4.2.0 # via pylint -psycopg2==2.9.1 - # via -r requirements.in\base.txt -pycodestyle==2.8.0 +psycopg[binary]==3.1.18 + # via -r requirements.in/base.txt +psycopg-binary==3.1.18 + # via psycopg +pycodestyle==2.11.1 # via # autopep8 # flake8 -pyflakes==2.4.0 +pyflakes==3.2.0 # via flake8 pygments==2.17.2 # via django-markup -pylint==2.11.1 +pylint==3.1.0 # via # -r requirements.in/dev.txt # pylint-django # pylint-plugin-utils -pylint-django==2.4.4 +pylint-django==2.5.5 # via -r requirements.in/dev.txt -pylint-plugin-utils==0.6 +pylint-plugin-utils==0.8.2 # via pylint-django pyproject-hooks==1.0.0 # via build @@ -117,11 +109,9 @@ python-creole==1.4.10 python-dateutil==2.8.2 # via pandas python-dotenv==0.19.1 - # via -r requirements.in\base.txt + # via -r requirements.in/base.txt pytz==2021.3 - # via - # django - # pandas + # via pandas regex==2023.12.25 # via textile requests==2.31.0 @@ -131,7 +121,7 @@ requests==2.31.0 roman==4.1 # via -r requirements.in/base.txt sentry-sdk==1.38.0 - # via -r requirements.in\base.txt + # via -r requirements.in/base.txt six==1.16.0 # via # bleach @@ -145,21 +135,12 @@ sqlparse==0.4.4 # django-debug-toolbar textile==4.0.2 # via django-markup -toml==0.10.2 - # via - # autopep8 - # pylint -tomli==2.0.1 - # via - # build - # pip-tools - # pyproject-hooks +tomlkit==0.12.4 + # via pylint tqdm==4.65.0 - # via -r requirements.in\base.txt -typing-extensions==3.10.0.2 - # via - # astroid - # pylint + # via -r requirements.in/base.txt +typing-extensions==4.10.0 + # via psycopg urllib3==1.26.18 # via # requests @@ -170,10 +151,6 @@ webencodings==0.5.1 # html5lib wheel==0.42.0 # via pip-tools -wrapt==1.13.2 - # via astroid -zipp==3.17.0 - # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/backend/requirements/prod.txt b/backend/requirements/prod.txt index de4794ebd..603ef43f9 100644 --- a/backend/requirements/prod.txt +++ b/backend/requirements/prod.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile --output-file=requirements/prod.txt requirements.in/prod.txt @@ -22,7 +22,7 @@ coverage==7.3.2 # via -r requirements.in/base.txt defusedxml==0.7.1 # via genbadge -django==3.2.24 +django==4.2.11 # via # -r requirements.in/base.txt # django-cors-headers @@ -32,7 +32,7 @@ django-cors-headers==4.0.0 # via -r requirements.in/base.txt django-inline-actions==2.4.0 # via -r requirements.in/base.txt -django-markup[all_filter_dependencies]==1.8.1 +django-markup[all-filter-dependencies,all_filter_dependencies]==1.8.1 # via -r requirements.in/base.txt docutils==0.20.1 # via @@ -46,8 +46,6 @@ html5lib==1.1 # via textile idna==3.6 # via requests -importlib-metadata==7.0.1 - # via markdown iptocc==2.1.2 # via -r requirements.in/base.txt markdown==3.5.2 @@ -58,8 +56,10 @@ pandas==1.5.3 # via iptocc pillow==10.2.0 # via genbadge -psycopg2==2.9.6 +psycopg[binary]==3.1.18 # via -r requirements.in/base.txt +psycopg-binary==3.1.18 + # via psycopg pygments==2.17.2 # via django-markup python-creole==1.4.10 @@ -69,9 +69,7 @@ python-dateutil==2.8.2 python-dotenv==1.0.0 # via -r requirements.in/base.txt pytz==2023.3 - # via - # django - # pandas + # via pandas regex==2023.12.25 # via textile requests==2.31.0 @@ -93,8 +91,8 @@ textile==4.0.2 # via django-markup tqdm==4.65.0 # via -r requirements.in/base.txt -typing-extensions==4.6.3 - # via asgiref +typing-extensions==4.10.0 + # via psycopg urllib3==2.1.0 # via # requests @@ -103,8 +101,6 @@ webencodings==0.5.1 # via # bleach # html5lib -zipp==3.17.0 - # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index c6a0f8f16..ac38f0ea8 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -43,6 +43,7 @@ services: - /home/github-runner/podman-volumes/server-uploads:/server/upload environment: - AML_ALLOWED_HOSTS=${AML_ALLOWED_HOSTS} + - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS} - AML_DEBUG=${AML_DEBUG} - AML_CORS_ORIGIN_WHITELIST=${AML_CORS_ORIGIN_WHITELIST} - AML_LOCATION_PROVIDER=${AML_LOCATION_PROVIDER} diff --git a/docker-compose.yaml b/docker-compose.yaml index 74f7fbba8..fcd901e03 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -41,6 +41,7 @@ services: target: /server environment: - AML_ALLOWED_HOSTS=${AML_ALLOWED_HOSTS} + - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS} - AML_DEBUG=${AML_DEBUG} - DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE} - DJANGO_SUPERUSER_USERNAME=${DJANGO_SUPERUSER_USERNAME} From ccf818ea10fee2d1bc752054bb27067715faa32c Mon Sep 17 00:00:00 2001 From: Evert-R Date: Tue, 19 Mar 2024 11:28:11 +0100 Subject: [PATCH 02/13] add csrf trusted origins --- .env.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.dist b/.env.dist index 2a1d19699..ad6ffb249 100644 --- a/.env.dist +++ b/.env.dist @@ -14,6 +14,7 @@ DJANGO_SUPERUSER_PASSWORD=admin # do not use in production! DJANGO_SUPERUSER_EMAIL=mail@example.com # do not use in production! AML_LOCATION_PROVIDER=http://ip2country:5000/{} # address of the ip2country container, don't change AML_ALLOWED_HOSTS="localhost" # needs to be changed when running in production +CSRF_TRUSTED_ORIGINS=http://localhost:3000 # needs to be changed when running in production FRONTEND_API_ROOT=http://localhost:8000 # address of the server, don't change FRONTEND_EXPERIMENT_SLUG=gold-msi # experiment slug that the frontend redirects to From cafc6fa86d3ca240fc3e34b26a69be8da5c14ace Mon Sep 17 00:00:00 2001 From: Evert-R Date: Thu, 21 Mar 2024 14:01:49 +0100 Subject: [PATCH 03/13] use FRONTEND_API_ROOT for CSRF_TRUSTED_ORIGINS --- docker-compose-deploy.yml | 2 +- docker-compose.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index 775b1781e..7a4a03df3 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -43,7 +43,7 @@ services: - /home/github-runner/podman-volumes/server-uploads:/server/upload environment: - AML_ALLOWED_HOSTS=${AML_ALLOWED_HOSTS} - - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS} + - CSRF_TRUSTED_ORIGINS=${FRONTEND_API_ROOT} - AML_DEBUG=${AML_DEBUG} - AML_CORS_ORIGIN_WHITELIST=${AML_CORS_ORIGIN_WHITELIST} - AML_LOCATION_PROVIDER=${AML_LOCATION_PROVIDER} diff --git a/docker-compose.yaml b/docker-compose.yaml index e8756e6dc..0894a0b1c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -41,7 +41,7 @@ services: target: /server environment: - AML_ALLOWED_HOSTS=${AML_ALLOWED_HOSTS} - - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS} + - CSRF_TRUSTED_ORIGINS=${FRONTEND_API_ROOT} - AML_DEBUG=${AML_DEBUG} - DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE} - DJANGO_SUPERUSER_USERNAME=${DJANGO_SUPERUSER_USERNAME} From e4f9ede936018cb9a4be687b17218463fb920804 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Thu, 21 Mar 2024 14:25:23 +0100 Subject: [PATCH 04/13] revert CSRF_TRUSTED_ORIGINS to new env variable --- docker-compose-deploy.yml | 2 +- docker-compose.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index 7a4a03df3..775b1781e 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -43,7 +43,7 @@ services: - /home/github-runner/podman-volumes/server-uploads:/server/upload environment: - AML_ALLOWED_HOSTS=${AML_ALLOWED_HOSTS} - - CSRF_TRUSTED_ORIGINS=${FRONTEND_API_ROOT} + - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS} - AML_DEBUG=${AML_DEBUG} - AML_CORS_ORIGIN_WHITELIST=${AML_CORS_ORIGIN_WHITELIST} - AML_LOCATION_PROVIDER=${AML_LOCATION_PROVIDER} diff --git a/docker-compose.yaml b/docker-compose.yaml index 0894a0b1c..e8756e6dc 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -41,7 +41,7 @@ services: target: /server environment: - AML_ALLOWED_HOSTS=${AML_ALLOWED_HOSTS} - - CSRF_TRUSTED_ORIGINS=${FRONTEND_API_ROOT} + - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS} - AML_DEBUG=${AML_DEBUG} - DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE} - DJANGO_SUPERUSER_USERNAME=${DJANGO_SUPERUSER_USERNAME} From 28b374367ca70e6b86b2a31508ca21436875e791 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Tue, 26 Mar 2024 08:24:16 +0100 Subject: [PATCH 05/13] Only update_admin_csv if playlist already has an id --- backend/section/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/section/models.py b/backend/section/models.py index 4ed8ecda9..225807ed1 100644 --- a/backend/section/models.py +++ b/backend/section/models.py @@ -30,7 +30,7 @@ class Playlist(models.Model): def save(self, *args, **kwargs): """Update playlist csv field on every save""" - if self.process_csv is False: + if self.process_csv is False and self.id: self.csv = self.update_admin_csv() if self.url_prefix and self.url_prefix[-1] != '/': self.url_prefix += '/' @@ -199,7 +199,7 @@ def export_sections(self): def update_admin_csv(self): """Update csv data for admin""" csvfile = CsvStringBuilder() - writer = csv.writer(csvfile) + writer = csv.writer(csvfile) for section in self.section_set.all(): if section.song: this_artist = section.song.artist From c2a13c86d6ff77ac1858760587bc0b669b767863 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Tue, 26 Mar 2024 10:01:12 +0100 Subject: [PATCH 06/13] forced sequence for random.sample (update for: python3.11) --- backend/experiment/rules/eurovision_2020.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/experiment/rules/eurovision_2020.py b/backend/experiment/rules/eurovision_2020.py index d632fa752..7eb6617a0 100644 --- a/backend/experiment/rules/eurovision_2020.py +++ b/backend/experiment/rules/eurovision_2020.py @@ -34,11 +34,11 @@ def plan_sections(self, session): n_free = session.experiment.rounds - 2 * n_old - n_new # Assign songs. - old_songs = random.sample(old_new_song_set, k=n_old) - free_songs = random.sample(free_song_set - set(old_songs), k=n_free) + old_songs = random.sample(list(old_new_song_set), k=n_old) + free_songs = random.sample(list(free_song_set - set(old_songs)), k=n_free) new_songs = \ random.sample( - free_song_set - set(old_songs + free_songs), + list(free_song_set - set(old_songs + free_songs)), k=n_new ) From 00022dc03c8a166470ce6a2725c5a2aff6939097 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Tue, 25 Jun 2024 14:16:17 +0200 Subject: [PATCH 07/13] update packages --- backend/requirements/dev.txt | 17 ++++------------- backend/requirements/prod.txt | 4 +++- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/backend/requirements/dev.txt b/backend/requirements/dev.txt index 2a64f8f8b..f0ca87b3c 100644 --- a/backend/requirements/dev.txt +++ b/backend/requirements/dev.txt @@ -135,21 +135,12 @@ sqlparse==0.5.0 # django-debug-toolbar textile==4.0.2 # via django-markup -toml==0.10.2 - # via - # autopep8 - # pylint -tomli==2.0.1 - # via - # build - # pip-tools - # pyproject-hooks +tomlkit==0.12.5 + # via pylint tqdm==4.65.0 - # via -r requirements.in\base.txt + # via -r requirements.in/base.txt typing-extensions==4.10.0 - # via - # astroid - # pylint + # via psycopg urllib3==1.26.19 # via # requests diff --git a/backend/requirements/prod.txt b/backend/requirements/prod.txt index 8c1483817..f5d55ec02 100644 --- a/backend/requirements/prod.txt +++ b/backend/requirements/prod.txt @@ -52,6 +52,8 @@ markdown==3.5.2 # via django-markup numpy==1.24.3 # via pandas +packaging==24.1 + # via gunicorn pandas==1.5.3 # via iptocc pillow==10.3.0 @@ -92,7 +94,7 @@ textile==4.0.2 tqdm==4.66.3 # via -r requirements.in/base.txt typing-extensions==4.10.0 - # via asgiref + # via psycopg urllib3==2.1.0 # via # requests From 47f4302b6e4041ee630fdaa002152b1802dc3746 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Wed, 26 Jun 2024 10:10:50 +0200 Subject: [PATCH 08/13] validate_playlist has to be passed an object --- backend/experiment/rules/tests/test_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/experiment/rules/tests/test_base.py b/backend/experiment/rules/tests/test_base.py index 1e96d1f2e..bf00bce89 100644 --- a/backend/experiment/rules/tests/test_base.py +++ b/backend/experiment/rules/tests/test_base.py @@ -66,6 +66,6 @@ def test_validate_playlist(self): errors = base.validate_playlist(playlist) self.assertEqual(errors, ['The experiment must have a playlist.']) - playlist = Playlist() + playlist = Playlist.objects.create() errors = base.validate_playlist(playlist) - self.assertEqual(errors, ['The experiment must have at least one section.']) \ No newline at end of file + self.assertEqual(errors, ['The experiment must have at least one section.']) From 953c635d2639304fde6be6a2fd49d64a052fed50 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Wed, 26 Jun 2024 10:13:33 +0200 Subject: [PATCH 09/13] validate_playlist has to be be passed an instance or None --- backend/experiment/rules/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/experiment/rules/base.py b/backend/experiment/rules/base.py index 57481a636..acf2df4fe 100644 --- a/backend/experiment/rules/base.py +++ b/backend/experiment/rules/base.py @@ -164,7 +164,7 @@ def social_media_info(self, experiment, score): 'hashtags': [experiment.hashtag or experiment.slug, "amsterdammusiclab", "citizenscience"] } - def validate_playlist(self, playlist: Playlist): + def validate_playlist(self, playlist: None): errors = [] # Common validations across experiments if not playlist: @@ -177,7 +177,7 @@ def validate_playlist(self, playlist: Playlist): errors.append('The experiment must have at least one section.') try: - Playlist.clean_csv(playlist) + playlist.clean_csv() except ValidationError as e: errors += e.error_list From 997c676abf398f9eaaf18c460c2396d13882c4e3 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Wed, 26 Jun 2024 12:45:01 +0200 Subject: [PATCH 10/13] Fix tests for django 4.2 --- .../experiment/tests/test_admin_experiment.py | 39 ++++++++++--------- backend/image/tests/test_admin.py | 10 ++--- backend/theme/tests/test_admin.py | 18 +++------ 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/backend/experiment/tests/test_admin_experiment.py b/backend/experiment/tests/test_admin_experiment.py index 9d19f15f4..1b638050a 100644 --- a/backend/experiment/tests/test_admin_experiment.py +++ b/backend/experiment/tests/test_admin_experiment.py @@ -26,9 +26,6 @@ class MockRequest: request = MockRequest() -this_experiment_admin = ExperimentAdmin( - model=Experiment, admin_site=AdminSite) - class TestAdminExperiment(TestCase): @@ -47,6 +44,11 @@ def setUpTestData(cls): session=Session.objects.first() ) + def setUp(self): + self.admin = ExperimentAdmin(model=Experiment, + admin_site=AdminSite + ) + def test_experiment_model_fields(self): experiment = model_to_dict(Experiment.objects.first()) experiment_fields = [key for key in experiment] @@ -109,9 +111,12 @@ def setUpTestData(cls): def setUp(self): self.client = Client() - + self.admin = ExperimentAdmin(model=Experiment, + admin_site=AdminSite + ) + def test_admin_export(self): - response = this_experiment_admin.export(request, self.experiment) + response = self.admin.export(request, self.experiment) zip_buffer = BytesIO(response.content) with ZipFile(zip_buffer, 'r') as test_zip: # Test files inside zip @@ -174,8 +179,11 @@ def setUpTestData(self): description='test description very long like the tea of oolong and the song of the bird in the morning', slug='TEST', ) - self.site = AdminSite() - self.admin = ExperimentCollectionAdmin(ExperimentCollection, self.site) + + def setUp(self): + self.admin = ExperimentCollectionAdmin(model=ExperimentCollection, + admin_site=AdminSite + ) def test_experiment_series_admin_list_display(self): self.assertEqual( @@ -208,20 +216,16 @@ def test_experiment_collection_admin_research_dashboard(self): class PhaseAdminTest(TestCase): - @classmethod - def setUpTestData(self): - self.factory = RequestFactory() - self.site = AdminSite() - self.admin = PhaseAdmin( - Phase, - self.site - ) + + def setUp(self): + self.admin = PhaseAdmin(model=Phase, + admin_site=AdminSite + ) def test_related_series_with_series(self): series = ExperimentCollection.objects.create(name='Test Series') phase = Phase.objects.create( name='Test Group', order=1, randomize=False, series=series, dashboard=True) - request = self.factory.get('/') related_series = self.admin.related_series(phase) expected_url = reverse( "admin:experiment_experimentcollection_change", args=[series.pk]) @@ -243,8 +247,7 @@ def test_experiments_with_experiments(self): experiment2 = Experiment.objects.create(name='Experiment 2', slug='experiment-2') grouped_experiment1 = GroupedExperiment.objects.create(phase=phase, experiment=experiment1) grouped_experiment2 = GroupedExperiment.objects.create(phase=phase, experiment=experiment2) - - request = self.factory.get('/') + experiments = self.admin.experiments(phase) expected_experiments = format_html( ', '.join([ diff --git a/backend/image/tests/test_admin.py b/backend/image/tests/test_admin.py index 832f9ce45..f59609f3f 100644 --- a/backend/image/tests/test_admin.py +++ b/backend/image/tests/test_admin.py @@ -7,11 +7,11 @@ class ImageAdminTest(TestCase): - @classmethod - def setUpTestData(cls): - cls.factory = RequestFactory() - cls.site = AdminSite() - cls.admin = ImageAdmin(Image, cls.site) + + def setUp(self): + self.admin = ImageAdmin(model=Image, + admin_site=AdminSite + ) def test_image_preview_with_file(self): image = Image.objects.create(file='path/to/image.jpg') diff --git a/backend/theme/tests/test_admin.py b/backend/theme/tests/test_admin.py index a1cbbbef1..3790d2495 100644 --- a/backend/theme/tests/test_admin.py +++ b/backend/theme/tests/test_admin.py @@ -1,5 +1,5 @@ from django.contrib.admin.sites import AdminSite -from django.test import TestCase, RequestFactory +from django.test import TestCase from image.models import Image from theme.admin import ThemeConfigAdmin @@ -7,15 +7,14 @@ class ThemeConfigAdminTest(TestCase): - @classmethod - def setUpTestData(cls): - cls.factory = RequestFactory() - cls.site = AdminSite() - cls.admin = ThemeConfigAdmin(ThemeConfig, cls.site) + + def setUp(self): + self.admin = ThemeConfigAdmin(model=ThemeConfig, + admin_site=AdminSite + ) def test_heading_font_preview_with_url(self): theme = ThemeConfig.objects.create(heading_font_url='https://example.com/font.css') - request = self.factory.get('/') preview = self.admin.heading_font_preview(theme) expected_preview = ( '' @@ -25,7 +24,6 @@ def test_heading_font_preview_with_url(self): def test_heading_font_preview_with_google_font_name(self): theme = ThemeConfig.objects.create(heading_font_url='Roboto') - request = self.factory.get('/') preview = self.admin.heading_font_preview(theme) expected_preview = ( '' @@ -35,13 +33,11 @@ def test_heading_font_preview_with_google_font_name(self): def test_heading_font_preview_with_no_font(self): theme = ThemeConfig.objects.create(heading_font_url='') - request = self.factory.get('/') preview = self.admin.heading_font_preview(theme) self.assertEqual(preview, "No font selected") def test_body_font_preview_with_url(self): theme = ThemeConfig.objects.create(body_font_url='https://example.com/font.css') - request = self.factory.get('/') preview = self.admin.body_font_preview(theme) expected_preview = ( '' @@ -51,7 +47,6 @@ def test_body_font_preview_with_url(self): def test_body_font_preview_with_google_font_name(self): theme = ThemeConfig.objects.create(body_font_url='Roboto') - request = self.factory.get('/') preview = self.admin.body_font_preview(theme) expected_preview = ( '' @@ -61,7 +56,6 @@ def test_body_font_preview_with_google_font_name(self): def test_body_font_preview_with_no_font(self): theme = ThemeConfig.objects.create(body_font_url='') - request = self.factory.get('/') preview = self.admin.body_font_preview(theme) self.assertEqual(preview, "No font selected") From 5e77de36d87554161b0480ade26acff4609d5510 Mon Sep 17 00:00:00 2001 From: Evert-R Date: Wed, 26 Jun 2024 13:10:09 +0200 Subject: [PATCH 11/13] fix for django 4.2 - csv file was always processed --- backend/section/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/section/forms.py b/backend/section/forms.py index 6b3b55283..e4b7fb3b6 100644 --- a/backend/section/forms.py +++ b/backend/section/forms.py @@ -78,7 +78,7 @@ def save(self, commit=True): # Handle uploaded CSV file csv_file = self.cleaned_data.get('csv_file') - if csv_file: + if csv_file and playlist.process_csv: # Read and process the CSV file playlist.csv = csv_file.read().decode('utf-8') From a7d23c27a6795440904988ceef8830ab7b2dec6e Mon Sep 17 00:00:00 2001 From: Evert-R Date: Wed, 26 Jun 2024 16:01:09 +0200 Subject: [PATCH 12/13] Add CSRF_TRUSTED_ORIGINS for django 4.2 --- .env-github-actions | 1 + 1 file changed, 1 insertion(+) diff --git a/.env-github-actions b/.env-github-actions index 8bf64eac4..8e7f7c7f7 100644 --- a/.env-github-actions +++ b/.env-github-actions @@ -7,6 +7,7 @@ AML_SECRET_KEY=amlsecretkey AML_LOCATION_PROVIDER=http://ip2country:5000/{} AML_DEBUG=True DJANGO_SETTINGS_MODULE=aml.development_settings +CSRF_TRUSTED_ORIGINS=http://localhost:3000 FRONTEND_API_ROOT=http://localhost:8000 FRONTEND_EXPERIMENT_SLUG=gold-msi From 907ee898e473a064e39b22147844a60a5c648aeb Mon Sep 17 00:00:00 2001 From: Evert-R Date: Wed, 26 Jun 2024 16:25:33 +0200 Subject: [PATCH 13/13] Rearranged comments for updated flake8 version --- backend/.flake8 | 90 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/backend/.flake8 b/backend/.flake8 index 0605143d0..5461f2cec 100644 --- a/backend/.flake8 +++ b/backend/.flake8 @@ -4,42 +4,72 @@ # High Priority: Security and Correctness # These issues are critical and should be addressed first. extend-ignore = - E722, # Do not use bare 'except' - F722, # Syntax error identified by pyflakes - F821, # Undefined name + # Do not use bare 'except' + E722, + # Syntax error identified by pyflakes + F722, + # Undefined name + F821, # Medium Priority: Code Maintainability and Readability # Improving these can greatly enhance code readability and maintainability. - E501, # Line too long - F401, # Unused import - F403, # 'from module import *' used; unable to detect undefined names - F405, # Name may be undefined, or defined from star imports - F811, # Redefinition of unused name from line N - F841, # Local variable name is assigned to but never used + # Line too long + E501, + # Unused import + F401, + # 'from module import *' used; unable to detect undefined names + F403, + # Name may be undefined, or defined from star imports + F405, + # Redefinition of unused name from line N + F811, + # Local variable name is assigned to but never used + F841, # Low Priority: Style Guide Adherence # These are mostly about whitespace and indentation, which can be adjusted later. - E201, # Whitespace after '(' - E202, # Whitespace before ')' - E203, # Whitespace before ':' - E222, # Multiple spaces after operator - E225, # Missing whitespace around operator - E231, # Missing whitespace after ',' - E251, # Unexpected spaces around keyword / parameter equals - E262, # Inline comment should start with '# ' - E122, # Continuation line missing indentation or outdented - E124, # Closing bracket does not match visual indentation - E125, # Continuation line with same indent as next logical line - E127, # Continuation line over-indented for visual indent - E128, # Continuation line under-indented for visual indent - E131, # Continuation line unaligned for hanging indent - E261, # At least two spaces before inline comment - W191, # Indentation contains tabs - W291, # Trailing whitespace - W292, # No newline at end of file - W293, # Blank line contains whitespace - W391, # Blank line at end of file - W503, # Line break occurred before a binary operator + # Whitespace after '(' + E201, + # Whitespace before ')' + E202, + # Whitespace before ':' + E203, + # Multiple spaces after operator + E222, + # Missing whitespace around operator + E225, + # Missing whitespace after ',' + E231, + # Unexpected spaces around keyword / parameter equals + E251, + # Inline comment should start with '# ' + E262, + # Continuation line missing indentation or outdented + E122, + # Closing bracket does not match visual indentation + E124, + # Continuation line with same indent as next logical line + E125, + # Continuation line over-indented for visual indent + E127, + # Continuation line under-indented for visual indent + E128, + # Continuation line unaligned for hanging indent + E131, + # At least two spaces before inline comment + E261, + # Indentation contains tabs + W191, + # Trailing whitespace + W291, + # No newline at end of file + W292, + # Blank line contains whitespace + W293, + # Blank line at end of file + W391, + # Line break occurred before a binary operator + W503, # General Configuration max-line-length = 120