From d73730bd13a83d26862582e909def859ad1adc29 Mon Sep 17 00:00:00 2001 From: Serkan Hosca Date: Wed, 7 Apr 2021 08:35:59 -0400 Subject: [PATCH] Django 3.2 support --- django_sorcery/compat.py | 12 ----------- django_sorcery/db/fields.py | 8 ++------ django_sorcery/db/meta/column.py | 11 +++++----- django_sorcery/db/models.py | 9 ++------- django_sorcery/db/relations.py | 13 +++++------- django_sorcery/db/sqlalchemy.py | 20 ++++++++----------- django_sorcery/db/url.py | 3 +-- django_sorcery/db/utils.py | 3 ++- django_sorcery/exceptions.py | 12 +++++------ django_sorcery/fields.py | 3 +-- django_sorcery/forms.py | 2 +- django_sorcery/formsets/base.py | 3 +-- django_sorcery/routers.py | 17 +++++++++------- django_sorcery/shortcuts.py | 3 +-- django_sorcery/utils.py | 7 ------- django_sorcery/views/base.py | 2 +- setup.py | 20 +++++-------------- tests/db/meta/test_model.py | 4 ++-- tests/db/test_sqlalchemy.py | 3 ++- .../commands/test_sorcery_current.py | 16 +++++++-------- .../commands/test_sorcery_downgrade.py | 10 +++++----- .../management/commands/test_sorcery_heads.py | 12 +++++------ .../commands/test_sorcery_history.py | 10 +++++----- .../commands/test_sorcery_revision.py | 4 ++-- .../management/commands/test_sorcery_stamp.py | 4 ++-- .../commands/test_sorcery_upgrade.py | 15 ++++++-------- tests/minimalapp/apps.py | 2 +- tests/otherapp/apps.py | 2 +- tests/otherapp/models.py | 2 +- .../owner_confirm_delete.html | 0 .../owner_detail.html | 0 .../owner_form.html | 0 .../owner_list.html | 0 .../vehicle_form.html | 0 tests/test_compat.py | 9 --------- tests/test_utils.py | 5 ----- tests/testapp/apps.py | 2 +- tox.ini | 12 +++-------- 38 files changed, 96 insertions(+), 164 deletions(-) delete mode 100644 django_sorcery/compat.py rename tests/templates/{tests.testapp => tests_testapp}/owner_confirm_delete.html (100%) rename tests/templates/{tests.testapp => tests_testapp}/owner_detail.html (100%) rename tests/templates/{tests.testapp => tests_testapp}/owner_form.html (100%) rename tests/templates/{tests.testapp => tests_testapp}/owner_list.html (100%) rename tests/templates/{tests.testapp => tests_testapp}/vehicle_form.html (100%) delete mode 100644 tests/test_compat.py diff --git a/django_sorcery/compat.py b/django_sorcery/compat.py deleted file mode 100644 index 57e8be5..0000000 --- a/django_sorcery/compat.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Python compat utils.""" -import contextlib - - -@contextlib.contextmanager -def suppress(*exceptions): - """Suppresses given exceptions, a backport from py3 contextlib.suppress.""" - try: - yield - - except exceptions: - pass diff --git a/django_sorcery/db/fields.py b/django_sorcery/db/fields.py index d28e88f..2845c32 100644 --- a/django_sorcery/db/fields.py +++ b/django_sorcery/db/fields.py @@ -1,4 +1,5 @@ """Django-esque declarative fields for sqlalchemy.""" +from contextlib import suppress import sqlalchemy as sa from django import forms as djangoforms @@ -7,7 +8,6 @@ from django.forms import fields as djangofields from django.utils.module_loading import import_string -from ..utils import suppress from .url import DIALECT_MAP_TO_DJANGO @@ -103,11 +103,7 @@ def get_column_kwargs(self, kwargs): "unique", "_proxies", ] - column_kwargs = {} - for k in column_args: - if k in kwargs: - column_kwargs[k] = kwargs.pop(k) - + column_kwargs = {k: kwargs.pop(k) for k in column_args if k in kwargs} column_kwargs["primary_key"] = kwargs.pop("primary_key", False) column_kwargs["nullable"] = kwargs.pop("nullable", not column_kwargs["primary_key"]) return column_kwargs diff --git a/django_sorcery/db/meta/column.py b/django_sorcery/db/meta/column.py index 40c43c6..6147493 100644 --- a/django_sorcery/db/meta/column.py +++ b/django_sorcery/db/meta/column.py @@ -2,6 +2,7 @@ import datetime import decimal import enum +from contextlib import suppress import sqlalchemy as sa from dateutil.parser import parse @@ -15,7 +16,7 @@ from django.utils.text import capfirst from ... import fields as sorceryfields -from ...utils import sanitize_separators, suppress +from ...utils import sanitize_separators def _make_naive(value): @@ -81,8 +82,7 @@ def __new__(cls, *args, **kwargs): break _cls = override_cls or cls - instance = super().__new__(_cls) - return instance + return super().__new__(_cls) def __init__(self, column, prop=None, parent=None, name=None): self.property = prop @@ -116,9 +116,8 @@ def __init__(self, column, prop=None, parent=None, name=None): self.label = self.column.info.get("label") or (capfirst(" ".join(self.name.split("_"))) if self.name else None) self.field_kwargs = {"required": self.required, "validators": self.validators, "help_text": self.help_text} - if self.default: - if not callable(self.default): - self.field_kwargs["initial"] = self.default + if self.default and not callable(self.default): + self.field_kwargs["initial"] = self.default if self.label: self.field_kwargs["label"] = self.label diff --git a/django_sorcery/db/models.py b/django_sorcery/db/models.py index 26cf6b8..0f72e57 100644 --- a/django_sorcery/db/models.py +++ b/django_sorcery/db/models.py @@ -128,11 +128,7 @@ def _deserialize(model, data, identity_map): info = meta.model_info(model) - kwargs = {} - for prop in info.primary_keys: - if prop in data: - kwargs[prop] = data.get(prop) - + kwargs = {prop: data.get(prop) for prop in info.primary_keys if prop in data} pk = info.identity_key_from_dict(kwargs) if pk is not None and pk in identity_map: return identity_map[pk] @@ -228,8 +224,7 @@ def clone(instance, *rels, **kwargs): sub_rels = [(r, kw) for r, kw in relations.items() if r is not attr] kwargs[relation.key] = clone(sub_instance, *sub_rels, **relations[attr]) - cloned = mapper.class_(**kwargs) - return cloned + return mapper.class_(**kwargs) class BaseMeta(sqlalchemy.ext.declarative.DeclarativeMeta): diff --git a/django_sorcery/db/relations.py b/django_sorcery/db/relations.py index 912f900..efea629 100644 --- a/django_sorcery/db/relations.py +++ b/django_sorcery/db/relations.py @@ -1,10 +1,11 @@ """sqlalchemy relationship related things.""" +from contextlib import suppress from itertools import chain import sqlalchemy as sa from sqlalchemy.ext.declarative import declared_attr -from ..utils import setdefaultattr, suppress +from ..utils import setdefaultattr from .signals import declare_first @@ -161,11 +162,7 @@ def m2m(cls): return m2m def _get_kwargs_for_relation(self, kwargs, prefix="fk_"): - opts = {} - for key in list(kwargs.keys()): - if key.startswith(prefix): - opts[key] = kwargs.pop(key) - return opts + return {key: kwargs.pop(key) for key in list(kwargs.keys()) if key.startswith(prefix)} def _add_foreign_keys(cls, parent_cls, relation): @@ -206,9 +203,9 @@ def _add_foreign_keys(cls, parent_cls, relation): if cols_created: # pk and fk ordering must match for foreign key constraint pks, fks = [], [] - for pk in cols: + for pk, value in cols.items(): pks.append(pk) - fks.append(cols[pk]) + fks.append(value) constraint = sa.ForeignKeyConstraint(fks, pks, **fk_kwargs) cls.__table__.append_constraint(constraint) diff --git a/django_sorcery/db/sqlalchemy.py b/django_sorcery/db/sqlalchemy.py index ddd58a7..86fa179 100644 --- a/django_sorcery/db/sqlalchemy.py +++ b/django_sorcery/db/sqlalchemy.py @@ -164,20 +164,16 @@ def session(self, **kwargs): If there's already a session in current scope, will raise InvalidRequestError """ - if kwargs: - if self.registry.has(): - raise sa.exc.InvalidRequestError( - "Scoped session is already present; " "no new arguments may be specified." - ) - - else: - session = self.session_factory(**kwargs) - self.registry.set(session) - return session - - else: + if not kwargs: return self.registry() + if self.registry.has(): + raise sa.exc.InvalidRequestError("Scoped session is already present; " "no new arguments may be specified.") + + session = self.session_factory(**kwargs) + self.registry.set(session) + return session + def Table(self, name, *args, **kwargs): """Returns a sqlalchemy table that is automatically added to metadata.""" diff --git a/django_sorcery/db/url.py b/django_sorcery/db/url.py index adcd8ba..2995c65 100644 --- a/django_sorcery/db/url.py +++ b/django_sorcery/db/url.py @@ -1,4 +1,5 @@ import os +from contextlib import suppress from importlib import import_module import sqlalchemy as sa @@ -6,8 +7,6 @@ from django.utils.encoding import force_text from django.utils.module_loading import import_string -from ..utils import suppress - DIALECT_MAP = { "django.db.backends.sqlite3": "sqlite", diff --git a/django_sorcery/db/utils.py b/django_sorcery/db/utils.py index 1a4a5a3..8afb5d2 100644 --- a/django_sorcery/db/utils.py +++ b/django_sorcery/db/utils.py @@ -1,8 +1,9 @@ +from contextlib import suppress + import sqlalchemy as sa from django.db import DEFAULT_DB_ALIAS from django.utils.module_loading import import_string -from ..utils import suppress from .sqlalchemy import SQLAlchemy from .transaction import TransactionContext from .url import get_settings, make_url diff --git a/django_sorcery/exceptions.py b/django_sorcery/exceptions.py index 6bb0e9f..3988058 100644 --- a/django_sorcery/exceptions.py +++ b/django_sorcery/exceptions.py @@ -50,14 +50,14 @@ def __init__(self, message, code=None, params=None): super().__init__(message, code, params) def update_error_dict(self, error_dict): - if hasattr(self, "error_dict"): - for field, errors in self.error_dict.items(): - holder = error_dict.setdefault(field, errors.__class__()) - (getattr(holder, "update", None) or holder.extend)(errors) - return error_dict - else: + if not hasattr(self, "error_dict"): return super().update_error_dict(error_dict) + for field, errors in self.error_dict.items(): + holder = error_dict.setdefault(field, errors.__class__()) + (getattr(holder, "update", None) or holder.extend)(errors) + return error_dict + def __iter__(self): if hasattr(self, "code"): yield from super().__iter__() diff --git a/django_sorcery/fields.py b/django_sorcery/fields.py index 8163f26..0e9fad4 100644 --- a/django_sorcery/fields.py +++ b/django_sorcery/fields.py @@ -1,12 +1,11 @@ """Field mapping from SQLAlchemy type's to form fields.""" import json +from contextlib import suppress from django.core.exceptions import ValidationError from django.forms import fields as djangofields from django.utils.translation import gettext_lazy -from .utils import suppress - class EnumField(djangofields.ChoiceField): """Form field for using an Enum as choices.""" diff --git a/django_sorcery/forms.py b/django_sorcery/forms.py index 88becca..e73f43b 100644 --- a/django_sorcery/forms.py +++ b/django_sorcery/forms.py @@ -1,5 +1,6 @@ """Helper functions for creating Form classes from SQLAlchemy models.""" from collections import OrderedDict +from contextlib import suppress from itertools import chain from django.core.exceptions import ( @@ -19,7 +20,6 @@ from django.forms.utils import ErrorList from .db import meta -from .utils import suppress def _get_default_kwargs( diff --git a/django_sorcery/formsets/base.py b/django_sorcery/formsets/base.py index 8668936..007cff6 100644 --- a/django_sorcery/formsets/base.py +++ b/django_sorcery/formsets/base.py @@ -68,8 +68,7 @@ def _construct_form(self, i, **kwargs): except IndexError: pass kwargs["session"] = self.session - form = super()._construct_form(i, **kwargs) - return form + return super()._construct_form(i, **kwargs) def add_fields(self, form, index): info = meta.model_info(self.model) diff --git a/django_sorcery/routers.py b/django_sorcery/routers.py index c617919..88ea629 100644 --- a/django_sorcery/routers.py +++ b/django_sorcery/routers.py @@ -33,8 +33,8 @@ def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs): def decorator(func): func.bind_to_methods = methods func.detail = detail - func.url_path = url_path if url_path else func.__name__ - func.url_name = url_name if url_name else func.__name__.replace("_", "-") + func.url_path = url_path or func.__name__ + func.url_name = url_name or func.__name__.replace("_", "-") func.kwargs = kwargs return func @@ -183,7 +183,7 @@ def get_routes(self, viewset): for route in self.routes: if isinstance(route, DynamicRoute) and route.detail: routes += [self._get_dynamic_route(route, action) for action in detail_actions] - elif isinstance(route, DynamicRoute) and not route.detail: + elif isinstance(route, DynamicRoute): routes += [self._get_dynamic_route(route, action) for action in list_actions] else: routes.append(route) @@ -234,11 +234,14 @@ def get_lookup_regex(self, viewset, lookup_prefix=""): if model: info = meta.model_info(model) - regexes = [] - for key, _ in info.primary_keys.items(): - regexes.append( - base_regex.format(lookup_prefix=lookup_prefix, lookup_url_kwarg=key, lookup_value="[^/.]+") + regexes = [ + base_regex.format( + lookup_prefix=lookup_prefix, + lookup_url_kwarg=key, + lookup_value="[^/.]+", ) + for key, _ in info.primary_keys.items() + ] return "/".join(regexes) diff --git a/django_sorcery/shortcuts.py b/django_sorcery/shortcuts.py index 4877190..65c1495 100644 --- a/django_sorcery/shortcuts.py +++ b/django_sorcery/shortcuts.py @@ -1,11 +1,10 @@ """Some Django like shortcuts that support sqlalchemy models.""" +from contextlib import suppress from django.core.exceptions import ImproperlyConfigured from django.http import Http404 from sqlalchemy.exc import InvalidRequestError -from .utils import suppress - def _get_query(klass): diff --git a/django_sorcery/utils.py b/django_sorcery/utils.py index d809cb7..dd8f6fb 100644 --- a/django_sorcery/utils.py +++ b/django_sorcery/utils.py @@ -1,17 +1,10 @@ """Some common utilities.""" -import contextlib import inspect import unicodedata from django.conf import settings -try: - suppress = contextlib.suppress -except AttributeError: # pragma: nocover - from .compat import suppress # noqa pragma: nocover - - def sanitize_separators(value): """Sanitize a value according to the current decimal and thousand separator setting. diff --git a/django_sorcery/views/base.py b/django_sorcery/views/base.py index 670cc5d..87b1246 100644 --- a/django_sorcery/views/base.py +++ b/django_sorcery/views/base.py @@ -1,4 +1,5 @@ """Base model view things with sqlalchemy.""" +from contextlib import suppress from django.apps import apps from django.core.exceptions import ImproperlyConfigured @@ -10,7 +11,6 @@ from sqlalchemy.exc import InvalidRequestError from ..db import meta -from ..utils import suppress class SQLAlchemyMixin(ContextMixin): diff --git a/setup.py b/setup.py index f4d0faf..073b9c5 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,6 @@ #!/usr/bin/env python # fmt:off import os -import shutil -import sys from setuptools import find_packages, setup @@ -19,19 +17,6 @@ def read(fname): return open(os.path.join(os.path.dirname(__file__), fname), "rb").read().decode("utf-8") -if sys.argv[-1] == "publish": - twine = shutil.which("twine") - if twine is None: - print("twine not installed.\nUse `pip install twine`.\nExiting.") - sys.exit() - os.system("python setup.py sdist bdist_wheel") - os.system("twine upload dist/*") - print("You probably want to also tag the version now:") - print(" git tag -a {} -m {}".format(about["__version__"], about["__version__"])) - print(" git push --tags") - os.system("make clean") - sys.exit() - setup( author=about["__author__"], author_email=about["__author_email__"], @@ -53,6 +38,9 @@ def read(fname): "Framework :: Django :: 2.0", "Framework :: Django :: 2.1", "Framework :: Django :: 2.2", + "Framework :: Django :: 3.0", + "Framework :: Django :: 3.1", + "Framework :: Django :: 3.2", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", @@ -62,6 +50,8 @@ def read(fname): "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Internet :: WWW/HTTP :: WSGI", diff --git a/tests/db/meta/test_model.py b/tests/db/meta/test_model.py index 63aaf97..e527274 100644 --- a/tests/db/meta/test_model.py +++ b/tests/db/meta/test_model.py @@ -81,8 +81,8 @@ def test_model_meta(self): self.assertEqual(info.other_location, info.composites["other_location"]) self.assertNotEqual(info.location, info.other_location) - self.assertEqual(info.label, "tests.testapp.Business") - self.assertEqual(info.label_lower, "tests.testapp.business") + self.assertEqual(info.label, "tests_testapp.Business") + self.assertEqual(info.label_lower, "tests_testapp.business") info = meta.model_info(Vehicle) self.assertEqual(info.private_fields, ()) diff --git a/tests/db/test_sqlalchemy.py b/tests/db/test_sqlalchemy.py index e036998..df3414a 100644 --- a/tests/db/test_sqlalchemy.py +++ b/tests/db/test_sqlalchemy.py @@ -1,7 +1,8 @@ +from contextlib import suppress + import sqlalchemy as sa from django.conf import settings from django_sorcery.db.query import Operation -from django_sorcery.utils import suppress from ..base import TestCase from ..testapp.models import ModelOne, Owner, db diff --git a/tests/management/commands/test_sorcery_current.py b/tests/management/commands/test_sorcery_current.py index b5cb8de..cc5b6f1 100644 --- a/tests/management/commands/test_sorcery_current.py +++ b/tests/management/commands/test_sorcery_current.py @@ -71,19 +71,19 @@ def setUp(self): self.write_migration(M1, "{}_.py".format("000000000000")) self.write_migration(M2, "{}_.py".format("000000000001")) - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) - Upgrade().run_from_argv(["./manage.py sorcery", "upgrade", "tests.testapp", "--no-color"]) + Upgrade().run_from_argv(["./manage.py sorcery", "upgrade", "tests_testapp", "--no-color"]) def tearDown(self): super().tearDown() - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) for rev in ["000000000000", "000000000001"]: self.delete_migration("{}_.py".format(rev)) - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) def test(self): out = six.StringIO() @@ -94,9 +94,9 @@ def test(self): self.assertEqual( out.readlines(), [ - "Revision for tests.testapp on database test\n", + "Revision for tests_testapp on database test\n", "000000000001 (head)\n", - "Revision for tests.otherapp on database test\n", + "Revision for tests_otherapp on database test\n", ], ) @@ -109,7 +109,7 @@ def test_verbose(self): self.assertEqual( out.readlines(), [ - "Revision for tests.testapp on database test\n", + "Revision for tests_testapp on database test\n", f"Current revision(s) for postgresql://postgres:***@{settings.DB_URL.host}/test\n", "Rev: 000000000001 (head)\n", "Parent: 000000000000\n", @@ -120,7 +120,7 @@ def test_verbose(self): " Revision ID: 000000000001\n", " Revises: 000000000000\n", " Create Date: 2018-07-24 02:02:55.504526\n", - "Revision for tests.otherapp on database test\n", + "Revision for tests_otherapp on database test\n", f"Current revision(s) for postgresql://postgres:***@{settings.DB_URL.host}/test\n", ], ) diff --git a/tests/management/commands/test_sorcery_downgrade.py b/tests/management/commands/test_sorcery_downgrade.py index 6cb7cf0..270dfd1 100644 --- a/tests/management/commands/test_sorcery_downgrade.py +++ b/tests/management/commands/test_sorcery_downgrade.py @@ -66,16 +66,16 @@ def setUp(self): self.write_migration(M1, "{}_.py".format("000000000000")) self.write_migration(M2, "{}_.py".format("000000000001")) - Upgrade().run_from_argv(["./manage.py sorcery", "upgrade", "tests.testapp", "--no-color"]) + Upgrade().run_from_argv(["./manage.py sorcery", "upgrade", "tests_testapp", "--no-color"]) def tearDown(self): super().tearDown() - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) for rev in ["000000000000", "000000000001"]: self.delete_migration("{}_.py".format(rev)) - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) def test(self): out = six.StringIO() @@ -87,7 +87,7 @@ def test(self): Upgrade().run_from_argv(["./manage.py sorcery", "upgrade", "--no-color"]) - cmd.run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "-r", "000000000000", "--no-color"]) + cmd.run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "-r", "000000000000", "--no-color"]) revs = db.execute("select * from public.alembic_version_tests_testapp").fetchall() self.assertEqual(revs, [("000000000000",)]) @@ -128,5 +128,5 @@ def test_with_range(self): with self.assertRaises(SystemExit): cmd.run_from_argv( - ["./manage.py sorcery", "downgrade", "tests.testapp", "-r", ":000000000000", "--no-color"] + ["./manage.py sorcery", "downgrade", "tests_testapp", "-r", ":000000000000", "--no-color"] ) diff --git a/tests/management/commands/test_sorcery_heads.py b/tests/management/commands/test_sorcery_heads.py index 63c99e8..2ce4b5b 100644 --- a/tests/management/commands/test_sorcery_heads.py +++ b/tests/management/commands/test_sorcery_heads.py @@ -75,9 +75,9 @@ def test(self): self.assertEqual( out.readlines(), [ - "Heads for tests.testapp on database test\n", - "000000000001 (head) \n", - "Heads for tests.otherapp on database test\n", + "Heads for tests_testapp on database test\n", + "000000000001 (head) \n", + "Heads for tests_otherapp on database test\n", ], ) @@ -90,8 +90,8 @@ def test_verbose(self): self.assertEqual( out.readlines(), [ - "Heads for tests.testapp on database test\n", - "[tests.testapp]\n", + "Heads for tests_testapp on database test\n", + "[tests_testapp]\n", "Rev: 000000000001 (head)\n", "Parent: 000000000000\n", "Path: {}/000000000001_.py\n".format(MIGRATION_DIR), @@ -101,6 +101,6 @@ def test_verbose(self): " Revision ID: 000000000001\n", " Revises: 000000000000\n", " Create Date: 2018-07-24 02:02:55.504526\n", - "Heads for tests.otherapp on database test\n", + "Heads for tests_otherapp on database test\n", ], ) diff --git a/tests/management/commands/test_sorcery_history.py b/tests/management/commands/test_sorcery_history.py index 14b03a3..c8c8138 100644 --- a/tests/management/commands/test_sorcery_history.py +++ b/tests/management/commands/test_sorcery_history.py @@ -51,9 +51,9 @@ def test(self): self.assertEqual( out.readlines(), [ - "Migrations for tests.testapp on database test\n", + "Migrations for tests_testapp on database test\n", " -> 000000000000 (zero) (head), zero\n", - "Migrations for tests.otherapp on database test\n", + "Migrations for tests_otherapp on database test\n", ], ) @@ -70,12 +70,12 @@ def test_with_range(self): cmd = Command(stdout=out) - cmd.run_from_argv(["./manage.py sorcery", "history", "tests.testapp", "-r", "base:head", "--no-color"]) + cmd.run_from_argv(["./manage.py sorcery", "history", "tests_testapp", "-r", "base:head", "--no-color"]) out.seek(0) self.assertEqual( out.readlines(), - ["Migrations for tests.testapp on database test\n", " -> 000000000000 (zero) (head), zero\n"], + ["Migrations for tests_testapp on database test\n", " -> 000000000000 (zero) (head), zero\n"], ) def test_bad_range(self): @@ -85,7 +85,7 @@ def test_bad_range(self): cmd = Command(stdout=out, stderr=err) with self.assertRaises(SystemExit): - cmd.run_from_argv(["./manage.py sorcery", "history", "tests.testapp", "-r", "base-head", "--no-color"]) + cmd.run_from_argv(["./manage.py sorcery", "history", "tests_testapp", "-r", "base-head", "--no-color"]) err.seek(0) self.assertEqual(err.readlines(), ["CommandError: History range requires [start]:[end], [start]:, or :[end]\n"]) diff --git a/tests/management/commands/test_sorcery_revision.py b/tests/management/commands/test_sorcery_revision.py index 5056019..75fbfe1 100644 --- a/tests/management/commands/test_sorcery_revision.py +++ b/tests/management/commands/test_sorcery_revision.py @@ -49,7 +49,7 @@ def test_with_name(self): cmd = Command(stdout=out) cmd.run_from_argv( - ["./manage.py sorcery", "makemigrations", "tests.testapp", "-r", rev, "-m", "zero", "--no-color"] + ["./manage.py sorcery", "makemigrations", "tests_testapp", "-r", rev, "-m", "zero", "--no-color"] ) self.assertTrue(os.path.isfile(os.path.join(MIGRATION_DIR, "{}_zero.py".format(rev)))) @@ -65,7 +65,7 @@ def test_longer_version_table_identifier(self): with self.assertRaises(SystemExit): cmd.run_from_argv( - ["./manage.py sorcery", "makemigrations", "tests.testapp", "-r", rev, "-m", "zero", "--no-color"] + ["./manage.py sorcery", "makemigrations", "tests_testapp", "-r", rev, "-m", "zero", "--no-color"] ) db.engine.dialect.max_identifier_length = original_length diff --git a/tests/management/commands/test_sorcery_stamp.py b/tests/management/commands/test_sorcery_stamp.py index abfbb93..d1c9033 100644 --- a/tests/management/commands/test_sorcery_stamp.py +++ b/tests/management/commands/test_sorcery_stamp.py @@ -52,7 +52,7 @@ def tearDown(self): def test(self): out = six.StringIO() cmd = Command(stdout=out) - cmd.run_from_argv(["./manage.py sorcery", "stamp", "tests.testapp", "--no-color"]) + cmd.run_from_argv(["./manage.py sorcery", "stamp", "tests_testapp", "--no-color"]) revs = db.execute("select * from alembic_version_tests_testapp").fetchall() self.assertEqual(revs, [("000000000000",)]) @@ -62,4 +62,4 @@ def test_bad_rev(self): cmd = Command(stdout=out) with self.assertRaises(SystemExit): - cmd.run_from_argv(["./manage.py sorcery", "stamp", "tests.testapp", "-r", ":000000000000", "--no-color"]) + cmd.run_from_argv(["./manage.py sorcery", "stamp", "tests_testapp", "-r", ":000000000000", "--no-color"]) diff --git a/tests/management/commands/test_sorcery_upgrade.py b/tests/management/commands/test_sorcery_upgrade.py index 7d2dea0..8bc2af5 100644 --- a/tests/management/commands/test_sorcery_upgrade.py +++ b/tests/management/commands/test_sorcery_upgrade.py @@ -41,14 +41,14 @@ def setUp(self): for rev in ["000000000000", "000000000001"]: self.write_migration(MIGRATION.format(rev=rev), "{}_zero.py".format(rev)) self.write_migration(MIGRATION.format(rev=rev), "{}_zero.py".format(rev)) - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) def tearDown(self): super().tearDown() - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) for rev in ["000000000000", "000000000001"]: self.delete_migration("{}_zero.py".format(rev)) - Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests.testapp", "--no-color"]) + Downgrade().run_from_argv(["./manage.py sorcery", "downgrade", "tests_testapp", "--no-color"]) def test(self): out = six.StringIO() @@ -74,10 +74,7 @@ def test_sql(self): "INSERT INTO public.alembic_version_tests_testapp (version_num) VALUES ('000000000000')", ] for statement in statements: - found = False - for line in lines: - if statement in line: - found = True + found = any(statement in line for line in lines) self.assertTrue(found, statement) @@ -92,7 +89,7 @@ def test_with_range(self): out = six.StringIO() cmd = Command(stdout=out) - cmd.run_from_argv(["./manage.py sorcery", "upgrade", "tests.testapp", "-r", ":000000000000", "--no-color"]) + cmd.run_from_argv(["./manage.py sorcery", "upgrade", "tests_testapp", "-r", ":000000000000", "--no-color"]) revs = db.execute("select * from public.alembic_version_tests_testapp").fetchall() self.assertEqual(revs, [("000000000000",)]) @@ -103,7 +100,7 @@ def test_catching_alembic_error(self): cmd = Command(stdout=out, stderr=err) with self.assertRaises(SystemExit): - cmd.run_from_argv(["./manage.py sorcery", "upgrade", "tests.testapp", "-r", "revision", "--no-color"]) + cmd.run_from_argv(["./manage.py sorcery", "upgrade", "tests_testapp", "-r", "revision", "--no-color"]) err.seek(0) self.assertEqual(err.readlines(), ["CommandError: Can't locate revision identified by 'revision'\n"]) diff --git a/tests/minimalapp/apps.py b/tests/minimalapp/apps.py index ec5f1f4..04eca8f 100644 --- a/tests/minimalapp/apps.py +++ b/tests/minimalapp/apps.py @@ -3,4 +3,4 @@ class MinimalAppConfig(AppConfig): name = "tests.minimalapp" - label = "tests.minimalapp" + label = "tests_minimalapp" diff --git a/tests/otherapp/apps.py b/tests/otherapp/apps.py index 10d48c0..f893578 100644 --- a/tests/otherapp/apps.py +++ b/tests/otherapp/apps.py @@ -3,4 +3,4 @@ class OtherAppConfig(AppConfig): name = "tests.otherapp" - label = "tests.otherapp" + label = "tests_otherapp" diff --git a/tests/otherapp/models.py b/tests/otherapp/models.py index c121a07..02ed4a5 100644 --- a/tests/otherapp/models.py +++ b/tests/otherapp/models.py @@ -16,7 +16,7 @@ class OtherAppInOtherApp(db.Model): name = db.Column(db.String()) class Meta: - app_label = "tests.testapp" + app_label = "tests_testapp" db.configure_mappers() diff --git a/tests/templates/tests.testapp/owner_confirm_delete.html b/tests/templates/tests_testapp/owner_confirm_delete.html similarity index 100% rename from tests/templates/tests.testapp/owner_confirm_delete.html rename to tests/templates/tests_testapp/owner_confirm_delete.html diff --git a/tests/templates/tests.testapp/owner_detail.html b/tests/templates/tests_testapp/owner_detail.html similarity index 100% rename from tests/templates/tests.testapp/owner_detail.html rename to tests/templates/tests_testapp/owner_detail.html diff --git a/tests/templates/tests.testapp/owner_form.html b/tests/templates/tests_testapp/owner_form.html similarity index 100% rename from tests/templates/tests.testapp/owner_form.html rename to tests/templates/tests_testapp/owner_form.html diff --git a/tests/templates/tests.testapp/owner_list.html b/tests/templates/tests_testapp/owner_list.html similarity index 100% rename from tests/templates/tests.testapp/owner_list.html rename to tests/templates/tests_testapp/owner_list.html diff --git a/tests/templates/tests.testapp/vehicle_form.html b/tests/templates/tests_testapp/vehicle_form.html similarity index 100% rename from tests/templates/tests.testapp/vehicle_form.html rename to tests/templates/tests_testapp/vehicle_form.html diff --git a/tests/test_compat.py b/tests/test_compat.py deleted file mode 100644 index 2531c75..0000000 --- a/tests/test_compat.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.test import TestCase -from django_sorcery import compat - - -class TestCompat(TestCase): - def test_suppress(self): - - with compat.suppress(AssertionError): - assert 1 == 2 diff --git a/tests/test_utils.py b/tests/test_utils.py index ca85b1a..91f24a7 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -3,11 +3,6 @@ class TestUtils(TestCase): - def test_suppress(self): - - with utils.suppress(AssertionError): - assert 1 == 2 - def test_setdefaultattr(self): class Dummy: pass diff --git a/tests/testapp/apps.py b/tests/testapp/apps.py index 37dae36..c081494 100644 --- a/tests/testapp/apps.py +++ b/tests/testapp/apps.py @@ -3,7 +3,7 @@ class TestAppConfig(AppConfig): name = "tests.testapp" - label = "tests.testapp" + label = "tests_testapp" version_table_schema = "public" def ready(self): diff --git a/tox.ini b/tox.ini index ad6343b..3bf1fee 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ skipsdist = true envlist = {pypy36,py36}-{sqla12,sqla13,sqla14}-{dj11} - {pypy36,py36,py37,py38,py39}-{sqla12,sqla13,sqla14}-{dj20,dj21,dj22,dj30,dj31} + {pypy36,py36,py37,py38,py39}-{sqla12,sqla13,sqla14}-{dj20,dj21,dj22,dj30,dj31,dj32} [testenv] passenv = @@ -27,21 +27,15 @@ deps = dj22: django==2.2.* dj30: django==3.0.* dj31: django==3.1.* + dj32: django==3.2.* sqla12: sqlalchemy==1.2.* sqla13: sqlalchemy==1.3.* sqla14: sqlalchemy==1.4.* -rrequirements.txt -setenv = - COVERAGE_FLAGS = whitelist_externals = make commands = pip freeze make -j resetdb - make coverage - -[testenv:py37] -setenv = - COVERAGE_FLAGS = --cov-fail-under=100 -commands_pre = make lint + make coverage