From fda2d39ec48002464b89bff319d2f2247a565034 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Sat, 26 Mar 2016 20:02:49 -0400 Subject: [PATCH] Drop unsupported django versions --- .travis.yml | 18 +----- CHANGES.rst | 5 ++ README.rst | 5 +- model_utils/fields.py | 27 -------- model_utils/managers.py | 8 +-- model_utils/tests/helpers.py | 5 -- model_utils/tests/test_fields/__init__.py | 5 -- .../tests/test_fields/test_field_tracker.py | 41 ++++++------ model_utils/tests/test_managers/__init__.py | 5 -- .../test_managers/test_inheritance_manager.py | 62 +++---------------- model_utils/tests/test_miscellaneous.py | 31 ---------- model_utils/tests/test_models/__init__.py | 5 -- model_utils/tests/tests.py | 9 --- setup.py | 4 +- tox.ini | 13 +--- 15 files changed, 44 insertions(+), 199 deletions(-) delete mode 100644 model_utils/tests/helpers.py delete mode 100644 model_utils/tests/tests.py diff --git a/.travis.yml b/.travis.yml index c38cff61..27291377 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,30 +3,18 @@ language: python python: 2.7 env: - - TOXENV=py26-django14 - - TOXENV=py26-django15 - - TOXENV=py26-django16 - - TOXENV=py27-django110 - - TOXENV=py27-django14 - - TOXENV=py27-django15 - - TOXENV=py27-django15_nosouth - - TOXENV=py27-django16 - - TOXENV=py27-django17 - TOXENV=py27-django18 - TOXENV=py27-django19 + - TOXENV=py27-django110 - TOXENV=py27-django_trunk - - TOXENV=py33-django15 - - TOXENV=py33-django16 - - TOXENV=py33-django17 - TOXENV=py33-django18 - - TOXENV=py34-django110 - - TOXENV=py34-django17 - TOXENV=py34-django18 - TOXENV=py34-django19 + - TOXENV=py34-django110 - TOXENV=py34-django_trunk - - TOXENV=py35-django110 - TOXENV=py35-django18 - TOXENV=py35-django19 + - TOXENV=py35-django110 - TOXENV=py35-django_trunk install: diff --git a/CHANGES.rst b/CHANGES.rst index fe1498a4..bc239269 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,11 @@ CHANGES master (unreleased) ------------------- +* Drop support for Python 2.6. + +* Drop support for Django 1.4, 1.5, 1.6, 1.7. + + 2.6.1 (2017.01.11) ------------------ diff --git a/README.rst b/README.rst index 001712f4..9ce6788d 100644 --- a/README.rst +++ b/README.rst @@ -11,9 +11,8 @@ django-model-utils Django model mixins and utilities. -``django-model-utils`` supports `Django`_ 1.4 through 1.9 (latest bugfix -release in each series only) on Python 2.6 (through Django 1.6 only), 2.7, 3.3 -(through Django 1.8 only), 3.4 and 3.5. +``django-model-utils`` supports `Django`_ 1.8 through 1.10 (latest bugfix +release in each series only) on Python 2.7, 3.3 (Django 1.8 only), 3.4 and 3.5. .. _Django: http://www.djangoproject.com/ diff --git a/model_utils/fields.py b/model_utils/fields.py index fe9d4a81..a349b7c6 100644 --- a/model_utils/fields.py +++ b/model_utils/fields.py @@ -241,30 +241,3 @@ def deconstruct(self): name, path, args, kwargs = super(SplitField, self).deconstruct() kwargs['no_excerpt_field'] = True return name, path, args, kwargs - -# allow South to handle these fields smoothly -try: - from south.modelsinspector import add_introspection_rules - # For a normal MarkupField, the add_excerpt_field attribute is - # always True, which means no_excerpt_field arg will always be - # True in a frozen MarkupField, which is what we want. - add_introspection_rules(rules=[ - ( - (SplitField,), - [], - {'no_excerpt_field': ('add_excerpt_field', {})} - ), - ( - (MonitorField,), - [], - {'monitor': ('monitor', {})} - ), - ( - (StatusField,), - [], - {'no_check_for_status': ('check_for_status', {})} - ), - ], patterns=['model_utils\.fields\.']) -except ImportError: - pass - diff --git a/model_utils/managers.py b/model_utils/managers.py index 0b677fff..3e345c9d 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -5,12 +5,8 @@ from django.db.models.query import QuerySet from django.core.exceptions import ObjectDoesNotExist -try: - from django.db.models.constants import LOOKUP_SEP - from django.utils.six import string_types -except ImportError: # Django < 1.5 - from django.db.models.sql.constants import LOOKUP_SEP - string_types = (basestring,) +from django.db.models.constants import LOOKUP_SEP +from django.utils.six import string_types class InheritanceQuerySetMixin(object): diff --git a/model_utils/tests/helpers.py b/model_utils/tests/helpers.py deleted file mode 100644 index 499dd521..00000000 --- a/model_utils/tests/helpers.py +++ /dev/null @@ -1,5 +0,0 @@ - -try: - from unittest import skipUnless -except ImportError: # Python 2.6 - from django.utils.unittest import skipUnless diff --git a/model_utils/tests/test_fields/__init__.py b/model_utils/tests/test_fields/__init__.py index 23a349f6..e69de29b 100644 --- a/model_utils/tests/test_fields/__init__.py +++ b/model_utils/tests/test_fields/__init__.py @@ -1,5 +0,0 @@ -# Needed for Django 1.4/1.5 test runner -from .test_field_tracker import * -from .test_monitor_field import * -from .test_split_field import * -from .test_status_field import * diff --git a/model_utils/tests/test_fields/test_field_tracker.py b/model_utils/tests/test_fields/test_field_tracker.py index c215f77b..8d6641c5 100644 --- a/model_utils/tests/test_fields/test_field_tracker.py +++ b/model_utils/tests/test_fields/test_field_tracker.py @@ -1,11 +1,12 @@ from __future__ import unicode_literals +from unittest import skipUnless + import django from django.core.exceptions import FieldError from django.test import TestCase from model_utils import FieldTracker -from model_utils.tests.helpers import skipUnless from model_utils.tests.models import ( Tracked, TrackedFK, InheritedTrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple, InheritedTracked, TrackedFileField, @@ -97,15 +98,14 @@ def test_first_save(self): self.assertPrevious(name=None, number=None, mutable=None) self.assertCurrent(name='retro', number=4, id=None, mutable=[1,2,3]) self.assertChanged(name=None, number=None, mutable=None) - # Django 1.4 doesn't have update_fields - if django.VERSION >= (1, 5, 0): - self.instance.save(update_fields=[]) - self.assertHasChanged(name=True, number=True, mutable=True) - self.assertPrevious(name=None, number=None, mutable=None) - self.assertCurrent(name='retro', number=4, id=None, mutable=[1,2,3]) - self.assertChanged(name=None, number=None, mutable=None) - with self.assertRaises(ValueError): - self.instance.save(update_fields=['number']) + + self.instance.save(update_fields=[]) + self.assertHasChanged(name=True, number=True, mutable=True) + self.assertPrevious(name=None, number=None, mutable=None) + self.assertCurrent(name='retro', number=4, id=None, mutable=[1,2,3]) + self.assertChanged(name=None, number=None, mutable=None) + with self.assertRaises(ValueError): + self.instance.save(update_fields=['number']) def test_post_save_has_changed(self): self.update_instance(name='retro', number=4, mutable=[1,2,3]) @@ -153,8 +153,6 @@ def test_current(self): self.instance.save() self.assertCurrent(id=self.instance.id, name='new age', number=8, mutable=[1,4,3]) - @skipUnless( - django.VERSION >= (1, 5, 0), "Django 1.4 doesn't have update_fields") def test_update_fields(self): self.update_instance(name='retro', number=4, mutable=[1,2,3]) self.assertChanged() @@ -280,8 +278,6 @@ def test_current(self): self.instance.save() self.assertCurrent(name='new age') - @skipUnless( - django.VERSION >= (1, 5, 0), "Django 1.4 doesn't have update_fields") def test_update_fields(self): self.update_instance(name='retro', number=4) self.assertChanged() @@ -622,15 +618,14 @@ def test_first_save(self): self.assertPrevious(name=None, number=None, mutable=None) self.assertCurrent(name='retro', number=4, id=None, mutable=[1,2,3]) self.assertChanged() - # Django 1.4 doesn't have update_fields - if django.VERSION >= (1, 5, 0): - self.instance.save(update_fields=[]) - self.assertHasChanged(name=True, number=True, mutable=True) - self.assertPrevious(name=None, number=None, mutable=None) - self.assertCurrent(name='retro', number=4, id=None, mutable=[1,2,3]) - self.assertChanged() - with self.assertRaises(ValueError): - self.instance.save(update_fields=['number']) + + self.instance.save(update_fields=[]) + self.assertHasChanged(name=True, number=True, mutable=True) + self.assertPrevious(name=None, number=None, mutable=None) + self.assertCurrent(name='retro', number=4, id=None, mutable=[1,2,3]) + self.assertChanged() + with self.assertRaises(ValueError): + self.instance.save(update_fields=['number']) def test_pre_save_has_changed(self): self.assertHasChanged(name=True, number=True) diff --git a/model_utils/tests/test_managers/__init__.py b/model_utils/tests/test_managers/__init__.py index 92661aa0..e69de29b 100644 --- a/model_utils/tests/test_managers/__init__.py +++ b/model_utils/tests/test_managers/__init__.py @@ -1,5 +0,0 @@ -# Needed for Django 1.4/1.5 test runner -from .test_inheritance_manager import * -from .test_query_manager import * -from .test_status_manager import * -from .test_softdelete_manager import * diff --git a/model_utils/tests/test_managers/test_inheritance_manager.py b/model_utils/tests/test_managers/test_inheritance_manager.py index 65d8b59b..0c2b91d0 100644 --- a/model_utils/tests/test_managers/test_inheritance_manager.py +++ b/model_utils/tests/test_managers/test_inheritance_manager.py @@ -1,10 +1,11 @@ from __future__ import unicode_literals +from unittest import skipUnless + import django from django.db import models from django.test import TestCase -from model_utils.tests.helpers import skipUnless from model_utils.tests.models import (InheritanceManagerTestRelated, InheritanceManagerTestGrandChild1, InheritanceManagerTestGrandChild1_2, InheritanceManagerTestParent, InheritanceManagerTestChild1, @@ -34,12 +35,8 @@ def test_normal(self): def test_select_all_subclasses(self): children = set([self.child1, self.child2]) - if django.VERSION >= (1, 6, 0): - children.add(self.grandchild1) - children.add(self.grandchild1_2) - else: - children.add(InheritanceManagerTestChild1(pk=self.grandchild1.pk)) - children.add(InheritanceManagerTestChild1(pk=self.grandchild1_2.pk)) + children.add(self.grandchild1) + children.add(self.grandchild1_2) self.assertEqual( set(self.get_manager().select_subclasses()), children) @@ -68,7 +65,6 @@ def test_select_specific_subclasses(self): children, ) - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_select_specific_grandchildren(self): children = set([ InheritanceManagerTestParent(pk=self.child1.pk), @@ -85,7 +81,6 @@ def test_select_specific_grandchildren(self): children, ) - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_children_and_grandchildren(self): children = set([ self.child1, @@ -120,39 +115,9 @@ def test_prior_select_related(self): "inheritancemanagertestchild2").get(pk=self.child1.pk) obj.inheritancemanagertestchild1 - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_version_determining_any_depth(self): self.assertIsNone(self.get_manager().all()._get_maximum_depth()) - @skipUnless(django.VERSION < (1, 6, 0), "test only applies to Django < 1.6") - def test_version_determining_only_child_depth(self): - self.assertEqual(1, self.get_manager().all()._get_maximum_depth()) - - @skipUnless(django.VERSION < (1, 6, 0), "test only applies to Django < 1.6") - def test_manually_specifying_parent_fk_only_children(self): - """ - given a Model which inherits from another Model, but also declares - the OneToOne link manually using `related_name` and `parent_link`, - ensure that the relation names and subclasses are obtained correctly. - """ - child3 = InheritanceManagerTestChild3.objects.create() - results = InheritanceManagerTestParent.objects.all().select_subclasses() - - expected_objs = [self.child1, self.child2, - InheritanceManagerTestChild1(pk=self.grandchild1.pk), - InheritanceManagerTestChild1(pk=self.grandchild1_2.pk), - child3] - self.assertEqual(list(results), expected_objs) - - expected_related_names = [ - 'inheritancemanagertestchild1', - 'inheritancemanagertestchild2', - 'manual_onetoone', # this was set via parent_link & related_name - ] - self.assertEqual(set(results.subclasses), - set(expected_related_names)) - - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_manually_specifying_parent_fk_including_grandchildren(self): """ given a Model which inherits from another Model, but also declares @@ -267,7 +232,6 @@ def test_select_subclass_by_child_model(self): self.assertEqual(objs.subclasses, objsmodels.subclasses) self.assertEqual(list(objs), list(objsmodels)) - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_select_subclass_by_grandchild_model(self): """ Confirm that passing a grandchild model works the same as passing the @@ -281,7 +245,6 @@ def test_select_subclass_by_grandchild_model(self): self.assertEqual(objs.subclasses, objsmodels.subclasses) self.assertEqual(list(objs), list(objsmodels)) - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_selecting_all_subclasses_specifically_grandchildren(self): """ A bare select_subclasses() should achieve the same results as doing @@ -310,16 +273,11 @@ def test_selecting_all_subclasses_specifically_children(self): """ objs = InheritanceManagerTestParent.objects.select_subclasses().order_by('pk') - if django.VERSION >= (1, 6, 0): - models = (InheritanceManagerTestChild1, - InheritanceManagerTestChild2, - InheritanceManagerTestChild3, - InheritanceManagerTestGrandChild1, - InheritanceManagerTestGrandChild1_2) - else: - models = (InheritanceManagerTestChild1, - InheritanceManagerTestChild2, - InheritanceManagerTestChild3) + models = (InheritanceManagerTestChild1, + InheritanceManagerTestChild2, + InheritanceManagerTestChild3, + InheritanceManagerTestGrandChild1, + InheritanceManagerTestGrandChild1_2) objsmodels = InheritanceManagerTestParent.objects.select_subclasses( *models).order_by('pk') @@ -353,7 +311,6 @@ def test_select_subclass_invalid_related_model(self): InheritanceManagerTestParent.objects.select_subclasses( TimeFrame).order_by('pk') - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_mixing_strings_and_classes_with_grandchildren(self): """ Given arguments consisting of both strings and model classes, @@ -414,7 +371,6 @@ def test_duplications(self): InheritanceManagerTestParent(pk=self.grandchild1_2.pk), ]) - @skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+") def test_child_doesnt_accidentally_get_parent(self): """ Given a Child model which also has an InheritanceManager, diff --git a/model_utils/tests/test_miscellaneous.py b/model_utils/tests/test_miscellaneous.py index 8b1df054..2f34fbb9 100644 --- a/model_utils/tests/test_miscellaneous.py +++ b/model_utils/tests/test_miscellaneous.py @@ -1,20 +1,12 @@ from __future__ import unicode_literals -import django -from django.db.models.fields import FieldDoesNotExist from django.core.management import call_command from django.test import TestCase from model_utils.fields import get_excerpt -from model_utils.tests.models import ( - Article, - StatusFieldDefaultFilled, -) -from model_utils.tests.helpers import skipUnless class MigrationsTests(TestCase): - @skipUnless(django.VERSION >= (1, 7, 0), "test only applies to Django 1.7+") def test_makemigrations(self): call_command('makemigrations', dry_run=True) @@ -35,26 +27,3 @@ def test_middle_of_para(self): def test_middle_of_line(self): e = get_excerpt("some text more text") self.assertEqual(e, "some text more text") - -try: - from south.modelsinspector import introspector -except ImportError: - introspector = None - - -@skipUnless(introspector, 'South is not installed') -class SouthFreezingTests(TestCase): - def test_introspector_adds_no_excerpt_field(self): - mf = Article._meta.get_field('body') - args, kwargs = introspector(mf) - self.assertEqual(kwargs['no_excerpt_field'], 'True') - - def test_no_excerpt_field_works(self): - from .models import NoRendered - with self.assertRaises(FieldDoesNotExist): - NoRendered._meta.get_field('_body_excerpt') - - def test_status_field_no_check_for_status(self): - sf = StatusFieldDefaultFilled._meta.get_field('status') - args, kwargs = introspector(sf) - self.assertEqual(kwargs['no_check_for_status'], 'True') diff --git a/model_utils/tests/test_models/__init__.py b/model_utils/tests/test_models/__init__.py index 6a0970bb..e69de29b 100644 --- a/model_utils/tests/test_models/__init__.py +++ b/model_utils/tests/test_models/__init__.py @@ -1,5 +0,0 @@ -# Needed for Django 1.4/1.5 test runner -from .test_softdeletable_model import * -from .test_status_model import * -from .test_timeframed_model import * -from .test_timestamped_model import * diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py deleted file mode 100644 index b023badc..00000000 --- a/model_utils/tests/tests.py +++ /dev/null @@ -1,9 +0,0 @@ -import django - -# Needed for Django 1.4/1.5 test runner -if django.VERSION < (1, 6): - from .test_fields import * - from .test_managers import * - from .test_models import * - from .test_choices import * - from .test_miscellaneous import * diff --git a/setup.py b/setup.py index d894b58e..5a4e3304 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ def get_version(root_path): author_email='carl@oddbird.net', url='https://github.com/carljm/django-model-utils/', packages=find_packages(), - install_requires=['Django>=1.4.2'], + install_requires=['Django>=1.8'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', @@ -47,7 +47,7 @@ def get_version(root_path): 'Framework :: Django', ], zip_safe=False, - tests_require=["Django>=1.4.2"], + tests_require=['Django>=1.8'], test_suite='runtests.runtests', package_data={ 'model_utils': [ diff --git a/tox.ini b/tox.ini index 6ce334ef..089f2119 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,12 @@ [tox] envlist = - py26-django{14,15,16}, - py27-django{14,19,110,_trunk}, py27-django15_nosouth, - py{27,33}-django{15,16,17,18}, - py34-django{17,18,19,110,_trunk}, + py27-django{18,19,110,_trunk}, + py33-django{18}, + py34-django{18,19,110,_trunk}, py35-django{18,19,110,_trunk}, [testenv] basepython = - py26: python2.6 py27: python2.7 py33: python3.3 py34: python3.4 @@ -16,15 +14,10 @@ basepython = deps = coverage == 3.6 - django14: Django>=1.4,<1.5 - django15{,_nosouth}: Django>=1.5,<1.6 - django16: Django>=1.6,<1.7 - django17: Django>=1.7,<1.8 django18: Django>=1.8,<1.9 django19: Django>=1.9,<1.10 django110: Django>=1.10,<1.11 django_trunk: https://github.com/django/django/tarball/master - django{14,15,16}: South==1.0.2 freezegun == 0.3.8 commands = coverage run -a setup.py test