Skip to content

Commit

Permalink
Merge pull request #643 from jdufresne/old-dj
Browse files Browse the repository at this point in the history
Remove support for EOL Django 1.8 and Python 3.3
  • Loading branch information
craigds committed Apr 15, 2018
2 parents 631a530 + b18933b commit bc871e8
Show file tree
Hide file tree
Showing 17 changed files with 41 additions and 135 deletions.
10 changes: 0 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,19 @@ python:
- "3.6"
- "3.5"
- "3.4"
- "3.3"
- "2.7"

env:
- DJANGO="Django>=1.8,<1.9"
- DJANGO="Django>=1.11,<2.0"
- DJANGO="Django>=2.0,<2.1"
- DJANGO="https://github.com/django/django/archive/master.tar.gz"

matrix:
exclude:
- env: DJANGO="Django>=1.8,<1.9"
python: "3.5"
- env: DJANGO="Django>=1.11,<2.0"
python: "3.3"
- env: DJANGO="Django>=2.0,<2.1"
python: "2.7"
- env: DJANGO="Django>=2.0,<2.1"
python: "3.3"
- env: DJANGO="https://github.com/django/django/archive/master.tar.gz"
python: "2.7"
- env: DJANGO="https://github.com/django/django/archive/master.tar.gz"
python: "3.3"
- env: DJANGO="https://github.com/django/django/archive/master.tar.gz"
python: "3.4"
allow_failures:
Expand Down
2 changes: 1 addition & 1 deletion INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ PYTHONPATH; this is useful if you're working from a git checkout.

Requires:
- Python 2.7 or newer
- Django 1.8 or newer
- Django 1.11 or newer

You can obtain Python from https://www.python.org/ and Django from
https://www.djangoproject.com/
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ structure and provides tools for working with trees of model instances.
Requirements
------------

* Python 2.7 or 3.3+
* A supported version of Django (currently 1.8+)
* Python 2.7 or 3.4+
* A supported version of Django (currently 1.11+)

Feature overview
----------------
Expand Down
2 changes: 1 addition & 1 deletion docs/admin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ to ``20``)::
# ...


.. _overriding admin templates: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#overriding-admin-templates
.. _overriding admin templates: https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#overriding-admin-templates
.. _FeinCMS: https://github.com/feincms/feincms/


Expand Down
6 changes: 6 additions & 0 deletions docs/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Upgrade notes
=============

UNRELASED
=========

End of life Python 3.3 and Django 1.8 are no longer supported. These versions
of Python and Django no longer receive security patches.

0.9.0
=====

Expand Down
17 changes: 6 additions & 11 deletions mptt/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

from js_asset import JS

from mptt.compat import remote_field, remote_model
from mptt.exceptions import InvalidMove
from mptt.forms import MPTTAdminForm, TreeNodeChoiceField
from mptt.models import MPTTModel, TreeForeignKey
Expand All @@ -45,15 +44,15 @@ class MPTTModelAdmin(ModelAdmin):
form = MPTTAdminForm

def formfield_for_foreignkey(self, db_field, request, **kwargs):
if issubclass(remote_model(db_field), MPTTModel) \
if issubclass(db_field.remote_field.model, MPTTModel) \
and not isinstance(db_field, TreeForeignKey) \
and db_field.name not in self.raw_id_fields:
db = kwargs.get('using')

