Skip to content

Commit

Permalink
Merge pull request #452 from Djailla/django31
Browse files Browse the repository at this point in the history
Add support for Django 3.1
  • Loading branch information
chrisglass committed Aug 14, 2020
2 parents eed4e9f + 7f248bd commit 8ae64d1
Show file tree
Hide file tree
Showing 18 changed files with 44 additions and 111 deletions.
34 changes: 20 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,38 @@ addons:
matrix:
fast_finish: true
include:
# Django 1.11: Python 2.7, 3.5, or 3.6
- { env: TOXENV=py27-django111, python: 2.7 }
- { env: TOXENV=py35-django111, python: 3.5 }
- { env: TOXENV=py36-django111, python: 3.6 }
- { env: TOXENV=py36-django111-postgres DB=postgres, python: 3.6 }
# Django 2.0: Python 3.5, or 3.6
- { env: TOXENV=py35-django20, python: 3.5 }
- { env: TOXENV=py36-django20, python: 3.6 }
- { env: TOXENV=py36-django20-postgres DB=postgres, python: 3.6 }
# Django 2.1: Python 3.6, or 3.7
# Django 2.1: Python 3.5, 3.6, or 3.7
- { env: TOXENV=py35-django21, python: 3.5 }
- { env: TOXENV=py36-django21, python: 3.6 }
- { env: TOXENV=py37-django21, python: 3.7 }
- { env: TOXENV=py37-django21-postgres DB=postgres, python: 3.7 }
# Django 2.2: Python 3.6, or 3.7
# Django 2.2: Python 3.5, 3.6, 3.7 or 3.8
- { env: TOXENV=py35-django22, python: 3.5 }
- { env: TOXENV=py36-django22, python: 3.6 }
- { env: TOXENV=py37-django22, python: 3.7 }
- { env: TOXENV=py37-django22-postgres DB=postgres, python: 3.7 }
- { env: TOXENV=py38-django22, python: 3.8 }
- { env: TOXENV=py38-django22-postgres DB=postgres, python: 3.8 }
# Django 3.0: Python 3.6, 3.7 or 3.8
- { env: TOXENV=py36-django30, python: 3.6 }
- { env: TOXENV=py37-django30, python: 3.7 }
- { env: TOXENV=py38-django30, python: 3.8 }
- { env: TOXENV=py38-django30-postgres DB=postgres, python: 3.8 }
# Django 3.1: Python 3.6, 3.7 or 3.8
- { env: TOXENV=py36-django31, python: 3.6 }
- { env: TOXENV=py37-django31, python: 3.7 }
- { env: TOXENV=py38-django31, python: 3.8 }
- { env: TOXENV=py38-django31-postgres DB=postgres, python: 3.8 }
# Django development master (direct from GitHub source):
- { env: TOXENV=py36-djangomaster, python: 3.6 }
- { env: TOXENV=py37-djangomaster, python: 3.7 }
- { env: TOXENV=py37-djangomaster-postgres DB=postgres, python: 3.7 }
- { env: TOXENV=py38-djangomaster, python: 3.8 }
- { env: TOXENV=py38-djangomaster-postgres DB=postgres, python: 3.8 }

allow_failures:
- env: TOXENV=py36-djangomaster
- env: TOXENV=py37-djangomaster
- env: TOXENV=py37-djangomaster-postgres DB=postgres
- env: TOXENV=py38-djangomaster
- env: TOXENV=py38-djangomaster-postgres DB=postgres

cache:
directories:
Expand Down
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ Django to perform an ``INNER JOIN`` to fetch the model fields from the database.
While taking this in mind, there are valid reasons for using subclassed models.
That's what this library is designed for!

The current release of *django-polymorphic* supports Django 1.11, 2.0, 2.1, 2.2 and Python 2.7 and 3.5+ is supported.
The current release of *django-polymorphic* supports Django 2.1, 2.2, 3.0, 3.1
and Python 3.5+ is supported.
For older Django versions, install *django-polymorphic==1.3*.

For more information, see the `documentation at Read the Docs <https://django-polymorphic.readthedocs.io/>`_.
Expand Down
1 change: 0 additions & 1 deletion docs/migrating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ can be included in a single Django migration. For example:
.. code-block:: python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
Expand Down
3 changes: 0 additions & 3 deletions example/orders/models.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from django.db import models
from django.utils.dates import MONTHS_3
from django.utils.six import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _

from polymorphic.models import PolymorphicModel


