Skip to content

Commit

Permalink
Add Django-4.2 support #116
Browse files Browse the repository at this point in the history
- inspectdb now suppress output 'id = AutoField(primary_key=True)'
- `TEST_WITH_REDSHIFT=... tox` testing with redshift database.
  • Loading branch information
shimizukawa committed Jul 15, 2024
1 parent 386d597 commit 6c2d53a
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 31 deletions.
5 changes: 4 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ Incompatible Changes:

Features:

* #116 Add Django-4.2 support.
* #83 Drop Django-2.2 support.
* #83 Drop Python-3.6 support.
* #127 Drop Python-3.7 support.
* #83 Drop Django-2.2 support.

Bug Fixes:

* #116 inspectdb suppress output 'id = AutoField(primary_key=True)'

3.0.0 (2022/02/27)
------------------

Expand Down
14 changes: 14 additions & 0 deletions django_redshift_backend/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,20 @@ class DatabaseCreation(BasePGDatabaseCreation):


class DatabaseIntrospection(BasePGDatabaseIntrospection):

# to avoid output 'id = meta.AutoField(primary_key=True)',
# return 'AutoField' for 'identity'.
def get_field_type(self, data_type, description):
field_type = super().get_field_type(data_type, description)
if description.default and "identity" in description.default:
if field_type == "IntegerField":
return "AutoField"
elif field_type == "BigIntegerField":
return "BigAutoField"
elif field_type == "SmallIntegerField":
return "SmallAutoField"
return field_type

