From ffa1a85dc7fe3fa8a56e8735b4ac881092abf216 Mon Sep 17 00:00:00 2001 From: Adam Dobrawy Date: Thu, 14 Nov 2019 17:50:04 +0100 Subject: [PATCH] Modernize Python syntax, add Python 3.8 (#398) * Modernize Python syntax, add Python 3.8 * Update Python version & dist in TravisCI * Add postgresql as addon * Switch to psycopg2-binary * Drop django.utils.six --- .travis.yml | 12 +++++--- docs/conf.py | 17 ++++++----- model_utils/choices.py | 6 ++-- model_utils/fields.py | 28 +++++++++---------- model_utils/managers.py | 27 ++++++++---------- model_utils/models.py | 6 ++-- model_utils/tracker.py | 24 ++++++++-------- requirements-test.txt | 2 +- setup.py | 5 ++-- tests/fields.py | 7 ++--- tests/managers.py | 2 -- tests/models.py | 8 ++---- tests/test_choices.py | 2 -- tests/test_fields/test_field_tracker.py | 3 +- tests/test_fields/test_monitor_field.py | 2 -- tests/test_fields/test_split_field.py | 9 ++---- tests/test_fields/test_status_field.py | 2 -- tests/test_fields/test_uuid_field.py | 2 -- tests/test_inheritance_iterable.py | 2 -- .../test_managers/test_inheritance_manager.py | 24 ++++++++-------- tests/test_managers/test_join_manager.py | 1 - tests/test_managers/test_query_manager.py | 2 -- .../test_managers/test_softdelete_manager.py | 2 -- tests/test_managers/test_status_manager.py | 2 -- tests/test_miscellaneous.py | 2 -- tests/test_models/test_deferred_fields.py | 2 -- .../test_savesignalhandling_model.py | 2 -- tests/test_models/test_softdeletable_model.py | 2 -- tests/test_models/test_timeframed_model.py | 2 -- tests/test_models/test_timestamped_model.py | 2 -- tests/test_models/test_uuid_model.py | 2 -- tox.ini | 7 +++-- 32 files changed, 85 insertions(+), 133 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9bc8f89..bc48f8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,23 @@ -sudo: True -dist: xenial +version: ~> 1.0 +dist: bionic +os: linux language: python cache: pip python: -- 3.7 - 3.6 +- 3.7 +- 3.8 install: pip install tox-travis codecov # positional args ({posargs}) to pass into tox.ini script: tox -- --cov --cov-append +addons: + postgresql: '10' services: - postgresql after_success: codecov deploy: provider: pypi - user: jazzband + username: jazzband server: https://jazzband.co/projects/django-model-utils/upload distributions: sdist bdist_wheel password: diff --git a/docs/conf.py b/docs/conf.py index 9f0c4e7..d234b3f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # django-model-utils documentation build configuration file, created by # sphinx-quickstart on Wed Jul 31 22:27:07 2013. @@ -40,8 +39,8 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'django-model-utils' -copyright = u'2015, Carl Meyer' +project = 'django-model-utils' +copyright = '2015, Carl Meyer' parent_dir = os.path.dirname(os.path.dirname(__file__)) @@ -194,8 +193,8 @@ latex_elements = { # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'django-model-utils.tex', u'django-model-utils Documentation', - u'Carl Meyer', 'manual'), + ('index', 'django-model-utils.tex', 'django-model-utils Documentation', + 'Carl Meyer', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -224,8 +223,8 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'django-model-utils', u'django-model-utils Documentation', - [u'Carl Meyer'], 1) + ('index', 'django-model-utils', 'django-model-utils Documentation', + ['Carl Meyer'], 1) ] # If true, show URL addresses after external links. @@ -238,8 +237,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'django-model-utils', u'django-model-utils Documentation', - u'Carl Meyer', 'django-model-utils', 'One line description of project.', + ('index', 'django-model-utils', 'django-model-utils Documentation', + 'Carl Meyer', 'django-model-utils', 'One line description of project.', 'Miscellaneous'), ] diff --git a/model_utils/choices.py b/model_utils/choices.py index 2219a25..46c3877 100644 --- a/model_utils/choices.py +++ b/model_utils/choices.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import copy @@ -132,9 +130,9 @@ class Choices: return False def __repr__(self): - return '%s(%s)' % ( + return '{}({})'.format( self.__class__.__name__, - ', '.join(("%s" % repr(i) for i in self._triples)) + ', '.join("%s" % repr(i) for i in self._triples) ) def __contains__(self, item): diff --git a/model_utils/fields.py b/model_utils/fields.py index 7e79855..0f943e5 100644 --- a/model_utils/fields.py +++ b/model_utils/fields.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import django import uuid from django.db import models @@ -22,7 +20,7 @@ class AutoCreatedField(models.DateTimeField): def __init__(self, *args, **kwargs): kwargs.setdefault('editable', False) kwargs.setdefault('default', now) - super(AutoCreatedField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class AutoLastModifiedField(AutoCreatedField): @@ -73,7 +71,7 @@ class StatusField(models.CharField): kwargs.setdefault('max_length', 100) self.check_for_status = not kwargs.pop('no_check_for_status', False) self.choices_name = kwargs.pop('choices_name', DEFAULT_CHOICES_NAME) - super(StatusField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def prepare_class(self, sender, **kwargs): if not sender._meta.abstract and self.check_for_status: @@ -90,10 +88,10 @@ class StatusField(models.CharField): # the STATUS class attr being available), but we need to set some dummy # choices now so the super method will add the get_FOO_display method self.choices = [(0, 'dummy')] - super(StatusField, self).contribute_to_class(cls, name) + super().contribute_to_class(cls, name) def deconstruct(self): - name, path, args, kwargs = super(StatusField, self).deconstruct() + name, path, args, kwargs = super().deconstruct() kwargs['no_check_for_status'] = True return name, path, args, kwargs @@ -117,12 +115,12 @@ class MonitorField(models.DateTimeField): if when is not None: when = set(when) self.when = when - super(MonitorField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def contribute_to_class(self, cls, name): self.monitor_attname = '_monitor_%s' % name models.signals.post_init.connect(self._save_initial, sender=cls) - super(MonitorField, self).contribute_to_class(cls, name) + super().contribute_to_class(cls, name) def get_monitored_value(self, instance): return getattr(instance, self.monitor) @@ -141,10 +139,10 @@ class MonitorField(models.DateTimeField): if self.when is None or current in self.when: setattr(model_instance, self.attname, value) self._save_initial(model_instance.__class__, model_instance) - return super(MonitorField, self).pre_save(model_instance, add) + return super().pre_save(model_instance, add) def deconstruct(self): - name, path, args, kwargs = super(MonitorField, self).deconstruct() + name, path, args, kwargs = super().deconstruct() kwargs['monitor'] = self.monitor if self.when is not None: kwargs['when'] = self.when @@ -236,17 +234,17 @@ class SplitField(models.TextField): # _excerpt field itself is frozen as well. See introspection # rules below. self.add_excerpt_field = not kwargs.pop('no_excerpt_field', False) - super(SplitField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def contribute_to_class(self, cls, name): if self.add_excerpt_field and not cls._meta.abstract: excerpt_field = models.TextField(editable=False) cls.add_to_class(_excerpt_field_name(name), excerpt_field) - super(SplitField, self).contribute_to_class(cls, name) + super().contribute_to_class(cls, name) setattr(cls, self.name, SplitDescriptor(self)) def pre_save(self, model_instance, add): - value = super(SplitField, self).pre_save(model_instance, add) + value = super().pre_save(model_instance, add) excerpt = get_excerpt(value.content) setattr(model_instance, _excerpt_field_name(self.attname), excerpt) return value.content @@ -262,7 +260,7 @@ class SplitField(models.TextField): return value def deconstruct(self): - name, path, args, kwargs = super(SplitField, self).deconstruct() + name, path, args, kwargs = super().deconstruct() kwargs['no_excerpt_field'] = True return name, path, args, kwargs @@ -310,4 +308,4 @@ class UUIDField(models.UUIDField): kwargs.setdefault('primary_key', primary_key) kwargs.setdefault('editable', editable) kwargs.setdefault('default', default) - super(UUIDField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) diff --git a/model_utils/managers.py b/model_utils/managers.py index 22985a9..34f8012 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals import django from django.db import models from django.db.models.fields.related import OneToOneField, OneToOneRel @@ -7,7 +6,6 @@ from django.db.models.query import ModelIterable from django.core.exceptions import ObjectDoesNotExist from django.db.models.constants import LOOKUP_SEP -from django.utils.six import string_types from django.db import connection from django.db.models.sql.datastructures import Join @@ -40,13 +38,12 @@ class InheritanceIterable(ModelIterable): yield sub_obj else: - for obj in iter: - yield obj + yield from iter class InheritanceQuerySetMixin: def __init__(self, *args, **kwargs): - super(InheritanceQuerySetMixin, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._iterable_class = InheritanceIterable def select_subclasses(self, *subclasses): @@ -65,7 +62,7 @@ class InheritanceQuerySetMixin: if subclass is self.model: continue - if not isinstance(subclass, string_types): + if not isinstance(subclass, (str,)): subclass = self._get_ancestors_path( subclass, levels=levels) @@ -73,7 +70,7 @@ class InheritanceQuerySetMixin: verified_subclasses.append(subclass) else: raise ValueError( - '%r is not in the discovered subclasses, tried: %s' % ( + '{!r} is not in the discovered subclasses, tried: {}'.format( subclass, ', '.join(calculated_subclasses)) ) subclasses = verified_subclasses @@ -93,11 +90,11 @@ class InheritanceQuerySetMixin: if hasattr(self, name): kwargs[name] = getattr(self, name) - return super(InheritanceQuerySetMixin, self)._chain(**kwargs) + return super()._chain(**kwargs) def _clone(self, klass=None, setup=False, **kwargs): if django.VERSION >= (2, 0): - qs = super(InheritanceQuerySetMixin, self)._clone() + qs = super()._clone() for name in ['subclasses', '_annotated']: if hasattr(self, name): setattr(qs, name, getattr(self, name)) @@ -107,10 +104,10 @@ class InheritanceQuerySetMixin: if hasattr(self, name): kwargs[name] = getattr(self, name) - return super(InheritanceQuerySetMixin, self)._clone(**kwargs) + return super()._clone(**kwargs) def annotate(self, *args, **kwargs): - qset = super(InheritanceQuerySetMixin, self).annotate(*args, **kwargs) + qset = super().annotate(*args, **kwargs) qset._annotated = [a.default_alias for a in args] + list(kwargs.keys()) return qset @@ -152,7 +149,7 @@ class InheritanceQuerySetMixin: """ if not issubclass(model, self.model): raise ValueError( - "%r is not a subclass of %r" % (model, self.model)) + "{!r} is not a subclass of {!r}".format(model, self.model)) ancestry = [] # should be a OneToOneField or None @@ -208,7 +205,7 @@ class InheritanceQuerySet(InheritanceQuerySetMixin, QuerySet): where_queries = [] for model in models: where_queries.append('(' + ' AND '.join([ - '"%s"."%s" IS NOT NULL' % ( + '"{}"."{}" IS NOT NULL'.format( model._meta.db_table, field.attname, # Should this be something else? ) for field in model._meta.parents.values() @@ -244,14 +241,14 @@ class QueryManagerMixin: else: self._q = models.Q(**kwargs) self._order_by = None - super(QueryManagerMixin, self).__init__() + super().__init__() def order_by(self, *args): self._order_by = args return self def get_queryset(self): - qs = super(QueryManagerMixin, self).get_queryset().filter(self._q) + qs = super().get_queryset().filter(self._q) if self._order_by is not None: return qs.order_by(*self._order_by) return qs diff --git a/model_utils/models.py b/model_utils/models.py index 50a83f3..65503f5 100644 --- a/model_utils/models.py +++ b/model_utils/models.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.core.exceptions import ImproperlyConfigured from django.db import models, transaction, router from django.db.models.signals import post_save, pre_save @@ -136,7 +134,7 @@ class SoftDeletableModel(models.Model): self.is_removed = True self.save(using=using) else: - return super(SoftDeletableModel, self).delete(using=using, *args, **kwargs) + return super().delete(using=using, *args, **kwargs) class UUIDModel(models.Model): @@ -170,7 +168,7 @@ class SaveSignalHandlingModel(models.Model): self.signals_to_disable = signals_to_disable or [] - super(SaveSignalHandlingModel, self).save(*args, **kwargs) + super().save(*args, **kwargs) def save_base(self, raw=False, force_insert=False, force_update=False, using=None, update_fields=None): diff --git a/model_utils/tracker.py b/model_utils/tracker.py index 4a806f4..d5c840a 100644 --- a/model_utils/tracker.py +++ b/model_utils/tracker.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from copy import deepcopy import django @@ -20,7 +18,7 @@ class DescriptorMixin: if field_name in instance._deferred_fields: instance._deferred_fields.remove(field_name) was_deferred = True - value = super(DescriptorMixin, self).__get__(instance, owner) + value = super().__get__(instance, owner) if was_deferred: self.tracker_instance.saved_data[field_name] = deepcopy(value) return value @@ -125,7 +123,7 @@ class FieldInstanceTracker: else: fields = self.fields - return dict((f, self.get_field_value(f)) for f in fields) + return {f: self.get_field_value(f) for f in fields} def has_changed(self, field): """Returns ``True`` if field has changed from currently saved value""" @@ -159,11 +157,11 @@ class FieldInstanceTracker: def changed(self): """Returns dict of fields that changed since save (with old values)""" - return dict( - (field, self.previous(field)) + return { + field: self.previous(field) for field in self.fields if self.has_changed(field) - ) + } def init_deferred_fields(self): self.instance._deferred_fields = set() @@ -199,10 +197,10 @@ class FieldTracker: def get_field_map(self, cls): """Returns dict mapping fields names to model attribute names""" - field_map = dict((field, field) for field in self.fields) - all_fields = dict((f.name, f.attname) for f in cls._meta.fields) - field_map.update(**dict((k, v) for (k, v) in all_fields.items() - if k in field_map)) + field_map = {field: field for field in self.fields} + all_fields = {f.name: f.attname for f in cls._meta.fields} + field_map.update(**{k: v for (k, v) in all_fields.items() + if k in field_map}) return field_map def contribute_to_class(self, cls, name): @@ -280,11 +278,11 @@ class ModelInstanceTracker(FieldInstanceTracker): return {} saved = self.saved_data.items() current = self.current() - return dict((k, v) for k, v in saved if v != current[k]) + return {k: v for k, v in saved if v != current[k]} class ModelTracker(FieldTracker): tracker_class = ModelInstanceTracker def get_field_map(self, cls): - return dict((field, field) for field in self.fields) + return {field: field for field in self.fields} diff --git a/requirements-test.txt b/requirements-test.txt index f190999..b363602 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,4 +1,4 @@ pytest==4.5.0 pytest-django==3.4.7 -psycopg2==2.7.6.1 +psycopg2-binary==2.8.4 pytest-cov==2.7.1 diff --git a/setup.py b/setup.py index 9c27fe8..c70f0d2 100644 --- a/setup.py +++ b/setup.py @@ -42,11 +42,12 @@ setup( 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Framework :: Django', - 'Framework :: Django :: 2.1', 'Framework :: Django :: 1.11', + 'Framework :: Django :: 2.1', 'Framework :: Django :: 2.2', ], zip_safe=False, diff --git a/tests/fields.py b/tests/fields.py index 230f128..87eb22d 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -1,13 +1,12 @@ import django from django.db import models -from django.utils.six import with_metaclass, string_types def mutable_from_db(value): if value == '': return None try: - if isinstance(value, string_types): + if isinstance(value, (str,)): return [int(i) for i in value.split(',')] except ValueError: pass @@ -18,7 +17,7 @@ def mutable_to_db(value): if value is None: return '' if isinstance(value, list): - value = ','.join((str(i) for i in value)) + value = ','.join(str(i) for i in value) return str(value) @@ -30,5 +29,5 @@ class MutableField(models.TextField): return mutable_from_db(value) def get_db_prep_save(self, value, connection): - value = super(MutableField, self).get_db_prep_save(value, connection) + value = super().get_db_prep_save(value, connection) return mutable_to_db(value) diff --git a/tests/managers.py b/tests/managers.py index 4a055f2..43b9860 100644 --- a/tests/managers.py +++ b/tests/managers.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals, absolute_import - from model_utils.managers import SoftDeletableQuerySet, SoftDeletableManager diff --git a/tests/models.py b/tests/models.py index c3c85db..c06d883 100644 --- a/tests/models.py +++ b/tests/models.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals, absolute_import - import django from django.db import models from django.db.models.query_utils import DeferredAttribute @@ -48,7 +46,7 @@ class InheritanceManagerTestParent(models.Model): objects = InheritanceManager() def __str__(self): - return "%s(%s)" % ( + return "{}({})".format( self.__class__.__name__[len('InheritanceManagerTest'):], self.pk, ) @@ -246,7 +244,7 @@ class Tracked(models.Model): def save(self, *args, **kwargs): """ No-op save() to ensure that FieldTracker.patch_save() works. """ - super(Tracked, self).save(*args, **kwargs) + super().save(*args, **kwargs) class TrackedFK(models.Model): @@ -399,7 +397,7 @@ class StringyDescriptor: class CustomDescriptorField(models.IntegerField): def contribute_to_class(self, cls, name, **kwargs): - super(CustomDescriptorField, self).contribute_to_class(cls, name, **kwargs) + super().contribute_to_class(cls, name, **kwargs) setattr(cls, name, StringyDescriptor(name)) diff --git a/tests/test_choices.py b/tests/test_choices.py index cb5bec9..6d09319 100644 --- a/tests/test_choices.py +++ b/tests/test_choices.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.test import TestCase from model_utils import Choices diff --git a/tests/test_fields/test_field_tracker.py b/tests/test_fields/test_field_tracker.py index b877bf2..0be3418 100644 --- a/tests/test_fields/test_field_tracker.py +++ b/tests/test_fields/test_field_tracker.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals from unittest import skip import django from django.core.exceptions import FieldError @@ -414,7 +413,7 @@ class FieldTrackedModelMultiTests(FieldTrackerTestCase, def test_pre_save_previous(self): for tracker in self.trackers: self.tracker = tracker - super(FieldTrackedModelMultiTests, self).test_pre_save_previous() + super().test_pre_save_previous() def test_post_save_has_changed(self): self.update_instance(name='retro', number=4) diff --git a/tests/test_fields/test_monitor_field.py b/tests/test_fields/test_monitor_field.py index 6c5792e..b3f3522 100644 --- a/tests/test_fields/test_monitor_field.py +++ b/tests/test_fields/test_monitor_field.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from datetime import datetime from freezegun import freeze_time diff --git a/tests/test_fields/test_split_field.py b/tests/test_fields/test_split_field.py index dfde85f..c053fa1 100644 --- a/tests/test_fields/test_split_field.py +++ b/tests/test_fields/test_split_field.py @@ -1,6 +1,3 @@ -from __future__ import unicode_literals - -from django.utils.six import text_type from django.test import TestCase from tests.models import Article, SplitFieldAbstractParent @@ -15,7 +12,7 @@ class SplitFieldTests(TestCase): title='example post', body=self.full_text) def test_unicode_content(self): - self.assertEqual(text_type(self.post.body), self.full_text) + self.assertEqual(str(self.post.body), self.full_text) def test_excerpt(self): self.assertEqual(self.post.body.excerpt, self.excerpt) @@ -40,13 +37,13 @@ class SplitFieldTests(TestCase): new_text = 'different\n\n\n\nother' self.post.body = new_text self.post.save() - self.assertEqual(text_type(self.post.body), new_text) + self.assertEqual(str(self.post.body), new_text) def test_assign_to_content(self): new_text = 'different\n\n\n\nother' self.post.body.content = new_text self.post.save() - self.assertEqual(text_type(self.post.body), new_text) + self.assertEqual(str(self.post.body), new_text) def test_assign_to_excerpt(self): with self.assertRaises(AttributeError): diff --git a/tests/test_fields/test_status_field.py b/tests/test_fields/test_status_field.py index dc0f223..a09e2b9 100644 --- a/tests/test_fields/test_status_field.py +++ b/tests/test_fields/test_status_field.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.test import TestCase from model_utils.fields import StatusField diff --git a/tests/test_fields/test_uuid_field.py b/tests/test_fields/test_uuid_field.py index 3a6c739..cc354f0 100644 --- a/tests/test_fields/test_uuid_field.py +++ b/tests/test_fields/test_uuid_field.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import uuid from django.core.exceptions import ValidationError diff --git a/tests/test_inheritance_iterable.py b/tests/test_inheritance_iterable.py index 884b763..6aca164 100644 --- a/tests/test_inheritance_iterable.py +++ b/tests/test_inheritance_iterable.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from unittest import skipIf import django diff --git a/tests/test_managers/test_inheritance_manager.py b/tests/test_managers/test_inheritance_manager.py index 95b7da4..d142220 100644 --- a/tests/test_managers/test_inheritance_manager.py +++ b/tests/test_managers/test_inheritance_manager.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from unittest import skipUnless import django @@ -27,16 +25,16 @@ class InheritanceManagerTests(TestCase): return InheritanceManagerTestParent.objects def test_normal(self): - children = set([ + children = { InheritanceManagerTestParent(pk=self.child1.pk), InheritanceManagerTestParent(pk=self.child2.pk), InheritanceManagerTestParent(pk=self.grandchild1.pk), InheritanceManagerTestParent(pk=self.grandchild1_2.pk), - ]) + } self.assertEqual(set(self.get_manager().all()), children) def test_select_all_subclasses(self): - children = set([self.child1, self.child2]) + children = {self.child1, self.child2} children.add(self.grandchild1) children.add(self.grandchild1_2) self.assertEqual( @@ -53,12 +51,12 @@ class InheritanceManagerTests(TestCase): self.get_manager().select_subclasses('user') def test_select_specific_subclasses(self): - children = set([ + children = { self.child1, InheritanceManagerTestParent(pk=self.child2.pk), InheritanceManagerTestChild1(pk=self.grandchild1.pk), InheritanceManagerTestChild1(pk=self.grandchild1_2.pk), - ]) + } self.assertEqual( set( self.get_manager().select_subclasses( @@ -68,12 +66,12 @@ class InheritanceManagerTests(TestCase): ) def test_select_specific_grandchildren(self): - children = set([ + children = { InheritanceManagerTestParent(pk=self.child1.pk), InheritanceManagerTestParent(pk=self.child2.pk), self.grandchild1, InheritanceManagerTestParent(pk=self.grandchild1_2.pk), - ]) + } self.assertEqual( set( self.get_manager().select_subclasses( @@ -84,12 +82,12 @@ class InheritanceManagerTests(TestCase): ) def test_children_and_grandchildren(self): - children = set([ + children = { self.child1, InheritanceManagerTestParent(pk=self.child2.pk), self.grandchild1, InheritanceManagerTestChild1(pk=self.grandchild1_2.pk), - ]) + } self.assertEqual( set( self.get_manager().select_subclasses( @@ -463,14 +461,14 @@ class InheritanceManagerUsingModelsTests(TestCase): results = InheritanceManagerTestParent.objects.instance_of(InheritanceManagerTestChild3, InheritanceManagerTestGrandChild1).select_subclasses() - self.assertEqual(set([child3, grandchild1]), set(results)) + self.assertEqual({child3, grandchild1}, set(results)) def test_select_subclasses_interaction_with_instance_of(self): child3 = InheritanceManagerTestChild3.objects.create() results = InheritanceManagerTestParent.objects.select_subclasses(InheritanceManagerTestChild1).instance_of(InheritanceManagerTestChild3) - self.assertEqual(set([child3]), set(results)) + self.assertEqual({child3}, set(results)) diff --git a/tests/test_managers/test_join_manager.py b/tests/test_managers/test_join_manager.py index b8a8131..c8110f1 100644 --- a/tests/test_managers/test_join_manager.py +++ b/tests/test_managers/test_join_manager.py @@ -1,4 +1,3 @@ - from django.test import TestCase from tests.models import JoinItemForeignKey, BoxJoinModel diff --git a/tests/test_managers/test_query_manager.py b/tests/test_managers/test_query_manager.py index dd539b6..2339dbe 100644 --- a/tests/test_managers/test_query_manager.py +++ b/tests/test_managers/test_query_manager.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.test import TestCase from tests.models import Post diff --git a/tests/test_managers/test_softdelete_manager.py b/tests/test_managers/test_softdelete_manager.py index 4ae5475..db495c4 100644 --- a/tests/test_managers/test_softdelete_manager.py +++ b/tests/test_managers/test_softdelete_manager.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.test import TestCase from tests.models import CustomSoftDelete diff --git a/tests/test_managers/test_status_manager.py b/tests/test_managers/test_status_manager.py index 593a547..e7fe144 100644 --- a/tests/test_managers/test_status_manager.py +++ b/tests/test_managers/test_status_manager.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.db import models from django.core.exceptions import ImproperlyConfigured from django.test import TestCase diff --git a/tests/test_miscellaneous.py b/tests/test_miscellaneous.py index 2f34fbb..684d824 100644 --- a/tests/test_miscellaneous.py +++ b/tests/test_miscellaneous.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.core.management import call_command from django.test import TestCase diff --git a/tests/test_models/test_deferred_fields.py b/tests/test_models/test_deferred_fields.py index 2a1b702..97801a8 100644 --- a/tests/test_models/test_deferred_fields.py +++ b/tests/test_models/test_deferred_fields.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import django from django.test import TestCase diff --git a/tests/test_models/test_savesignalhandling_model.py b/tests/test_models/test_savesignalhandling_model.py index 6af0820..fbe9d81 100644 --- a/tests/test_models/test_savesignalhandling_model.py +++ b/tests/test_models/test_savesignalhandling_model.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.test import TestCase from tests.models import SaveSignalHandlingTestModel diff --git a/tests/test_models/test_softdeletable_model.py b/tests/test_models/test_softdeletable_model.py index 5f06fd3..6cb8682 100644 --- a/tests/test_models/test_softdeletable_model.py +++ b/tests/test_models/test_softdeletable_model.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.db.utils import ConnectionDoesNotExist from django.test import TestCase diff --git a/tests/test_models/test_timeframed_model.py b/tests/test_models/test_timeframed_model.py index dccc5a7..c51b9e5 100644 --- a/tests/test_models/test_timeframed_model.py +++ b/tests/test_models/test_timeframed_model.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from datetime import datetime, timedelta from django.db import models diff --git a/tests/test_models/test_timestamped_model.py b/tests/test_models/test_timestamped_model.py index 9fc884f..8bd226e 100644 --- a/tests/test_models/test_timestamped_model.py +++ b/tests/test_models/test_timestamped_model.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from datetime import datetime, timedelta from freezegun import freeze_time diff --git a/tests/test_models/test_uuid_model.py b/tests/test_models/test_uuid_model.py index 5559159..3ce9f91 100644 --- a/tests/test_models/test_uuid_model.py +++ b/tests/test_models/test_uuid_model.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.test import TestCase from tests.models import CustomUUIDModel, CustomNotPrimaryUUIDModel diff --git a/tox.ini b/tox.ini index 21f13dc..2b024ac 100644 --- a/tox.ini +++ b/tox.ini @@ -2,13 +2,14 @@ envlist = py37-django{202,201} py36-django{111,202,201,trunk} + py38-django{202,201,trunk} flake8 [testenv] deps = - django111: Django>=1.11,<1.12 - django202: Django>=2.2,<3.0 - django201: Django>=2.1,<2.2 + django111: Django==1.11.* + django202: Django==2.2.* + django201: Django==2.1.* djangotrunk: https://github.com/django/django/archive/master.tar.gz freezegun == 0.3.8 -rrequirements-test.txt