@python_2_unicode_compatible
class Order(models.Model):
"""
An example order that has polymorphic relations
Expand All @@ -23,7 +21,6 @@ def __str__(self):
return self.title


@python_2_unicode_compatible
class Payment(PolymorphicModel):
"""
A generic payment model.
Expand Down
18 changes: 3 additions & 15 deletions polymorphic/admin/parentadmin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""
The parent admin displays the list view of the base model.
"""
import sys

from django.contrib import admin
from django.contrib.admin.helpers import AdminErrorList, AdminForm
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
Expand All @@ -11,6 +9,7 @@
from django.db import models
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import URLResolver
from django.utils.encoding import force_text
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
Expand All @@ -20,17 +19,6 @@

from .forms import PolymorphicModelChoiceForm

try:
# Django 2.0+
from django.urls import URLResolver
except ImportError:
# Django < 2.0
from django.urls import RegexURLResolver as URLResolver


if sys.version_info[0] >= 3:
long = int


class RegistrationClosed(RuntimeError):
"The admin model can't be registered anymore at this point."
Expand Down Expand Up @@ -293,9 +281,9 @@ def subclass_view(self, request, path):
try:
pos = path.find("/")
if pos == -1:
object_id = long(path)
object_id = int(path)
else:
object_id = long(path[0:pos])
object_id = int(path[0:pos])
except ValueError:
raise Http404(
"No ct_id parameter, unable to find admin subclass for path '{0}'.".format(
Expand Down
2 changes: 0 additions & 2 deletions polymorphic/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"""
PolymorphicModel Meta Class
"""
from __future__ import absolute_import

import inspect
import os
import sys
Expand Down
37 changes: 0 additions & 37 deletions polymorphic/compat.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,8 @@
"""Compatibility with Python 2 (taken from 'django.utils.six')"""
import sys

PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3


if PY3:
string_types = (str,)
integer_types = (int,)
class_types = (type,)
text_type = str
binary_type = bytes

MAXSIZE = sys.maxsize
else:
string_types = (basestring,)
integer_types = (int, long)


def with_metaclass(meta, *bases):
class metaclass(type):
def __new__(cls, name, this_bases, d):
return meta(name, bases, d)

return type.__new__(metaclass, "temporary_class", (), {})


def python_2_unicode_compatible(klass):
"""
A decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.
To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
"""
if PY2:
if "__str__" not in klass.__dict__:
raise ValueError(
"@python_2_unicode_compatible cannot be applied "
"to %s because it doesn't define __str__()." % klass.__name__
)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode("utf-8")
return klass
2 changes: 0 additions & 2 deletions polymorphic/contrib/extra_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
This package provides classes that support both options for polymorphic formsets.
"""
from __future__ import absolute_import

import extra_views
from django.core.exceptions import ImproperlyConfigured

Expand Down
3 changes: 0 additions & 3 deletions polymorphic/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@
"""
The manager class for use in the models.
"""
from __future__ import unicode_literals

from django.db import models

from polymorphic.compat import python_2_unicode_compatible
from polymorphic.query import PolymorphicQuerySet

__all__ = ("PolymorphicManager", "PolymorphicQuerySet")


@python_2_unicode_compatible
class PolymorphicManager(models.Manager):
"""
Manager for PolymorphicModel
Expand Down
2 changes: 0 additions & 2 deletions polymorphic/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"""
Seamless Polymorphic Inheritance for Django Models
"""
from __future__ import absolute_import

from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models.fields.related import (
Expand Down
6 changes: 2 additions & 4 deletions polymorphic/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
"""
QuerySet for PolymorphicModel
"""
from __future__ import absolute_import

import copy
from collections import defaultdict

from django.contrib.contenttypes.models import ContentType
from django.db.models import FieldDoesNotExist
from django.core.exceptions import FieldDoesNotExist
from django.db.models.query import ModelIterable, Q, QuerySet

from . import compat
Expand Down Expand Up @@ -177,7 +175,7 @@ def order_by(self, *field_names):
"""translate the field paths in the args, then call vanilla order_by."""
field_names = [
translate_polymorphic_field_path(self.model, a)
if isinstance(a, compat.string_types)
if isinstance(a, str)
else a # allow expressions to pass unchanged
for a in field_names
]
Expand Down
8 changes: 3 additions & 5 deletions polymorphic/query_translate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
"""
PolymorphicQuerySet support functions
"""
from __future__ import absolute_import

import copy
from collections import deque

from django.apps import apps
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldError
from django.core.exceptions import FieldError, FieldDoesNotExist
from django.db import models
from django.db.models import Q
from django.db.models.fields.related import ForeignObjectRel, RelatedField
Expand Down Expand Up @@ -144,7 +142,7 @@ def translate_polymorphic_field_path(queryset_model, field_path):
into modela__modelb__modelc__field3.
Returns: translated path (unchanged, if no translation needed)
"""
if not isinstance(field_path, compat.string_types):
if not isinstance(field_path, str):
raise ValueError("Expected field name as string: {0}".format(field_path))

