diff --git a/cove/cove_360/templates/cove_360/validation_table.html b/cove/cove_360/templates/cove_360/validation_table.html
index 58b1ebdb..b5036ec2 100644
--- a/cove/cove_360/templates/cove_360/validation_table.html
+++ b/cove/cove_360/templates/cove_360/validation_table.html
@@ -1,5 +1,6 @@
{% load i18n %}
{% load cove_tags %}
+{% load cove_360_tags %}
{% for error_json, error_extra in validation_errors %}
{% with error=error_json|json_decode %}
diff --git a/cove/cove_360/templatetags/cove_tags.py b/cove/cove_360/templatetags/cove_360_tags.py
similarity index 98%
rename from cove/cove_360/templatetags/cove_tags.py
rename to cove/cove_360/templatetags/cove_360_tags.py
index 65d4553f..9e89d5b4 100644
--- a/cove/cove_360/templatetags/cove_tags.py
+++ b/cove/cove_360/templatetags/cove_360_tags.py
@@ -44,6 +44,6 @@ def multiply(a, b):
res = a*b
if res < 1:
- return f"{(a*b):.1f}"
+ return f"{(a*b): .1f}"
return int(round(res))
diff --git a/cove/cove_360/tests/test_browser.py b/cove/cove_360/tests/test_browser.py
index abfd00c7..cdf37448 100644
--- a/cove/cove_360/tests/test_browser.py
+++ b/cove/cove_360/tests/test_browser.py
@@ -40,13 +40,13 @@ def wait_for_results_page(browser):
def browser(request):
if BROWSER == 'Chrome':
chrome_options = Options()
- browser = webdriver.Chrome(chrome_options=chrome_options)
+ browser = webdriver.Chrome(options=chrome_options)
elif BROWSER == 'ChromeHeadless':
chrome_options = Options()
chrome_options.add_argument("--headless")
# uncomment this if "DevToolsActivePort" error
# chrome_options.add_argument("--remote-debugging-port=9222")
- browser = webdriver.Chrome(chrome_options=chrome_options)
+ browser = webdriver.Chrome(options=chrome_options)
else:
browser = getattr(webdriver, BROWSER)()
@@ -130,7 +130,7 @@ def server_url(request, live_server):
'0 is not a JSON object',
'amountAwarded is not a number. Check that the value is not null, and doesn’t contain any characters other than 0-9 and dot (.). Number values should not be in quotes.',
'plannedDates is not a JSON array',
- 'title is not a string. Check that the value is not null, and has quotes at the start and end. Escape any quotes in the value with \ (more info about this error)',
+ 'title is not a string. Check that the value is not null, and has quotes at the start and end. Escape any quotes in the value with \\ (more info about this error)',
'Invalid \'uri\' found (more info about this error)',
'Invalid code found in currency (more info about this error)',
'[] is too short. You must supply at least one value, or remove the item entirely (unless it’s required).',
@@ -406,19 +406,9 @@ def test_error_modal(server_url, browser, httpserver, source_filename):
assert len(table_rows) == 4
-@pytest.mark.parametrize(('data_url'), [
- reverse_lazy('results', args=['0']),
- reverse_lazy('results', args=['324ea8eb-f080-43ce-a8c1-9f47b28162f3']),
-])
-def test_url_invalid_dataset_request(server_url, browser, data_url):
- # Test a badly formed hexadecimal UUID string
- # Trim the / off reverse_lazy result as server_url has trailing slash to avoid
- # e.g. //results/0
-
- browser.get("%s%s" % (server_url, data_url[1:]))
- assert "We don't seem to be able to find the data you requested." in browser.find_element(By.TAG_NAME, 'body').text
+def test_url_invalid_dataset_request(server_url, browser):
# Test for well formed UUID that doesn't identify any dataset that exists
- browser.get("%s%s" % (server_url, reverse_lazy('results', args=['38e267ce-d395-46ba-acbf-2540cdd0c810'])[1:]))
+ browser.get("%s%s" % (server_url, reverse_lazy('results', args=['38e267ce-d395-46ba-acbf-2540cdd0c810'])))
assert "We don't seem to be able to find the data you requested." in browser.find_element(By.TAG_NAME, 'body').text
assert '360Giving' in browser.find_element(By.TAG_NAME, 'body').text
@@ -430,9 +420,13 @@ def test_500_error(server_url, browser):
def test_common_errors_page(server_url, browser):
- browser.get(server_url + 'common_errors/')
- assert "Common Errors" in browser.find_element(By.TAG_NAME, 'body').text
- assert '360Giving' in browser.find_element(By.TAG_NAME, 'body').text
+ path = reverse_lazy("common_errors")
+ browser.get(f"{server_url}/{path}")
+ content = browser.find_element(By.CLASS_NAME, "layout__content").text
+ # Make sure the expected page has loaded
+ assert "Common Errors" in content
+ # Make sure it is the 360Giving version
+ assert "360Giving" in content
def test_favicon(server_url, browser):
diff --git a/cove/cove_360/views.py b/cove/cove_360/views.py
index 454550ae..a97e0b98 100644
--- a/cove/cove_360/views.py
+++ b/cove/cove_360/views.py
@@ -14,7 +14,7 @@
from django.http import HttpResponse, JsonResponse
from django.shortcuts import redirect, render
from django.utils.html import format_html
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.core.cache import cache
from libcove.config import LibCoveConfig
diff --git a/cove/cove_project/urls.py b/cove/cove_project/urls.py
index 8fd6e90d..bf6ff0ba 100644
--- a/cove/cove_project/urls.py
+++ b/cove/cove_project/urls.py
@@ -1,4 +1,3 @@
-from django.conf.urls import url
from django.conf.urls.static import static
from django.conf import settings
from django.urls import path
@@ -10,15 +9,15 @@
import cove_360.api
urlpatterns += [
- url(r'^results/(.+)/advanced$', cove_360.views.explore_360, name='results', kwargs=dict(template='cove_360/explore_advanced.html')),
- url(r'^results/(.+)$', cove_360.views.explore_360, name='results'),
- url(r'^data/(.+)$', cove_360.views.data_loading, name='explore'),
- path("api/results/", cove_360.api.ResultsApiView.as_view(), name="api-results"),
- url(r'^xhr_results_ready/(.+)$', cove_360.views.results_ready, name='xhr_results_ready'),
- url(r'^common_errors', cove_360.views.common_errors, name='common_errors'),
- url(r'^additional_checks', cove_360.views.additional_checks, name='additional_checks'),
- path("submit/", TemplateView.as_view(template_name="cove_360/publishing.html", extra_context={"submission_tool": True}), name="publishing"),
- path("terms-conditions/", TemplateView.as_view(template_name="cove_360/terms.html"), name="terms-conditions"),
+ path("results//advanced", cove_360.views.explore_360, name='results', kwargs=dict(template='cove_360/explore_advanced.html')),
+ path("results/", cove_360.views.explore_360, name='results'),
+ path("data/", cove_360.views.data_loading, name='explore'),
+ path("api/results/", cove_360.api.ResultsApiView.as_view(), name="api-results"),
+ path("xhr_results_ready/", cove_360.views.results_ready, name='xhr_results_ready'),
+ path("common_errors", cove_360.views.common_errors, name='common_errors'),
+ path("additional_checks", cove_360.views.additional_checks, name='additional_checks'),
+ path("submit", TemplateView.as_view(template_name="cove_360/publishing.html", extra_context={"submission_tool": True}), name="publishing"),
+ path("terms-conditions", TemplateView.as_view(template_name="cove_360/terms.html"), name="terms-conditions"),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/lib360dataquality/cove/threesixtygiving.py b/lib360dataquality/cove/threesixtygiving.py
index 0f35d020..db57470a 100644
--- a/lib360dataquality/cove/threesixtygiving.py
+++ b/lib360dataquality/cove/threesixtygiving.py
@@ -481,7 +481,7 @@ def check_charity_number(charity_number):
return False
-company_pattern_re = re.compile("^\w{8}$")
+company_pattern_re = re.compile(r"^\w{8}$")
def check_company_number(company_number):
@@ -977,7 +977,7 @@ def process(self, grant, path_prefix):
self.message = mark_safe(self.check_text["message"][self.grants_percentage])
-compiled_email_re = re.compile("[\w.-]+@[\w.-]+\.[\w.-]+")
+compiled_email_re = re.compile(r"[\w.-]+@[\w.-]+\.[\w.-]+")
class LooksLikeEmail(AdditionalTest):
@@ -1713,7 +1713,7 @@ def process(self, grant, path_prefix):
# This is a simple regex, for something that "looks roughly like a postcode",
# which is all we need here.
# Modified to match when there are accidental leading and trailing spaces.
-postcode_re = re.compile("^\s*[a-z]{1,2}\d[a-z\d]?\s*\d[a-z]{2}\s*$", re.IGNORECASE)
+postcode_re = re.compile(r"^\s*[a-z]{1,2}\d[a-z\d]?\s*\d[a-z]{2}\s*$", re.IGNORECASE)
# Note that we ignore Geographic Code Type here because people putting in
diff --git a/requirements_cove.in b/requirements_cove.in
index aeac698d..673a2045 100644
--- a/requirements_cove.in
+++ b/requirements_cove.in
@@ -1,5 +1,5 @@
-e file:./
-Django>3.2,<3.3
+Django<5
flattentool>=0.17.0
libcove>=0.30.0
libcoveweb==0.31.1
diff --git a/requirements_cove.txt b/requirements_cove.txt
index 13fe8ca2..e4a33d34 100644
--- a/requirements_cove.txt
+++ b/requirements_cove.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.12
# by the following command:
#
# pip-compile ./requirements_cove.in
@@ -8,11 +8,11 @@
# via -r ./requirements_cove.in
asgiref==3.8.1
# via django
-attrs==25.1.0
+attrs==25.3.0
# via jsonschema
backports-datetime-fromisoformat==2.0.3
# via flattentool
-bleach==6.1.0
+bleach==6.2.0
# via -r ./requirements_cove.in
btrees==6.1
# via zodb
@@ -32,23 +32,23 @@ dealer==2.1.0
# via -r ./requirements_cove.in
defusedxml==0.7.1
# via odfpy
-django==3.2.25
+django==4.2.20
# via
# -r ./requirements_cove.in
# django-bootstrap3
# django-debug-toolbar
# libcoveweb
-django-bootstrap3==23.6
+django-bootstrap3==25.1
# via
# -r ./requirements_cove.in
# libcoveweb
-django-debug-toolbar==4.3.0
+django-debug-toolbar==5.1.0
# via -r ./requirements_cove.in
-django-environ==0.11.2
+django-environ==0.12.0
# via -r ./requirements_cove.in
et-xmlfile==2.0.0
# via openpyxl
-flattentool==0.26.0
+flattentool==0.27.0
# via
# -r ./requirements_cove.in
# libcove
@@ -59,7 +59,7 @@ ijson==3.3.0
# via
# flattentool
# lib360dataquality
-json-merge-patch==0.2
+json-merge-patch==0.3.0
# via
# -r ./requirements_cove.in
# lib360dataquality
@@ -81,7 +81,7 @@ libcoveweb==0.31.1
# via -r ./requirements_cove.in
lxml==5.3.1
# via flattentool
-markupsafe==2.1.5
+markupsafe==3.0.2
# via werkzeug
odfpy==1.4.1
# via flattentool
@@ -89,7 +89,7 @@ openpyxl==3.1.5
# via
# -r ./requirements_cove.in
# flattentool
-persistent==6.1
+persistent==6.1.1
# via
# btrees
# zodb
@@ -101,10 +101,8 @@ python-dateutil==2.9.0.post0
# via
# -r ./requirements_cove.in
# lib360dataquality
-pytz==2025.1
- # via
- # django
- # flattentool
+pytz==2025.2
+ # via flattentool
rangedict==0.1.7
# via
# -r ./requirements_cove.in
@@ -122,11 +120,10 @@ rfc3987==1.3.8
# libcove
schema==0.7.7
# via flattentool
-sentry-sdk==2.20.0
+sentry-sdk==2.24.1
# via -r ./requirements_cove.in
six==1.17.0
# via
- # bleach
# jsonschema
# python-dateutil
# rfc3339-validator
@@ -138,17 +135,15 @@ strict-rfc3339==0.7
# via -r ./requirements_cove.in
transaction==5.0
# via zodb
-typing-extensions==4.12.2
- # via asgiref
-urllib3==2.2.3
+urllib3==2.3.0
# via
# requests
# sentry-sdk
webencodings==0.5.1
# via bleach
-werkzeug==3.0.6
+werkzeug==3.1.3
# via libcoveweb
-whitenoise==6.7.0
+whitenoise==6.9.0
# via -r ./requirements_cove.in
xmltodict==0.14.2
# via
@@ -158,13 +153,13 @@ zc-lockfile==3.0.post1
# via zodb
zc-zlibstorage==1.2.0
# via flattentool
-zconfig==4.1
+zconfig==4.2
# via zodb
zodb==6.0
# via
# flattentool
# zc-zlibstorage
-zodbpickle==4.1.1
+zodbpickle==4.2
# via zodb
zope-deferredimport==5.0
# via persistent
diff --git a/requirements_cove_dev.txt b/requirements_cove_dev.txt
index 4013abf6..845c91dd 100644
--- a/requirements_cove_dev.txt
+++ b/requirements_cove_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.12
# by the following command:
#
# pip-compile ./requirements_cove_dev.in
#
-e file:./
- # via -r requirements_cove.in
-alabaster==0.7.13
+ # via -r ./requirements_cove.in
+alabaster==1.0.0
# via sphinx
asgiref==3.8.1
# via django
-attrs==25.1.0
+attrs==25.3.0
# via
# hypothesis
# jsonschema
@@ -20,14 +20,14 @@ babel==2.17.0
# via sphinx
backports-datetime-fromisoformat==2.0.3
# via flattentool
-black==24.8.0
+black==25.1.0
# via -r ./requirements_cove_dev.in
-bleach==6.1.0
- # via -r requirements_cove.in
+bleach==6.2.0
+ # via -r ./requirements_cove.in
btrees==6.1
# via zodb
cached-property==2.0.1
- # via -r requirements_cove.in
+ # via -r ./requirements_cove.in
certifi==2025.1.31
# via
# requests
@@ -45,66 +45,57 @@ click==8.1.8
# via black
commonmark==0.9.1
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# recommonmark
-coverage[toml]==7.6.1
+coverage[toml]==7.7.1
# via
# coveralls
# pytest-cov
coveralls==4.0.1
# via -r ./requirements_cove_dev.in
-cryptography==44.0.1
+cryptography==44.0.2
# via
# pyopenssl
# urllib3
dealer==2.1.0
- # via -r requirements_cove.in
+ # via -r ./requirements_cove.in
defusedxml==0.7.1
# via odfpy
-django==3.2.25
+django==4.2.20
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# django-bootstrap3
# django-debug-toolbar
# django-selenium-login
# libcoveweb
-django-bootstrap3==23.6
+django-bootstrap3==25.1
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# libcoveweb
-django-debug-toolbar==4.3.0
- # via -r requirements_cove.in
-django-environ==0.11.2
- # via -r requirements_cove.in
+django-debug-toolbar==5.1.0
+ # via -r ./requirements_cove.in
+django-environ==0.12.0
+ # via -r ./requirements_cove.in
django-selenium-login==2.0.0
# via -r ./requirements_cove_dev.in
docopt==0.6.2
# via coveralls
-docutils==0.20.1
+docutils==0.21.2
# via
# recommonmark
# sphinx
# sphinx-rtd-theme
et-xmlfile==2.0.0
# via openpyxl
-exceptiongroup==1.2.2
- # via
- # pytest
- # trio
- # trio-websocket
execnet==2.1.1
# via pytest-xdist
-flake8==7.1.1
+flake8==7.1.2
# via -r ./requirements_cove_dev.in
-flattentool==0.26.0
+flattentool==0.27.0
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# libcove
# libcoveweb
-gitdb==4.0.12
- # via gitpython
-gitpython==3.1.44
- # via transifex-client
h11==0.14.0
# via wsproto
hypothesis==6.13.0
@@ -120,15 +111,13 @@ ijson==3.3.0
# lib360dataquality
imagesize==1.4.1
# via sphinx
-importlib-metadata==8.5.0
- # via sphinx
-iniconfig==2.0.0
+iniconfig==2.1.0
# via pytest
-jinja2==3.1.5
+jinja2==3.1.6
# via sphinx
-json-merge-patch==0.2
+json-merge-patch==0.3.0
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# lib360dataquality
jsonref==1.1.0
# via
@@ -136,21 +125,21 @@ jsonref==1.1.0
# libcove
jsonschema==3.2.0
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# lib360dataquality
# libcove
libcove==0.31.0
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# lib360dataquality
# libcoveweb
libcoveweb==0.31.1
- # via -r requirements_cove.in
+ # via -r ./requirements_cove.in
libsass==0.23.0
# via -r ./requirements_cove_dev.in
lxml==5.3.1
# via flattentool
-markupsafe==2.1.5
+markupsafe==3.0.2
# via
# jinja2
# werkzeug
@@ -162,10 +151,12 @@ odfpy==1.4.1
# via flattentool
openpyxl==3.1.5
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# flattentool
outcome==1.3.0.post0
- # via trio
+ # via
+ # trio
+ # trio-websocket
packaging==24.2
# via
# black
@@ -174,11 +165,11 @@ packaging==24.2
# sphinx
pathspec==0.12.1
# via black
-persistent==6.1
+persistent==6.1.1
# via
# btrees
# zodb
-platformdirs==4.3.6
+platformdirs==4.3.7
# via black
pluggy==1.5.0
# via pytest
@@ -196,13 +187,13 @@ pyrsistent==0.20.0
# via jsonschema
pysocks==1.7.1
# via urllib3
-pytest==8.3.4
+pytest==8.3.5
# via
# -r ./requirements_cove_dev.in
# pytest-cov
# pytest-django
# pytest-xdist
-pytest-cov==5.0.0
+pytest-cov==6.0.0
# via -r ./requirements_cove_dev.in
pytest-django==4.10.0
# via -r ./requirements_cove_dev.in
@@ -212,50 +203,43 @@ pytest-xdist==3.6.1
# via -r ./requirements_cove_dev.in
python-dateutil==2.9.0.post0
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# lib360dataquality
-python-slugify==4.0.1
- # via transifex-client
-pytz==2025.1
- # via
- # babel
- # django
- # flattentool
+pytz==2025.2
+ # via flattentool
rangedict==0.1.7
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# lib360dataquality
recommonmark==0.7.1
# via -r ./requirements_cove_dev.in
requests==2.32.3
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# coveralls
# libcove
# libcoveweb
# sphinx
- # transifex-client
rfc3339-validator==0.1.4
# via libcove
rfc3987==1.3.8
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# libcove
+roman-numerals-py==3.1.0
+ # via sphinx
schema==0.7.7
# via flattentool
selenium==4.2.0
# via -r ./requirements_cove_dev.in
-sentry-sdk==2.20.0
- # via -r requirements_cove.in
+sentry-sdk==2.24.1
+ # via -r ./requirements_cove.in
six==1.17.0
# via
- # bleach
# jsonschema
# python-dateutil
# rfc3339-validator
# transifex-client
-smmap==5.0.2
- # via gitdb
sniffio==1.3.1
# via trio
snowballstemmer==2.2.0
@@ -264,7 +248,7 @@ sortedcontainers==2.4.0
# via
# hypothesis
# trio
-sphinx==7.1.2
+sphinx==8.2.3
# via
# -r ./requirements_cove_dev.in
# recommonmark
@@ -272,48 +256,38 @@ sphinx==7.1.2
# sphinxcontrib-jquery
sphinx-rtd-theme==3.0.2
# via -r ./requirements_cove_dev.in
-sphinxcontrib-applehelp==1.0.4
+sphinxcontrib-applehelp==2.0.0
# via sphinx
-sphinxcontrib-devhelp==1.0.2
+sphinxcontrib-devhelp==2.0.0
# via sphinx
-sphinxcontrib-htmlhelp==2.0.1
+sphinxcontrib-htmlhelp==2.1.0
# via sphinx
sphinxcontrib-jquery==4.1
# via sphinx-rtd-theme
sphinxcontrib-jsmath==1.0.1
# via sphinx
-sphinxcontrib-qthelp==1.0.3
+sphinxcontrib-qthelp==2.0.0
# via sphinx
-sphinxcontrib-serializinghtml==1.1.5
+sphinxcontrib-serializinghtml==2.0.0
# via sphinx
sqlparse==0.5.3
# via
# django
# django-debug-toolbar
strict-rfc3339==0.7
- # via -r requirements_cove.in
-text-unidecode==1.3
- # via python-slugify
-tomli==2.2.1
- # via
- # black
- # coverage
- # pytest
+ # via -r ./requirements_cove.in
transaction==5.0
# via zodb
-transifex-client==0.14.4
+transifex-client==0.12.5
# via -r ./requirements_cove_dev.in
-trio==0.27.0
+trio==0.29.0
# via
# selenium
# trio-websocket
-trio-websocket==0.11.1
+trio-websocket==0.12.2
# via selenium
typing-extensions==4.12.2
- # via
- # asgiref
- # black
- # pyopenssl
+ # via pyopenssl
urllib3[secure,socks]==1.26.20
# via
# requests
@@ -324,31 +298,29 @@ urllib3-secure-extra==0.1.0
# via urllib3
webencodings==0.5.1
# via bleach
-werkzeug==3.0.6
+werkzeug==3.1.3
# via
# libcoveweb
# pytest-localserver
-whitenoise==6.7.0
- # via -r requirements_cove.in
+whitenoise==6.9.0
+ # via -r ./requirements_cove.in
wsproto==1.2.0
# via trio-websocket
xmltodict==0.14.2
# via
- # -r requirements_cove.in
+ # -r ./requirements_cove.in
# flattentool
zc-lockfile==3.0.post1
# via zodb
zc-zlibstorage==1.2.0
# via flattentool
-zconfig==4.1
+zconfig==4.2
# via zodb
-zipp==3.20.2
- # via importlib-metadata
zodb==6.0
# via
# flattentool
# zc-zlibstorage
-zodbpickle==4.1.1
+zodbpickle==4.2
# via zodb
zope-deferredimport==5.0
# via persistent
diff --git a/requirements_cove_dokku.txt b/requirements_cove_dokku.txt
index d162656d..6b53ba49 100644
--- a/requirements_cove_dokku.txt
+++ b/requirements_cove_dokku.txt
@@ -1,8 +1,8 @@
#
-# This file is autogenerated by pip-compile with Python 3.8
+# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
-# pip-compile ./requirements_cove_dokku.in
+# pip-compile requirements_cove_dokku.in
#
-e file:./
# via -r requirements_cove.txt
@@ -10,7 +10,7 @@ asgiref==3.8.1
# via
# -r requirements_cove.txt
# django
-attrs==25.1.0
+attrs==25.3.0
# via
# -r requirements_cove.txt
# jsonschema
@@ -18,7 +18,7 @@ backports-datetime-fromisoformat==2.0.3
# via
# -r requirements_cove.txt
# flattentool
-bleach==6.1.0
+bleach==6.2.0
# via -r requirements_cove.txt
btrees==6.1
# via
@@ -47,31 +47,31 @@ defusedxml==0.7.1
# via
# -r requirements_cove.txt
# odfpy
-django==3.2.25
+django==4.2.20
# via
# -r requirements_cove.txt
# django-bootstrap3
# django-debug-toolbar
# libcoveweb
-django-bootstrap3==23.6
+django-bootstrap3==25.1
# via
# -r requirements_cove.txt
# libcoveweb
-django-debug-toolbar==4.3.0
+django-debug-toolbar==5.1.0
# via -r requirements_cove.txt
-django-environ==0.11.2
+django-environ==0.12.0
# via -r requirements_cove.txt
et-xmlfile==2.0.0
# via
# -r requirements_cove.txt
# openpyxl
-flattentool==0.26.0
+flattentool==0.27.0
# via
# -r requirements_cove.txt
# libcove
# libcoveweb
gunicorn==23.0.0
- # via -r ./requirements_cove_dokku.in
+ # via -r requirements_cove_dokku.in
idna==3.10
# via
# -r requirements_cove.txt
@@ -81,7 +81,7 @@ ijson==3.3.0
# -r requirements_cove.txt
# flattentool
# lib360dataquality
-json-merge-patch==0.2
+json-merge-patch==0.3.0
# via
# -r requirements_cove.txt
# lib360dataquality
@@ -106,7 +106,7 @@ lxml==5.3.1
# via
# -r requirements_cove.txt
# flattentool
-markupsafe==2.1.5
+markupsafe==3.0.2
# via
# -r requirements_cove.txt
# werkzeug
@@ -120,7 +120,7 @@ openpyxl==3.1.5
# flattentool
packaging==24.2
# via gunicorn
-persistent==6.1
+persistent==6.1.1
# via
# -r requirements_cove.txt
# btrees
@@ -137,10 +137,9 @@ python-dateutil==2.9.0.post0
# via
# -r requirements_cove.txt
# lib360dataquality
-pytz==2025.1
+pytz==2025.2
# via
# -r requirements_cove.txt
- # django
# flattentool
rangedict==0.1.7
# via
@@ -163,12 +162,11 @@ schema==0.7.7
# via
# -r requirements_cove.txt
# flattentool
-sentry-sdk==2.20.0
+sentry-sdk==2.24.1
# via -r requirements_cove.txt
six==1.17.0
# via
# -r requirements_cove.txt
- # bleach
# jsonschema
# python-dateutil
# rfc3339-validator
@@ -183,11 +181,7 @@ transaction==5.0
# via
# -r requirements_cove.txt
# zodb
-typing-extensions==4.12.2
- # via
- # -r requirements_cove.txt
- # asgiref
-urllib3==2.2.3
+urllib3==2.3.0
# via
# -r requirements_cove.txt
# requests
@@ -196,11 +190,11 @@ webencodings==0.5.1
# via
# -r requirements_cove.txt
# bleach
-werkzeug==3.0.6
+werkzeug==3.1.3
# via
# -r requirements_cove.txt
# libcoveweb
-whitenoise==6.7.0
+whitenoise==6.9.0
# via -r requirements_cove.txt
xmltodict==0.14.2
# via
@@ -214,7 +208,7 @@ zc-zlibstorage==1.2.0
# via
# -r requirements_cove.txt
# flattentool
-zconfig==4.1
+zconfig==4.2
# via
# -r requirements_cove.txt
# zodb
@@ -223,7 +217,7 @@ zodb==6.0
# -r requirements_cove.txt
# flattentool
# zc-zlibstorage
-zodbpickle==4.1.1
+zodbpickle==4.2
# via
# -r requirements_cove.txt
# zodb
diff --git a/requirements_dev.txt b/requirements_dev.txt
index f8ffefae..40421d44 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -1,30 +1,26 @@
#
-# This file is autogenerated by pip-compile with Python 3.8
+# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile requirements_dev.in
#
-black==23.1.0
+black==25.1.0
# via -r requirements_dev.in
-click==8.1.3
+click==8.1.8
# via black
-flake8==6.0.0
+flake8==7.1.2
# via -r requirements_dev.in
mccabe==0.7.0
# via flake8
mypy-extensions==1.0.0
# via black
-packaging==23.0
+packaging==24.2
# via black
-pathspec==0.11.1
+pathspec==0.12.1
# via black
-platformdirs==3.1.1
+platformdirs==4.3.7
# via black
-pycodestyle==2.10.0
+pycodestyle==2.12.1
# via flake8
-pyflakes==3.0.1
+pyflakes==3.2.0
# via flake8
-tomli==2.0.1
- # via black
-typing-extensions==4.5.0
- # via black
diff --git a/setup.py b/setup.py
index b57d8506..c2181ada 100644
--- a/setup.py
+++ b/setup.py
@@ -40,6 +40,6 @@
],
classifiers=[
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
- 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.12',
],
)
diff --git a/tools/check_grantnav_assumptions.py b/tools/check_grantnav_assumptions.py
index 04bedaf1..2c995c55 100755
--- a/tools/check_grantnav_assumptions.py
+++ b/tools/check_grantnav_assumptions.py
@@ -9,13 +9,13 @@
# We assmue that there are no one-to-many relationships besides location
def one_to_one_assumption(loc):
for x in loc:
- if type(x) == list:
+ if type(x) is list:
if len(x) == 2 and x[0] == x[1]:
print("WARNING, Duplicate lines")
else:
assert len(x) <= 1
one_to_one_assumption(x)
- elif type(x) == dict:
+ elif type(x) is dict:
one_to_one_assumption(x.values())
else:
# Check we've not got the wrong types above