diff --git a/src/paperless/checks.py b/src/paperless/checks.py index 150fcb201..5ac4db7ff 100644 --- a/src/paperless/checks.py +++ b/src/paperless/checks.py @@ -212,3 +212,31 @@ def audit_log_check(app_configs, **kwargs): ) return result + + +@register() +def check_postgres_version(app_configs, **kwargs): + """ + Django 5.2 removed PostgreSQL 13 support and thus it will be removed in + a future Paperless-ngx version. This check can be removed eventually. + See https://docs.djangoproject.com/en/5.2/releases/5.2/#dropped-support-for-postgresql-13 + """ + db_conn = connections["default"] + result = [] + if db_conn.vendor == "postgresql": + try: + with db_conn.cursor() as cursor: + cursor.execute("SHOW server_version;") + version = cursor.fetchone()[0] + if version.startswith("13"): + return [ + Warning( + "PostgreSQL 13 is deprecated and will not be supported in a future Paperless-ngx release.", + hint="Upgrade to PostgreSQL 14 or newer.", + ), + ] + except Exception: # pragma: no cover + # Don't block checks on version query failure + pass + + return result diff --git a/src/paperless/tests/test_checks.py b/src/paperless/tests/test_checks.py index ff6c25e43..a064a0d59 100644 --- a/src/paperless/tests/test_checks.py +++ b/src/paperless/tests/test_checks.py @@ -9,6 +9,7 @@ from documents.tests.utils import DirectoriesMixin from documents.tests.utils import FileSystemAssertsMixin from paperless.checks import audit_log_check from paperless.checks import binaries_check +from paperless.checks import check_postgres_version from paperless.checks import debug_mode_check from paperless.checks import paths_check from paperless.checks import settings_values_check @@ -262,3 +263,39 @@ class TestAuditLogChecks(TestCase): ("auditlog table was found but audit log is disabled."), msg.msg, ) + + +class TestPostgresVersionCheck(TestCase): + @mock.patch("paperless.checks.connections") + def test_postgres_13_warns(self, mock_connections): + mock_connection = mock.MagicMock() + mock_connection.vendor = "postgresql" + mock_cursor = mock.MagicMock() + mock_cursor.__enter__.return_value.fetchone.return_value = ["13.11"] + mock_connection.cursor.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_connection + + warnings = check_postgres_version(None) + self.assertEqual(len(warnings), 1) + self.assertIn("PostgreSQL 13 is deprecated", warnings[0].msg) + + @mock.patch("paperless.checks.connections") + def test_postgres_14_passes(self, mock_connections): + mock_connection = mock.MagicMock() + mock_connection.vendor = "postgresql" + mock_cursor = mock.MagicMock() + mock_cursor.__enter__.return_value.fetchone.return_value = ["14.10"] + mock_connection.cursor.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_connection + + warnings = check_postgres_version(None) + self.assertEqual(warnings, []) + + @mock.patch("paperless.checks.connections") + def test_non_postgres_skipped(self, mock_connections): + mock_connection = mock.MagicMock() + mock_connection.vendor = "sqlite" + mock_connections.__getitem__.return_value = mock_connection + + warnings = check_postgres_version(None) + self.assertEqual(warnings, [])