classname, sep, pure_field_path = field_path.partition("___")
Expand Down Expand Up @@ -189,7 +187,7 @@ def translate_polymorphic_field_path(queryset_model, field_path):
# Can also test whether the field exists in the related object to avoid ambiguity between
# class names and field names, but that never happens when your class names are in CamelCase.
return field_path # No exception raised, field does exist.
except models.FieldDoesNotExist:
except FieldDoesNotExist:
pass

submodels = _get_all_sub_models(queryset_model)
Expand Down
4 changes: 1 addition & 3 deletions polymorphic/showfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
from django.db import models

from . import compat
from .compat import python_2_unicode_compatible

RE_DEFERRED = re.compile("_Deferred_.*")


@python_2_unicode_compatible
class ShowFieldBase(object):
""" base class for the ShowField... model mixins, does the work """

Expand Down Expand Up @@ -42,7 +40,7 @@ def _showfields_get_content(self, field_name, field_type=type(None)):
out += content.__class__.__name__
elif issubclass(field_type, models.ManyToManyField):
out += "%d" % content.count()
elif isinstance(content, compat.integer_types):
elif isinstance(content, int):
out += str(content)
elif content is None:
out += "None"
Expand Down
2 changes: 1 addition & 1 deletion polymorphic/templatetags/polymorphic_admin_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def render(self, context):
# Instead, have an assignment tag that inserts that in the template.
base_opts = self.base_opts.resolve(context)
new_vars = {}
if base_opts and not isinstance(base_opts, compat.string_types):
if base_opts and not isinstance(base_opts, str):
new_vars = {
"app_label": base_opts.app_label, # What this is all about
"opts": base_opts,
Expand Down
2 changes: 0 additions & 2 deletions polymorphic/tests/test_multidb.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import print_function

from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.test import TestCase
Expand Down
9 changes: 2 additions & 7 deletions polymorphic/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import sys

from django.contrib.contenttypes.models import ContentType
from django.db import DEFAULT_DB_ALIAS

Expand Down Expand Up @@ -59,12 +57,9 @@ def sort_by_subclass(*classes):
"""
Sort a series of models by their inheritance order.
"""
if sys.version_info[0] == 2:
return sorted(classes, cmp=_compare_mro)
else:
from functools import cmp_to_key
from functools import cmp_to_key

return sorted(classes, key=cmp_to_key(_compare_mro))
return sorted(classes, key=cmp_to_key(_compare_mro))


def get_base_polymorphic_model(ChildModel, allow_abstract=False):
Expand Down
7 changes: 4 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Web Environment
Framework :: Django
Framework :: Django :: 1.11
Framework :: Django :: 2.0
Framework :: Django :: 2.1
Framework :: Django :: 2.2
Framework :: Django :: 3.0
Framework :: Django :: 3.1
Intended Audience :: Developers
License :: OSI Approved :: BSD License
Operating System :: OS Independent
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Topic :: Database

[options]
Expand Down
12 changes: 6 additions & 6 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[tox]
envlist =
py27-django{111}
py35-django{111,20}
py36-django{111,20,21,22,master}
py37-django{21,22,master}
py35-django{21,22,master}
py36-django{21,22,30,31,master}
py37-django{21,22,30,31,master}
py38-django{21,22,30,31,master}
docs

[testenv]
Expand All @@ -14,10 +14,10 @@ setenv =
deps =
coverage
dj-database-url
django111: Django >= 1.11, < 2.0
django20: Django ~= 2.0
django21: Django ~= 2.1
django22: Django ~= 2.2
django30: Django ~= 3.0
django31: Django ~= 3.1
djangomaster: https://github.com/django/django/archive/master.tar.gz
postgres: psycopg2
commands =
Expand Down

0 comments on commit 8ae64d1

Please sign in to comment.