diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ecbb323d2e..3eca4001ff 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,6 +23,7 @@ jobs: "3.8", "3.9", "3.10", + "3.11", ] include: - rule: "storage-service" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a945a716bd..c2caba41f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: rev: "1.15.0" hooks: - id: django-upgrade - args: [--target-version, "3.2"] + args: [--target-version, "4.2"] - repo: https://github.com/psf/black rev: "23.10.1" hooks: diff --git a/hack/submodules/archivematica-storage-service b/hack/submodules/archivematica-storage-service index 6f15665a68..41a28d7071 160000 --- a/hack/submodules/archivematica-storage-service +++ b/hack/submodules/archivematica-storage-service @@ -1 +1 @@ -Subproject commit 6f15665a683b70ec5d591c2ee73e8a33d1078d1d +Subproject commit 41a28d70712311670e2d97f1c20b7b329b610f44 diff --git a/requirements-dev.txt b/requirements-dev.txt index 2aa701fdc8..50a3c4251e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -14,7 +14,7 @@ asgiref==3.7.2 # via # -r requirements.txt # django -attrs==23.1.0 +attrs==23.2.0 # via # -r requirements.txt # jsonschema @@ -51,7 +51,7 @@ click==8.1.7 # pip-tools colorama==0.4.6 # via tox -coverage[toml]==7.3.2 +coverage[toml]==7.4.0 # via # -r requirements-dev.in # pytest-cov @@ -61,9 +61,9 @@ cryptography==41.0.7 # josepy # mozilla-django-oidc # pyopenssl -distlib==0.3.7 +distlib==0.3.8 # via virtualenv -django==3.2.23 +django==4.2.9 # via # -r requirements.txt # django-auth-ldap @@ -100,7 +100,7 @@ gearman3 @ git+https://github.com/artefactual-labs/python-gearman.git@b68efc868c # via -r requirements.txt gevent==23.9.1 # via -r requirements.txt -greenlet==3.0.1 +greenlet==3.0.3 # via # -r requirements.txt # gevent @@ -110,7 +110,7 @@ idna==3.6 # via # -r requirements.txt # requests -importlib-metadata==6.8.0 +importlib-metadata==7.0.1 # via # -r requirements.txt # build @@ -127,15 +127,15 @@ josepy==1.14.0 # via # -r requirements.txt # mozilla-django-oidc -jsonschema==4.20.0 +jsonschema==4.21.0 # via -r requirements.txt -jsonschema-specifications==2023.11.1 +jsonschema-specifications==2023.12.1 # via # -r requirements.txt # jsonschema lazy-paged-sequence==0.3 # via -r requirements.txt -lxml==4.9.3 +lxml==5.1.0 # via # -r requirements.txt # ammcpc @@ -145,13 +145,13 @@ metsrw==0.5.0 # via -r requirements.txt mockldap @ git+https://github.com/artefactual-labs/mockldap@v0.3.1 # via -r requirements-dev.in -mozilla-django-oidc==3.0.0 +mozilla-django-oidc==4.0.0 # via -r requirements.txt -mysqlclient==2.2.0 +mysqlclient==2.2.1 # via # -r requirements.txt # agentarchives -olefile==0.46 +olefile==0.47 # via # -r requirements.txt # opf-fido @@ -167,7 +167,7 @@ packaging==23.2 # tox pip-tools==7.3.0 # via -r requirements.txt -platformdirs==4.0.0 +platformdirs==4.1.0 # via # tox # virtualenv @@ -202,7 +202,7 @@ pyproject-hooks==1.0.0 # via # -r requirements.txt # build -pytest==7.4.3 +pytest==7.4.4 # via # -r requirements-dev.in # pytest-cov @@ -234,11 +234,7 @@ python-mimeparse==1.6.0 # via # -r requirements.txt # django-tastypie -pytz==2023.3.post1 - # via - # -r requirements.txt - # django -referencing==0.31.0 +referencing==0.32.1 # via # -r requirements.txt # jsonschema @@ -251,7 +247,7 @@ requests==2.31.0 # mozilla-django-oidc # opf-fido # python-cas -rpds-py==0.13.1 +rpds-py==0.17.1 # via # -r requirements.txt # jsonschema @@ -276,13 +272,13 @@ tomli==2.0.1 # pyproject-hooks # pytest # tox -tox==4.11.4 +tox==4.12.1 # via -r requirements-dev.in -typing-extensions==4.8.0 +typing-extensions==4.9.0 # via # -r requirements.txt # asgiref -unidecode==1.3.7 +unidecode==1.3.8 # via -r requirements.txt urllib3==2.1.0 # via @@ -290,7 +286,7 @@ urllib3==2.1.0 # amclient # elasticsearch # requests -virtualenv==20.24.7 +virtualenv==20.25.0 # via tox wheel==0.42.0 # via @@ -313,11 +309,11 @@ zope-interface==6.1 # gevent # The following packages are considered to be unsafe in a requirements file: -pip==23.3.1 +pip==23.3.2 # via # -r requirements.txt # pip-tools -setuptools==69.0.2 +setuptools==69.0.3 # via # -r requirements.txt # pip-tools diff --git a/requirements.in b/requirements.in index 79f20f180d..ab7dd2274f 100644 --- a/requirements.in +++ b/requirements.in @@ -1,5 +1,5 @@ git+https://github.com/Brown-University-Library/django-shibboleth-remoteuser.git@962f6f9818683ef5f6432f091d22945e54b82592#egg=django-shibboleth-remoteuser -Django>=3.2,<4 +Django>=4.2,<5 agentarchives amclient ammcpc @@ -9,7 +9,6 @@ clamd django-autoslug django-csp django-forms-bootstrap -django-prometheus>=2.2,<2.3; python_version == "3.6" django-prometheus django-tastypie elasticsearch>=6.0.0,<7.0.0 @@ -27,10 +26,8 @@ pip pip-tools prometheus_client python-dateutil -requests~=2.27; python_version == "3.6" requests unidecode -whitenoise>=5.3.0,<6.0; python_version == "3.6" whitenoise # Required by LDAP authentication @@ -41,5 +38,4 @@ python-ldap django-cas-ng # Required for OpenID Connect authentication -mozilla-django-oidc~=2.0; python_version == "3.6" mozilla-django-oidc diff --git a/requirements.txt b/requirements.txt index 768b160ad7..213910c9e6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ ammcpc==0.2.0 # via -r requirements.in asgiref==3.7.2 # via django -attrs==23.1.0 +attrs==23.2.0 # via # jsonschema # referencing @@ -37,7 +37,7 @@ cryptography==41.0.7 # josepy # mozilla-django-oidc # pyopenssl -django==3.2.23 +django==4.2.9 # via # -r requirements.in # django-auth-ldap @@ -66,13 +66,13 @@ gearman3 @ git+https://github.com/artefactual-labs/python-gearman.git@b68efc868c # via -r requirements.in gevent==23.9.1 # via -r requirements.in -greenlet==3.0.1 +greenlet==3.0.3 # via gevent gunicorn==21.2.0 # via -r requirements.in idna==3.6 # via requests -importlib-metadata==6.8.0 +importlib-metadata==7.0.1 # via # -r requirements.in # build @@ -82,13 +82,13 @@ inotify-simple==1.3.5 # via -r requirements.in josepy==1.14.0 # via mozilla-django-oidc -jsonschema==4.20.0 +jsonschema==4.21.0 # via -r requirements.in -jsonschema-specifications==2023.11.1 +jsonschema-specifications==2023.12.1 # via jsonschema lazy-paged-sequence==0.3 # via -r requirements.in -lxml==4.9.3 +lxml==5.1.0 # via # -r requirements.in # ammcpc @@ -96,11 +96,11 @@ lxml==4.9.3 # python-cas metsrw==0.5.0 # via -r requirements.in -mozilla-django-oidc==3.0.0 +mozilla-django-oidc==4.0.0 # via -r requirements.in -mysqlclient==2.2.0 +mysqlclient==2.2.1 # via agentarchives -olefile==0.46 +olefile==0.47 # via opf-fido opf-fido==1.6.1 # via -r requirements.in @@ -138,9 +138,7 @@ python-ldap==3.4.4 # django-auth-ldap python-mimeparse==1.6.0 # via django-tastypie -pytz==2023.3.post1 - # via django -referencing==0.31.0 +referencing==0.32.1 # via # jsonschema # jsonschema-specifications @@ -152,7 +150,7 @@ requests==2.31.0 # mozilla-django-oidc # opf-fido # python-cas -rpds-py==0.13.1 +rpds-py==0.17.1 # via # jsonschema # referencing @@ -168,9 +166,9 @@ tomli==2.0.1 # build # pip-tools # pyproject-hooks -typing-extensions==4.8.0 +typing-extensions==4.9.0 # via asgiref -unidecode==1.3.7 +unidecode==1.3.8 # via -r requirements.in urllib3==2.1.0 # via @@ -191,11 +189,11 @@ zope-interface==6.1 # via gevent # The following packages are considered to be unsafe in a requirements file: -pip==23.3.1 +pip==23.3.2 # via # -r requirements.in # pip-tools -setuptools==69.0.2 +setuptools==69.0.3 # via # pip-tools # zope-event diff --git a/src/MCPClient/tests/test_archivematicaClient.py b/src/MCPClient/tests/test_archivematicaClient.py index b979ded237..ea9865fc7c 100644 --- a/src/MCPClient/tests/test_archivematicaClient.py +++ b/src/MCPClient/tests/test_archivematicaClient.py @@ -23,14 +23,14 @@ def test_handle_batch_task_replaces_non_ascii_arguments(mocker): }, ) + # This is the only function that uses the arguments after the replacements + _parse_command_line = mocker.patch("archivematicaClient._parse_command_line") + # The mocked module will not have a `concurrent_instances` attribute mocker.patch( "importlib.import_module", return_value=mocker.MagicMock(spec=["call"]) ) - # This is the only function that uses the arguments after the replacements - _parse_command_line = mocker.patch("archivematicaClient._parse_command_line") - # Mock the two parameters sent to handle_batch_task gearman_job_mock = mocker.Mock(task=b"task name") supported_modules_mock = mocker.Mock(**{"get.side_effect": "some_module_name"}) diff --git a/src/MCPClient/tests/test_load_premis_events_from_xml.py b/src/MCPClient/tests/test_load_premis_events_from_xml.py index 7589c2156d..e9cc44d96e 100644 --- a/src/MCPClient/tests/test_load_premis_events_from_xml.py +++ b/src/MCPClient/tests/test_load_premis_events_from_xml.py @@ -187,7 +187,7 @@ def test_parse_datetime_with_valid_datetime_and_timezone(): result = load_premis_events_from_xml.parse_datetime("2019-09-24T16:54:21+04:00") assert (2019, 9, 24) == (result.year, result.month, result.day) assert (16, 54, 21) == (result.hour, result.minute, result.second) - assert "+0400" == result.tzname() + assert "UTC+04:00" == result.tzname() def test_parse_datetime_with_empty_string(): diff --git a/src/dashboard/src/components/administration/tests/test_dip_upload_configs.py b/src/dashboard/src/components/administration/tests/test_dip_upload_configs.py index a52f1163a4..487579e110 100644 --- a/src/dashboard/src/components/administration/tests/test_dip_upload_configs.py +++ b/src/dashboard/src/components/administration/tests/test_dip_upload_configs.py @@ -60,15 +60,23 @@ def test_post_missing_fields(self): self.assertFalse(form.is_valid()) self.assertTrue(form.errors) - self.assertFormError(response, "form", "user", "This field is required.") - self.assertFormError(response, "form", "xlink_show", "This field is required.") self.assertFormError( - response, "form", "xlink_actuate", "This field is required." + response.context["form"], "user", "This field is required." ) - self.assertFormError(response, "form", "uri_prefix", "This field is required.") - self.assertFormError(response, "form", "repository", "This field is required.") self.assertFormError( - response, "form", "restrictions", "This field is required." + response.context["form"], "xlink_show", "This field is required." + ) + self.assertFormError( + response.context["form"], "xlink_actuate", "This field is required." + ) + self.assertFormError( + response.context["form"], "uri_prefix", "This field is required." + ) + self.assertFormError( + response.context["form"], "repository", "This field is required." + ) + self.assertFormError( + response.context["form"], "restrictions", "This field is required." ) self.assertIsInstance(config, dict) @@ -128,8 +136,14 @@ def test_post_missing_fields(self): self.assertFalse(form.is_valid()) self.assertTrue(form.errors) - self.assertFormError(response, "form", "email", "This field is required.") - self.assertFormError(response, "form", "password", "This field is required.") - self.assertFormError(response, "form", "version", "This field is required.") + self.assertFormError( + response.context["form"], "email", "This field is required." + ) + self.assertFormError( + response.context["form"], "password", "This field is required." + ) + self.assertFormError( + response.context["form"], "version", "This field is required." + ) self.assertIsInstance(config, dict) diff --git a/src/dashboard/src/settings/base.py b/src/dashboard/src/settings/base.py index 91d976fc13..30bae8676b 100644 --- a/src/dashboard/src/settings/base.py +++ b/src/dashboard/src/settings/base.py @@ -290,14 +290,6 @@ def _get_settings_from_file(path): SITE_ID = 1 -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True - -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale -USE_L10N = True - # Enable timezone support, for more info see: # https://docs.djangoproject.com/en/dev/topics/i18n/timezones/ USE_TZ = True @@ -348,7 +340,14 @@ def _get_settings_from_file(path): # 'django.contrib.staticfiles.finders.DefaultStorageFinder', ) -STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", + }, +} TEMPLATES = [ { diff --git a/src/dashboard/src/settings/test.py b/src/dashboard/src/settings/test.py index b9b5014877..27c0b69f7e 100644 --- a/src/dashboard/src/settings/test.py +++ b/src/dashboard/src/settings/test.py @@ -53,7 +53,9 @@ } # Disable whitenoise -STATICFILES_STORAGE = None +STORAGES["staticfiles"][ + "BACKEND" +] = "django.contrib.staticfiles.storage.StaticFilesStorage" if MIDDLEWARE[0] == "whitenoise.middleware.WhiteNoiseMiddleware": del MIDDLEWARE[0] diff --git a/src/dashboard/tests/test_auth.py b/src/dashboard/tests/test_auth.py index 168bf496d4..62c857cfd7 100644 --- a/src/dashboard/tests/test_auth.py +++ b/src/dashboard/tests/test_auth.py @@ -74,7 +74,7 @@ def test_api_authenticates_via_key(self): for url in self.API_URLS: response = self.client.get( - url, HTTP_AUTHORIZATION=f"ApiKey test:{key}", follow=False + url, headers={"authorization": f"ApiKey test:{key}"}, follow=False ) self.assertEqual(response.status_code, 200)