Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare for Django 2.0 #320

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ env:
- DJANGO="Django>=1.9,<1.10"
- DJANGO="Django>=1.10,<1.11"
- DJANGO="Django>=1.11,<1.12"
- DJANGO="Django>=2.0,<2.1"

install:
- pip install -U coverage codecov
Expand All @@ -42,5 +43,9 @@ matrix:
env: DJANGO="Django>=1.10,<1.11"
- python: 3.3
env: DJANGO="Django>=1.11,<1.12"
- python: 2.7
env: DJANGO="Django>=2.0,<2.1"
- python: 3.3
env: DJANGO="Django>=2.0,<2.1"

after_success: codecov
3 changes: 3 additions & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ Authors
- Brian Dixon
- Corey Bertram
- Damien Nozay
- Daniel Gilge
- Daniel Levy
- Daniel Roschka
- David Hite
- Eduardo Cuducos
- Florian Eßer
- George Vilches
- Grzegorz Bialy
- Hamish Downer
Expand All @@ -33,6 +35,7 @@ Authors
- Rod Xavier Bondoc
- Ross Lote
- Ross Mechanic
- Ross Rogers
- Steven Klass
- Steeve Chailloux
- Trey Hunner
Expand Down
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Unreleased
- Use get_queryset rather than model.objects in history_view. (gh-303)
- Change ugettext calls in models.py to ugettext_lazy
- Resolve issue where model references itself (gh-278)
- Add Django 2.0 support

1.9.0 (2017-06-11)
------------------
Expand Down
19 changes: 14 additions & 5 deletions runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

import django
from django.conf import settings
try:
from django.utils.version import get_complete_version
except ImportError:
get_complete_version = lambda: django.VERSION

sys.path.insert(0, abspath(dirname(__file__)))

Expand Down Expand Up @@ -38,11 +42,6 @@
'ENGINE': 'django.db.backends.sqlite3',
}
},
MIDDLEWARE_CLASSES=[
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
],
TEMPLATES=[{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
Expand All @@ -54,6 +53,16 @@
}],
)

MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
]
if get_complete_version() >= (1, 10):
DEFAULT_SETTINGS['MIDDLEWARE'] = MIDDLEWARE
else:
DEFAULT_SETTINGS['MIDDLEWARE_CLASSES'] = MIDDLEWARE


def main():

Expand Down
5 changes: 4 additions & 1 deletion simple_history/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
from django.contrib import admin
from django.contrib.admin import helpers
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404, render
from django.utils.text import capfirst
from django.utils.html import mark_safe
from django.utils.translation import ugettext as _
from django.utils.encoding import force_text
from django.conf import settings

try:
from django.urls import reverse
except ImportError: # Django < 1.10
from django.core.urlresolvers import reverse
try:
from django.contrib.admin.utils import unquote
except ImportError: # Django < 1.7
Expand Down
23 changes: 18 additions & 5 deletions simple_history/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,17 @@ def copy_fields(self, model):
# If old_field.rel.to is 'self' then we have a case where object has a foreign key
# to itself. In this case we update need to set the `to` value of the field
# to be set to a model. We can use the old_field.model value.
if isinstance(old_field.rel.to, str) and old_field.rel.to == 'self':
try:
old_remote_field = old_field.remote_field
except AttributeError: # Django < 1.9
old_remote_field = old_field.rel
if isinstance(old_remote_field, str) and old_remote_field == 'self':
object_to = old_field.model
else:
object_to = old_field.rel.to
try:
object_to = old_remote_field.model
except AttributeError: # Django < 1.8
object_to = old_remote_field.to

field = FieldType(
object_to,
Expand Down Expand Up @@ -284,11 +291,17 @@ def get_history_user(self, instance):
return instance._history_user
except AttributeError:
try:
if self.thread.request.user.is_authenticated():
return self.thread.request.user
return None
user = self.thread.request.user
except AttributeError:
return None
if user.is_authenticated is True:
return user
try: # Django < 2.0
if user.is_authenticated():
return user
except TypeError:
pass
return None


def transform_field(field):
Expand Down
2 changes: 1 addition & 1 deletion simple_history/registry_tests/migration_test_app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ class WhatIMean(DoYouKnow):


class Yar(models.Model):
what = models.ForeignKey(WhatIMean)
what = models.ForeignKey(WhatIMean, on_delete=models.CASCADE)
history = HistoricalRecords()
9 changes: 8 additions & 1 deletion simple_history/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class Voter(models.Model):
related_name='voters',
)

def __str__(self):
return 'Voter object'


class HistoricalRecordsVerbose(HistoricalRecords):
def get_extra_fields(self, model, fields):
Expand Down Expand Up @@ -287,7 +290,11 @@ class UserAccessorOverride(models.Model):


class Employee(models.Model):
manager = models.OneToOneField('Employee', null=True)
manager = models.OneToOneField(
'Employee',
on_delete=models.CASCADE,
null=True,
)
history = HistoricalRecords()


Expand Down
27 changes: 18 additions & 9 deletions simple_history/tests/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from django.contrib.messages.storage.fallback import FallbackStorage
from django.test.utils import override_settings
from django.test.client import RequestFactory
from django.core.urlresolvers import reverse
from django.conf import settings
from django.contrib.auth import get_user_model
from django.utils.encoding import force_text
Expand All @@ -19,7 +18,17 @@
from django.contrib.admin.utils import quote
except ImportError: # Django < 1.7
from django.contrib.admin.util import quote
try:
from django.urls import reverse
except ImportError: # Django < 1.10
from django.core.urlresolvers import reverse