limit_choices_to = db_field.get_limit_choices_to()
defaults = dict(
form_class=TreeNodeChoiceField,
queryset=remote_model(db_field)._default_manager.using(
queryset=db_field.remote_field.model._default_manager.using(
db).complex_filter(limit_choices_to),
required=False)
defaults.update(kwargs)
Expand Down Expand Up @@ -271,8 +270,8 @@ class MyModelAdmin(admin.ModelAdmin):

def __init__(self, field, request, params, model, model_admin, field_path):
self.other_model = get_model_from_relation(field)
if remote_field(field) is not None and hasattr(remote_field(field), 'get_related_field'):
self.rel_name = remote_field(field).get_related_field().name
if field.remote_field is not None and hasattr(field.remote_field, 'get_related_field'):
self.rel_name = field.remote_field.get_related_field().name
else:
self.rel_name = self.other_model._meta.pk.name
self.changed_lookup_kwarg = '%s__%s__inhierarchy' % (field_path, self.rel_name)
Expand Down Expand Up @@ -320,11 +319,7 @@ def field_choices(self, field, request, model_admin):
# yield padding_style
def choices(self, cl):
# #### MPTT ADDITION START
try:
# EMPTY_CHANGELIST_VALUE has been removed in django 1.9
from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
except:
EMPTY_CHANGELIST_VALUE = self.empty_value_display
EMPTY_CHANGELIST_VALUE = self.empty_value_display
# #### MPTT ADDITION END
yield {
'selected': self.lookup_val is None and not self.lookup_val_isnull,
Expand All @@ -344,7 +339,7 @@ def choices(self, cl):
}
if (isinstance(self.field, ForeignObjectRel) and
(self.field.field.null or isinstance(self.field.field, ManyToManyField)) or
remote_field(self.field) is not None and
self.field.remote_field is not None and
(self.field.null or isinstance(self.field, ManyToManyField))):
yield {
'selected': bool(self.lookup_val_isnull),
Expand Down
10 changes: 0 additions & 10 deletions mptt/compat.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
def remote_field(field):
# remote_field is new in Django 1.9
return field.remote_field if hasattr(field, 'remote_field') else getattr(field, 'rel', None)


def remote_model(field):
# remote_field is new in Django 1.9
return field.remote_field.model if hasattr(field, 'remote_field') else field.rel.to


def cached_field_value(instance, attr):
try:
# In Django 2.0, use the new field cache API
Expand Down
6 changes: 3 additions & 3 deletions mptt/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from django.db.models import F, ManyToManyField, Max, Q
from django.utils.translation import ugettext as _

from mptt.compat import cached_field_value, remote_field
from mptt.compat import cached_field_value
from mptt.exceptions import CantDisableUpdates, InvalidMove
from mptt.querysets import TreeQuerySet
from mptt.utils import _get_tree_model
Expand Down Expand Up @@ -483,7 +483,7 @@ def add_related_count(self, queryset, rel_model, rel_field, count_attr,
'rel_table': qn(rel_model._meta.db_table),
'mptt_fk': qn(rel_model._meta.get_field(rel_field).column),
'mptt_table': qn(self.tree_model._meta.db_table),
'mptt_rel_to': qn(remote_field(mptt_field).field_name),
'mptt_rel_to': qn(mptt_field.remote_field.field_name),
'tree_id': qn(meta.get_field(self.tree_id_attr).column),
'left': qn(meta.get_field(self.left_attr).column),
'right': qn(meta.get_field(self.right_attr).column),
Expand All @@ -493,7 +493,7 @@ def add_related_count(self, queryset, rel_model, rel_field, count_attr,
'rel_table': qn(rel_model._meta.db_table),
'mptt_fk': qn(rel_model._meta.get_field(rel_field).column),
'mptt_table': qn(self.tree_model._meta.db_table),
'mptt_rel_to': qn(remote_field(mptt_field).field_name),
'mptt_rel_to': qn(mptt_field.remote_field.field_name),
}
return queryset.extra(select={count_attr: subquery})

Expand Down
14 changes: 3 additions & 11 deletions mptt/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from django.utils import six
from django.utils.translation import ugettext as _

from mptt.compat import cached_field_value, remote_field
from mptt.compat import cached_field_value
from mptt.fields import TreeForeignKey, TreeOneToOneField, TreeManyToManyField
from mptt.managers import TreeManager
from mptt.signals import node_moved
Expand Down Expand Up @@ -360,15 +360,7 @@ def register(meta, cls, **kwargs):
if cls._default_manager and isinstance(cls._default_manager, TreeManager):
tree_manager = cls._default_manager
else:
if hasattr(cls._meta, 'concrete_managers'): # Django < 1.10
# Django < 1.10 doesn't sort managers
cls_managers = sorted(
cls._meta.concrete_managers + cls._meta.abstract_managers)
cls_managers = [r[2] for r in cls_managers]
else:
cls_managers = cls._meta.managers

for cls_manager in cls_managers:
for cls_manager in cls._meta.managers:
if isinstance(cls_manager, TreeManager):
# prefer any locally defined manager (i.e. keep going if not local)
if cls_manager.model is cls:
Expand Down Expand Up @@ -805,7 +797,7 @@ def _is_saved(self, using=None):
if not self.pk or self._mpttfield('tree_id') is None:
return False
opts = self._meta
if remote_field(opts.pk) is None:
if opts.pk.remote_field is None:
return True
else:
if not hasattr(self, '_mptt_saved'):
Expand Down
60 changes: 7 additions & 53 deletions mptt/templatetags/mptt_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import datetime
import warnings

import django
from django.conf import settings
from django.contrib.admin.templatetags.admin_list import (
result_hidden_fields, result_headers)
Expand All @@ -13,10 +12,7 @@
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.template import Library
try:
from django.urls import NoReverseMatch
except ImportError: # Django < 1.10 pragma: no cover
from django.core.urlresolvers import NoReverseMatch
from django.urls import NoReverseMatch
try:
from django.utils.deprecation import RemovedInDjango20Warning
except ImportError:
Expand All @@ -25,8 +21,7 @@
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import get_language_bidi

from mptt.compat import remote_field
from django.contrib.admin.templatetags.admin_list import _coerce_field_name


register = Library()
Expand All @@ -36,29 +31,6 @@
IS_GRAPPELLI_INSTALLED = True if 'grappelli' in settings.INSTALLED_APPS else False


###
# Ripped from contrib.admin (1.10)
def _coerce_field_name(field_name, field_index):
"""
Coerce a field_name (which may be a callable) to a string.
"""
if callable(field_name):
if field_name.__name__ == '<lambda>':
return 'lambda' + str(field_index)
else:
return field_name.__name__
return field_name


def get_empty_value_display(cl):
if hasattr(cl.model_admin, 'get_empty_value_display'):
return cl.model_admin.get_empty_value_display()
else:
# Django < 1.9
from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
return EMPTY_CHANGELIST_VALUE


###
# Ripped from contrib.admin's (1.10) items_for_result tag.
# The only difference is we're indenting nodes according to their level.
Expand Down Expand Up @@ -99,7 +71,7 @@ def link_in_col(is_first, field_name, cl):

for field_index, field_name in enumerate(cl.list_display):
# #### MPTT SUBSTITUTION START
empty_value_display = get_empty_value_display(cl)
empty_value_display = cl.model_admin.get_empty_value_display()
# #### MPTT SUBSTITUTION END
row_classes = ['field-%s' % _coerce_field_name(field_name, field_index)]
try:
Expand All @@ -114,12 +86,7 @@ def link_in_col(is_first, field_name, cl):
allow_tags = getattr(attr, 'allow_tags', False)
boolean = getattr(attr, 'boolean', False)
# #### MPTT SUBSTITUTION START
try:
# Changed in Django 1.9, now takes 3 arguments
result_repr = display_for_value(
value, empty_value_display, boolean)
except TypeError:
result_repr = display_for_value(value, boolean)
result_repr = display_for_value(value, empty_value_display, boolean)
# #### MPTT SUBSTITUTION END
if allow_tags:
warnings.warn(
Expand All @@ -133,7 +100,7 @@ def link_in_col(is_first, field_name, cl):
row_classes.append('nowrap')
else:
# #### MPTT SUBSTITUTION START
is_many_to_one = isinstance(remote_field(f), models.ManyToOneRel)
is_many_to_one = isinstance(f.remote_field, models.ManyToOneRel)
if is_many_to_one:
# #### MPTT SUBSTITUTION END
field_val = getattr(result, f.name)
Expand All @@ -143,12 +110,7 @@ def link_in_col(is_first, field_name, cl):
result_repr = field_val
else:
# #### MPTT SUBSTITUTION START
try:
result_repr = display_for_field(value, f)
except TypeError:
# Changed in Django 1.9, now takes 3 arguments
result_repr = display_for_field(
value, f, empty_value_display)
result_repr = display_for_field(value, f, empty_value_display)
# #### MPTT SUBSTITUTION END
if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
row_classes.append('nowrap')
Expand Down Expand Up @@ -189,15 +151,7 @@ def link_in_col(is_first, field_name, cl):
attr = pk
value = result.serializable_value(attr)
if cl.is_popup:
if django.VERSION < (1, 10):
opener = format_html(
' onclick="opener.dismissRelatedLookupPopup(window, &#39;{}&#39;);'
' return false;"', value
)
else:
opener = format_html(
' data-popup-opener="{}"', value
)
opener = format_html(' data-popup-opener="{}"', value)
else:
opener = ''
link_or_text = format_html(
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Django >= 1.8
Django >= 1.11
django-js-asset
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
packages=find_packages(exclude=['tests', 'tests.*']),
include_package_data=True,
install_requires=[
'Django>=1.11',
'django-js-asset',
],
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*",
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Intended Audience :: Developers',
Expand All @@ -34,7 +34,6 @@
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
Expand Down

0 comments on commit bc871e8

Please sign in to comment.