diff --git a/.github/workflows/test-examples-proj1.yml b/.github/workflows/test-examples-proj1.yml index 49a1e98..94b603e 100644 --- a/.github/workflows/test-examples-proj1.yml +++ b/.github/workflows/test-examples-proj1.yml @@ -11,7 +11,7 @@ jobs: max-parallel: 5 matrix: python-version: ['3.10'] - django-version: ['3.2', '4.0', '4.2'] + django-version: ['3.2', '4.0', '4.2', '5.0'] include: - django-version: 'main' python-version: '3.10' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7225c37..43df145 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,12 +11,20 @@ jobs: max-parallel: 5 matrix: python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] - django-version: ['3.2', '4.0', '4.2'] - include: - - django-version: 'main' + django-version: ['3.2', '4.0', '4.2', '5.0'] + exclude: + - python-version: '3.11' + django-version: '3.2' + - python-version: '3.12' + django-version: '3.2' + - django-version: '5.0' + python-version: '3.8' + - django-version: '5.0' python-version: '3.9' - django-version: 'main' - python-version: '3.10' + python-version: '3.8' + - django-version: 'main' + python-version: '3.9' services: postgres: diff --git a/CHANGES.rst b/CHANGES.rst index 2b52c9d..9223d86 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,13 @@ CHANGES ======= +4.2.0 (Unreleased) +------------------ + +Features: + +* #143 Add Django-5.0 support. + 4.1.1 (2024/08/20) ------------------ diff --git a/django_redshift_backend/_vendor/django40/db/backends/base/base.py b/django_redshift_backend/_vendor/django40/db/backends/base/base.py index 9f37b84..d0092b1 100644 --- a/django_redshift_backend/_vendor/django40/db/backends/base/base.py +++ b/django_redshift_backend/_vendor/django40/db/backends/base/base.py @@ -5,6 +5,7 @@ import warnings from collections import deque from contextlib import contextmanager +from datetime import timezone as pytimezone try: import zoneinfo @@ -23,6 +24,9 @@ from django.utils.asyncio import async_unsafe from django.utils.functional import cached_property +# django.utils.timezone.utc has been removed in django 5.0 +timezone.utc = pytimezone.utc + NO_DB_ALIAS = "__no_db__" diff --git a/django_redshift_backend/base.py b/django_redshift_backend/base.py index b0f02a5..2f02b39 100644 --- a/django_redshift_backend/base.py +++ b/django_redshift_backend/base.py @@ -16,6 +16,7 @@ from django.conf import settings from django.core.exceptions import FieldDoesNotExist from django.db.models import Index +from django.db.models.expressions import Col from django.db.utils import NotSupportedError, ProgrammingError from ._vendor.django40.db.backends.base.introspection import FieldInfo, TableInfo @@ -58,6 +59,11 @@ class DatabaseFeatures(BasePGDatabaseFeatures): allows_group_by_select_index = True # since django-4.2 # since django-4.2. I don't know the Redshift supports comments or not. supports_comments = False + # django-redshift-backend does not support dj50 features due to dj40 codebase. + # https://docs.djangoproject.com/en/5.0/releases/5.0/ + supports_default_keyword_in_insert = False + supports_default_keyword_in_bulk_insert = False + supports_nulls_distinct_unique_constraints = False # If support atomic for ddl, we should implement non-atomic migration for on rename and change type(size) # refs django-redshift-backend #96 @@ -146,6 +152,20 @@ def on_conflict_suffix_sql( ): return "" + # copy from djang 5.0 postgresql/operations.py + def prepare_join_on_clause(self, lhs_table, lhs_field, rhs_table, rhs_field): + lhs_expr = Col(lhs_table, lhs_field) + rhs_expr = Col(rhs_table, rhs_field) + + # Cast is not impremented for redshift. + # Because the following code generate redundant SQL like: + # ... LEFT OUTER JOIN "tbl2" ON ("tbl1"."id" = CAST("tbl2"."parent_id" AS integer)) + + # if lhs_field.db_type(self.connection) != rhs_field.db_type(self.connection): + # rhs_expr = Cast(rhs_expr, lhs_field) + + return lhs_expr, rhs_expr + def _get_type_default(field): internal_type = field.get_internal_type() diff --git a/doc/index.rst b/doc/index.rst index 181d9e1..4323f91 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -44,7 +44,7 @@ Support versions This product is tested with: * Python-3.8, 3.9, 3.10, 3.11, 3.12 -* Django-3.2, 4.0, 4.2 +* Django-3.2, 4.0, 4.2, 5.0 License ======= diff --git a/pyproject.toml b/pyproject.toml index edef721..e63daca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ "Framework :: Django :: 3.2", "Framework :: Django :: 4.0", "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", @@ -35,7 +36,7 @@ classifiers = [ "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ - "django<5", + "django<5.1", "backports.zoneinfo;python_version<'3.9'", ] diff --git a/tests/test_migrations.py b/tests/test_migrations.py index c338fdf..c454f9c 100644 --- a/tests/test_migrations.py +++ b/tests/test_migrations.py @@ -289,6 +289,27 @@ def test_add_notnull_with_default(self): '''ALTER TABLE "test_pony" ADD COLUMN "name" varchar(10) DEFAULT '' NOT NULL;''', ], sqls) + @pytest.mark.skip('django-redshift-backend does not support in-database defaults') + @postgres_fixture() + def test_add_db_default(self): + from django.db.models.functions import Now + + new_state = self.set_up_test_model('test') + operations = [ + migrations.AddField( + model_name='Pony', + name='birthday', + field=models.DateTimeField(null=False, db_default=Now()), + ), + ] + + with self.collect_sql() as sqls: + self.apply_operations('test', new_state, operations) + + self.assertEqual([ + '''ALTER TABLE "test_pony" ADD COLUMN "birthday" timestamp with time zone DEFAULT now() NOT NULL;''', + ], sqls) + @postgres_fixture() def test_add_binary(self): from django_redshift_backend.base import DatabaseWrapper, _remove_length_from_type diff --git a/tox.ini b/tox.ini index 95be6e0..059842e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,9 @@ [tox] envlist = - py{38,39,310,311,312}-dj{32,40,42,main} + py{38,39,310}-dj32 + py{38,39,310,311,312}-dj40 + py{38,39,310,311,312}-dj42 + py{310,311,312}-dj50 lint check skipsdist = True @@ -18,6 +21,7 @@ DJANGO = 3.2: dj32 4.0: dj40 4.2: dj42 + 5.0: dj50 main: djmain [testenv] @@ -32,6 +36,7 @@ deps = dj32: Django>=3.2,<3.3 dj40: Django>=4.0,<4.1 dj42: Django>=4.2,<5.0 + dj50: Django>=5.0,<5.1 djmain: https://github.com/django/django/archive/main.tar.gz setenv = DJANGO_SETTINGS_MODULE = settings