def get_table_description(self, cursor, table_name):
"""
Return a description of the table with the DB-API cursor.description
Expand Down
6 changes: 6 additions & 0 deletions doc/dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ To test the database migration as well, start postgres and test it as follows::
$ docker-compose up -d
$ TEST_WITH_POSTGRES=1 tox

To test migrations with Redshift, do it as follows:

1. Create your redshift cruster on AWS
2. Get a redshift endpoint URI
3. run tox as: `TEST_WITH_REDSHIFT=redshift://user:password@<cluster>.<slug>.<region>.redshift.amazonaws.com:5439/<database>?DISABLE_SERVER_SIDE_CURSORS=True tox`

CI (Continuous Integration)
----------------------------

Expand Down
3 changes: 1 addition & 2 deletions examples/dj-sql-explorer/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
Django<4
-e ../..[psycopg2-binary]
django-environ==0.8.1
django-sql-explorer
-e ../..
3 changes: 1 addition & 2 deletions examples/proj1/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
Django<4
-e ../..[psycopg2-binary]
django-environ==0.8.1
-e ../..
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ classifiers = [
"Framework :: Django",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.2",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python",
Expand All @@ -32,7 +33,7 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = [
"django",
"django<5",
"backports.zoneinfo;python_version<'3.9'",
]

Expand Down
53 changes: 53 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,56 @@

from django.apps import apps # noqa E402
apps.populate(['testapp'])


import contextlib
from unittest import mock

import pytest

from django_redshift_backend.base import BasePGDatabaseWrapper

TEST_WITH_POSTGRES = os.environ.get('TEST_WITH_POSTGRES')
TEST_WITH_REDSHIFT = os.environ.get('TEST_WITH_REDSHIFT')

skipif_no_database = pytest.mark.skipif(
not TEST_WITH_POSTGRES and not TEST_WITH_REDSHIFT,
reason="no TEST_WITH_POSTGRES/TEST_WITH_REDSHIFT are found",
)
run_only_postgres = pytest.mark.skipif(
not TEST_WITH_POSTGRES,
reason="Test only for postgres",
)
run_only_redshift = pytest.mark.skipif(
not TEST_WITH_REDSHIFT,
reason="Test only for redshift",
)

@contextlib.contextmanager
def postgres_fixture():
"""A context manager that patches the database backend to use PostgreSQL
for local testing.
The purpose of the postgres_fixture context manager is to conditionally
patch the database backend to use PostgreSQL for testing, but only if the
TEST_WITH_POSTGRES variable is set to True.
The reason for not using pytest.fixture in the current setup is due to the
use of classes that inherit from TestCase. pytest fixtures do not directly
integrate with Django's TestCase based tests.
"""
if TEST_WITH_POSTGRES:
with (
mock.patch(
'django_redshift_backend.base.DatabaseWrapper.data_types',
BasePGDatabaseWrapper.data_types,
),
mock.patch(
'django_redshift_backend.base.DatabaseSchemaEditor._get_create_options',
lambda self, model: '',
),
):
yield

else:
yield
17 changes: 9 additions & 8 deletions tests/settings.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# -*- coding: utf-8 -*-
import os
import environ

if uri := os.environ.get("TEST_WITH_REDSHIFT"):
# use URI if it has least one charactor.
os.environ["DATABASE_URL"] = uri
else:
os.environ["DATABASE_URL"] = "redshift://user:password@localhost:5439/testing"
env = environ.Env()

DATABASES = {
'default': {
'ENGINE': 'django_redshift_backend',
'NAME': 'testing',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '5439',
}
'default': env.db()
}

SECRET_KEY = '<key>'
11 changes: 4 additions & 7 deletions tests/test_inspectdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

from django.db import connections
from django.core.management import call_command
import pytest

from django_redshift_backend.base import BasePGDatabaseWrapper
from test_base import OperationTestBase

from conftest import skipif_no_database, postgres_fixture

def norm_sql(sql):
return ' '.join(sql.split()).replace('( ', '(').replace(' )', ')').replace(' ;', ';')
Expand Down Expand Up @@ -188,8 +187,7 @@ def test_get_get_constraints_does_not_use_unsupported_functions(self):
self.assertEqual(self.expected_indexes_query, executed_sql)


@pytest.mark.skipif(not os.environ.get('TEST_WITH_POSTGRES'),
reason='to run, TEST_WITH_POSTGRES=1 tox')
@skipif_no_database
class InspectDbTests(OperationTestBase):
available_apps = []
databases = {'default'}
Expand All @@ -210,11 +208,10 @@ class Meta:
def tearDown(self):
self.cleanup_test_tables()

@mock.patch('django_redshift_backend.base.DatabaseWrapper.data_types', BasePGDatabaseWrapper.data_types)
@mock.patch('django_redshift_backend.base.DatabaseSchemaEditor._get_create_options', lambda self, model: '')
@postgres_fixture()
def test_inspectdb(self):
self.set_up_test_model('test')
out = StringIO()
call_command('inspectdb', stdout=out)
call_command('inspectdb', 'test_pony', stdout=out)
print(out.getvalue())
self.assertIn(self.expected_pony_model, out.getvalue())
19 changes: 13 additions & 6 deletions tests/test_migrations.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import os
import contextlib
from unittest import mock

from django.db import migrations, models
from django.db.migrations.state import ProjectState
import pytest

from django_redshift_backend.base import BasePGDatabaseWrapper
from test_base import OperationTestBase
from conftest import skipif_no_database, postgres_fixture


@pytest.mark.skipif(not os.environ.get('TEST_WITH_POSTGRES'),
reason='to run, TEST_WITH_POSTGRES=1 tox')
@mock.patch('django_redshift_backend.base.DatabaseWrapper.data_types', BasePGDatabaseWrapper.data_types)
@mock.patch('django_redshift_backend.base.DatabaseSchemaEditor._get_create_options', lambda self, model: '')
@skipif_no_database
class MigrationTests(OperationTestBase):
available_apps = ["testapp"]
databases = {'default'}
Expand All @@ -40,6 +36,7 @@ def execute(self, sql, params=()):

print('\n'.join(collected_sql))

@postgres_fixture()
def test_alter_size(self):
new_state = self.set_up_test_model('test')
operations = [
Expand Down Expand Up @@ -69,6 +66,7 @@ def test_alter_size(self):
'''ALTER TABLE "test_pony" ALTER COLUMN "name" TYPE varchar(10);''',
], sqls)

@postgres_fixture()
def test_alter_size_for_unique(self):
new_state = self.set_up_test_model('test')
operations = [
Expand All @@ -94,6 +92,7 @@ def test_alter_size_for_unique(self):
'''ALTER TABLE "test_pony" ADD CONSTRAINT "test_pony_name_key" UNIQUE ("name");'''
], sqls)

@postgres_fixture()
def test_alter_size_for_pk(self):
setup_operations = [migrations.CreateModel(
'Pony',
Expand All @@ -120,6 +119,7 @@ def test_alter_size_for_pk(self):
'''ALTER TABLE "test_pony" ADD CONSTRAINT "test_pony_name_2c070d2a_pk" PRIMARY KEY ("name");''',
], sqls)

@postgres_fixture()
def test_alter_size_for_fk(self):
setup_operations = [
migrations.CreateModel(
Expand Down Expand Up @@ -159,6 +159,7 @@ def test_alter_size_for_fk(self):
''' FOREIGN KEY ("pony_id") REFERENCES "test_pony" ("id");'''),
], sqls)

@postgres_fixture()
def test_add_notnull_without_default_raise_exception(self):
from django.db.utils import ProgrammingError
new_state = self.set_up_test_model('test')
Expand All @@ -173,6 +174,7 @@ def test_add_notnull_without_default_raise_exception(self):
with self.collect_sql():
self.apply_operations('test', new_state, operations)

@postgres_fixture()
def test_add_notnull_without_default_on_backwards(self):
project_state = self.set_up_test_model('test')
operations = [
Expand Down Expand Up @@ -203,6 +205,7 @@ def test_add_notnull_without_default_on_backwards(self):
'''ALTER TABLE test_pony RENAME COLUMN "weight_tmp" TO "weight";''',
], sqls)

@postgres_fixture()
def test_add_notnull_with_default(self):
new_state = self.set_up_test_model('test')
operations = [
Expand All @@ -220,6 +223,7 @@ def test_add_notnull_with_default(self):
'''ALTER TABLE "test_pony" ADD COLUMN "name" varchar(10) DEFAULT '' NOT NULL;''',
], sqls)

@postgres_fixture()
def test_alter_type(self):
new_state = self.set_up_test_model('test')
operations = [
Expand All @@ -240,6 +244,7 @@ def test_alter_type(self):
'''ALTER TABLE test_pony RENAME COLUMN "weight_tmp" TO "weight";''',
], sqls)

@postgres_fixture()
def test_alter_notnull_with_default(self):
new_state = self.set_up_test_model('test')
operations = [
Expand Down Expand Up @@ -270,6 +275,7 @@ def test_alter_notnull_with_default(self):
# ## ref: https://github.com/django/django/blob/3.2.12/django/db/backends/base/schema.py#L524
# ## django-redshift-backend also does not support in-database defaults
@pytest.mark.skip('django-redshift-backend does not support in-database defaults')
@postgres_fixture()
def test_change_default(self):
# https://github.com/jazzband/django-redshift-backend/issues/63
new_state = self.set_up_test_model('test')
Expand Down Expand Up @@ -297,6 +303,7 @@ def test_change_default(self):
'''ALTER TABLE test_pony RENAME COLUMN "name_tmp" TO "name";''',
], sqls)

@postgres_fixture()
def test_alter_notnull_to_nullable(self):
# https://github.com/jazzband/django-redshift-backend/issues/63
new_state = self.set_up_test_model('test')
Expand Down
7 changes: 3 additions & 4 deletions tests/test_redshift_backend.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-

import os
import unittest

from django.db import connections
from django.db.utils import NotSupportedError
from django.core.management.color import no_style
import pytest

from conftest import skipif_no_database


def norm_sql(sql):
Expand Down Expand Up @@ -153,8 +153,7 @@ def test_create_table_meta_keys(self):
from testapp.models import TestModelWithMetaKeys
self.check_model_creation(TestModelWithMetaKeys, expected_ddl_meta_keys)

@pytest.mark.skipif(not os.environ.get('TEST_WITH_POSTGRES'),
reason='to run, TEST_WITH_POSTGRES=1 tox')
@skipif_no_database
def test_sqlmigrate(self):
from django.db import connection
from django.db.migrations.loader import MigrationLoader
Expand Down
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ deps =
pytest
pytest-cov
mock>=2.0
django-environ
py38: backports.zoneinfo
dj32: Django>=3.2,<3.3
dj40: Django>=4.0,<4.1
Expand All @@ -34,6 +35,7 @@ setenv =
DJANGO_SETTINGS_MODULE = settings
PYTHONPATH = {toxinidir}
TEST_WITH_POSTGRES = {env:TEST_WITH_POSTGRES:}
TEST_WITH_REDSHIFT = {env:TEST_WITH_REDSHIFT:}
pip_pre = True
commands =
pytest -v --cov django_redshift_backend --cov-append --cov-report term-missing --cov-report=xml {posargs}
Expand Down

0 comments on commit 6c2d53a

Please sign in to comment.