try:
settings.MIDDLEWARE
except AttributeError: # Django < 1.10
MIDDLEWARE_SETTING = 'MIDDLEWARE_CLASSES'
else:
MIDDLEWARE_SETTING = 'MIDDLEWARE'
User = get_user_model()
today = datetime(2021, 1, 1, 10, 0)
tomorrow = today + timedelta(days=1)
Expand Down Expand Up @@ -201,8 +210,8 @@ def test_history_user_not_saved(self):

def test_middleware_saves_user(self):
overridden_settings = {
'MIDDLEWARE_CLASSES':
settings.MIDDLEWARE_CLASSES +
MIDDLEWARE_SETTING:
getattr(settings, MIDDLEWARE_SETTING) +
['simple_history.middleware.HistoryRequestMiddleware'],
}
with override_settings(**overridden_settings):
Expand All @@ -219,8 +228,8 @@ def test_middleware_saves_user(self):

def test_middleware_unsets_request(self):
overridden_settings = {
'MIDDLEWARE_CLASSES':
settings.MIDDLEWARE_CLASSES +
MIDDLEWARE_SETTING:
getattr(settings, MIDDLEWARE_SETTING) +
['simple_history.middleware.HistoryRequestMiddleware'],
}
with override_settings(**overridden_settings):
Expand All @@ -234,8 +243,8 @@ def test_rolled_back_user_does_not_lead_to_foreign_key_error(self):
# creating a new entry does not fail with a foreign key error.

overridden_settings = {
'MIDDLEWARE_CLASSES':
settings.MIDDLEWARE_CLASSES +
MIDDLEWARE_SETTING:
getattr(settings, MIDDLEWARE_SETTING) +
['simple_history.middleware.HistoryRequestMiddleware'],
}
with override_settings(**overridden_settings):
Expand All @@ -256,8 +265,8 @@ def test_rolled_back_user_does_not_lead_to_foreign_key_error(self):

def test_middleware_anonymous_user(self):
overridden_settings = {
'MIDDLEWARE_CLASSES':
settings.MIDDLEWARE_CLASSES +
MIDDLEWARE_SETTING:
getattr(settings, MIDDLEWARE_SETTING) +
['simple_history.middleware.HistoryRequestMiddleware'],
}
with override_settings(**overridden_settings):
Expand Down
35 changes: 28 additions & 7 deletions simple_history/tests/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import unicode_literals

import mock
import unittest
import warnings
from datetime import datetime, timedelta
Expand Down Expand Up @@ -190,7 +191,11 @@ def test_foreignkey_still_allows_reverse_lookup_via_set_attribute(self):
lib = Library.objects.create()
state = State.objects.create(library=lib)
self.assertTrue(hasattr(lib, 'state_set'))
self.assertIsNone(state._meta.get_field('library').rel.related_name,
try:
remote_related_name = state._meta.get_field('library').remote_field.related_name
except AttributeError: # Django < 1.9
remote_related_name = state._meta.get_field('library').rel.related_name
self.assertIsNone(remote_related_name,
"the '+' shouldn't leak through to the original "
"model's field related_name")

Expand Down Expand Up @@ -343,6 +348,16 @@ def test_model_with_excluded_fields(self):
self.assertIn('question', all_fields_names)
self.assertNotIn('pub_date', all_fields_names)

def test_get_history_user(self):
poll = Poll()
historical_records = HistoricalRecords()
historical_records.thread = mock.Mock()
test_user = User()
historical_records.thread.request.user = test_user

self.assertRaises(AttributeError, lambda: poll._history_user)
self.assertEquals(historical_records.get_history_user(poll), test_user)


class CreateHistoryModelTests(unittest.TestCase):

Expand Down Expand Up @@ -515,17 +530,23 @@ def test_invalid_bases(self):
def test_import_related(self):
field_object = HistoricalChoice._meta.get_field('poll')
try:
related_model = field_object.rel.related_model
except AttributeError: # Django<1.8
related_model = field_object.related.model
related_model = field_object.remote_field.related_model
except AttributeError: # Django < 1.9
try:
related_model = field_object.rel.related_model
except AttributeError: # Django < 1.8
related_model = field_object.related.model
self.assertEqual(related_model, HistoricalChoice)

def test_string_related(self):
field_object = HistoricalState._meta.get_field('library')
try:
related_model = field_object.rel.related_model
except AttributeError: # Django<1.8
related_model = field_object.related.model
related_model = field_object.remote_field.related_model
except AttributeError: # Django < 1.9
try:
related_model = field_object.rel.related_model
except AttributeError: # Django < 1.8
related_model = field_object.related.model
self.assertEqual(related_model, HistoricalState)

@unittest.skipUnless(django.get_version() >= "1.7",
Expand Down
6 changes: 3 additions & 3 deletions simple_history/tests/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from __future__ import unicode_literals

from django.conf.urls import include, url
from django.conf.urls import url
from django.contrib import admin
from . import other_admin

admin.autodiscover()

urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^other-admin/', include(other_admin.site.urls)),
url(r'^admin/', admin.site.urls),
url(r'^other-admin/', other_admin.site.urls),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the omission of function include backwards compatible? All other edits seem backwards compatibility except maybe this one.

Copy link
Contributor

@dgilge dgilge Dec 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests passed using tox.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect.

]
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ envlist =
py{27,34,35}-django19,
py{27,34,35,36}-django110,
py{27,34,35,36}-django111,
py{34,35,36}-django20,
py{35,36}-djangotrunk,
docs, flake8

Expand Down Expand Up @@ -37,6 +38,7 @@ deps =
django19: Django>=1.9,<1.10
django110: Django>=1.10,<1.11
django111: Django>=1.11,<1.12
django20: Django>=2.0,<2.1
djangotrunk: https://github.com/django/django/tarball/master
commands =
coverage run -a --branch setup.py test