Skip to content

Commit 1fd2f0e

Browse files
committed
Merge pull request #203 from treyhunner/drop-14
Remove Django 1.4, and Python 2.6 and 3.2 support
2 parents bc630e5 + 879f7c6 commit 1fd2f0e

File tree

9 files changed

+44
-162
lines changed

9 files changed

+44
-162
lines changed

.travis.yml

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,32 @@ sudo: false
44

55
python:
66
- 2.7
7-
- 3.2
87
- 3.3
8+
- 3.4
9+
- 3.5
910

1011
env:
11-
- DJANGO="Django>=1.4,<1.5"
1212
- DJANGO="Django>=1.6,<1.7"
1313
- DJANGO="Django>=1.7,<1.8"
1414
- DJANGO="Django>=1.8,<1.9"
15-
- DJANGO="Django>=1.9a,<1.10"
15+
- DJANGO="Django>=1.9,<1.10"
1616

1717
install:
18-
- pip install -U 'coverage<4' codecov
18+
- pip install -U coverage codecov
1919
- pip install -U $DJANGO
20-
- python -c 'from __future__ import print_function; import django; print("Django " + django.get_version())'
20+
- pip freeze
2121

2222
script: coverage run setup.py test
2323

2424
matrix:
2525
exclude:
26-
- python: 3.2
27-
env: DJANGO="Django>=1.4,<1.5"
28-
- python: 3.3
29-
env: DJANGO="Django>=1.4,<1.5"
30-
- python: 3.2
31-
env: DJANGO="Django>=1.9a,<1.10"
32-
- python: 3.3
33-
env: DJANGO="Django>=1.9a,<1.10"
34-
35-
include:
36-
- python: 2.6
37-
env: DJANGO="Django>=1.4,<1.5"
3826
- python: 3.4
39-
env: DJANGO="Django>=1.7,<1.8"
40-
- python: 3.4
41-
env: DJANGO="Django>=1.8,<1.9"
27+
env: DJANGO="Django>=1.6,<1.7"
4228
- python: 3.5
43-
env: DJANGO="Django>=1.8,<1.9"
29+
env: DJANGO="Django>=1.6,<1.7"
4430
- python: 3.5
31+
env: DJANGO="Django>=1.7,<1.8"
32+
- python: 3.3
4533
env: DJANGO="Django>=1.9,<1.10"
4634

4735
after_success: codecov

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ django-simple-history
2020

2121
django-simple-history stores Django model state on every create/update/delete.
2222

23-
This app requires Django 1.4.2, 1.6, or greater and Python 2.6 or greater.
23+
This app requires Django 1.6 or greater and Python 2.7, 3.3, or greater.
2424

2525
Getting Help
2626
------------

runtests.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from os.path import abspath, dirname, join
44
from shutil import rmtree
55
import sys
6-
import warnings
76

87
import django
98
from django.conf import settings
@@ -14,17 +13,21 @@
1413
rmtree(media_root, ignore_errors=True)
1514

1615
installed_apps = [
16+
'simple_history.tests',
17+
'simple_history.tests.custom_user',
18+
'simple_history.tests.external',
19+
'simple_history.tests.migration_test_app',
20+
21+
'simple_history',
22+
1723
'django.contrib.contenttypes',
1824
'django.contrib.auth',
1925
'django.contrib.sessions',
2026
'django.contrib.admin',
21-
'simple_history',
22-
'simple_history.tests',
23-
'simple_history.tests.external',
24-
'simple_history.tests.migration_test_app',
2527
]
2628

2729
DEFAULT_SETTINGS = dict(
30+
AUTH_USER_MODEL='custom_user.CustomUser',
2831
ROOT_URLCONF='simple_history.tests.urls',
2932
MEDIA_ROOT=media_root,
3033
STATIC_URL='/static/',
@@ -45,9 +48,6 @@
4548
}],
4649
)
4750

48-
if django.VERSION >= (1, 5):
49-
installed_apps.append('simple_history.tests.custom_user')
50-
DEFAULT_SETTINGS['AUTH_USER_MODEL'] = 'custom_user.CustomUser'
5151

5252
def main():
5353
if not settings.configured:

simple_history/admin.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,9 @@
1818
from django.contrib.admin.utils import unquote
1919
except ImportError: # Django < 1.7
2020
from django.contrib.admin.util import unquote
21-
try:
22-
USER_NATURAL_KEY = settings.AUTH_USER_MODEL
23-
except AttributeError: # Django < 1.5
24-
USER_NATURAL_KEY = "auth.User"
2521

26-
USER_NATURAL_KEY = tuple(key.lower() for key in USER_NATURAL_KEY.split('.', 1))
22+
USER_NATURAL_KEY = tuple(
23+
key.lower() for key in settings.AUTH_USER_MODEL.split('.', 1))
2724

2825
SIMPLE_HISTORY_EDIT = getattr(settings, 'SIMPLE_HISTORY_EDIT', False)
2926

@@ -37,10 +34,7 @@ def get_urls(self):
3734
urls = super(SimpleHistoryAdmin, self).get_urls()
3835
admin_site = self.admin_site
3936
opts = self.model._meta
40-
try:
41-
info = opts.app_label, opts.model_name
42-
except AttributeError: # Django < 1.7
43-
info = opts.app_label, opts.module_name
37+
info = opts.app_label, opts.model_name
4438
history_urls = [
4539
url("^([^/]+)/history/([^/]+)/$",
4640
admin_site.admin_view(self.history_form_view),
@@ -149,10 +143,7 @@ def history_form_view(self, request, object_id, version_id):
149143
model_admin=self,
150144
)
151145

152-
try:
153-
model_name = original_opts.model_name
154-
except AttributeError: # Django < 1.7
155-
model_name = original_opts.module_name
146+
model_name = original_opts.model_name
156147
url_triplet = self.admin_site.name, original_opts.app_label, model_name
157148
context = {
158149
'title': _('Revert %s') % force_text(obj),

simple_history/management/commands/_populate_utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ def bulk_history_create(model, history_model):
2121
history_model(
2222
history_date=getattr(instance, '_history_date', now()),
2323
history_user=getattr(instance, '_history_user', None),
24-
**dict((field.attname, getattr(instance, field.attname))
25-
for field in instance._meta.fields)
24+
**{
25+
field.attname: getattr(instance, field.attname)
26+
for field in instance._meta.fields
27+
}
2628
) for instance in model.objects.all()]
2729
history_model.objects.bulk_create(historical_instances)

simple_history/manager.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ def __init__(self, model, instance=None):
2020
self.instance = instance
2121

2222
def get_super_queryset(self):
23-
try:
24-
return super(HistoryManager, self).get_queryset()
25-
except AttributeError: # Django < 1.6
26-
return super(HistoryManager, self).get_query_set()
23+
return super(HistoryManager, self).get_queryset()
2724

2825
def get_queryset(self):
2926
qs = self.get_super_queryset()

simple_history/models.py

Lines changed: 8 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
from __future__ import unicode_literals
22

3-
import threading
43
import copy
5-
import warnings
4+
import importlib
5+
import threading
66

7-
import django
87
from django.db import models, router
98
from django.db.models.fields.proxy import OrderWrt
10-
from django.db.models.fields.related import RelatedField
119
from django.conf import settings
1210
from django.contrib import admin
1311
from django.utils import six
@@ -20,10 +18,6 @@
2018
from django.apps import apps
2119
except ImportError: # Django < 1.7
2220
from django.db.models import get_app
23-
try:
24-
import importlib
25-
except ImportError: # Python < 2.7
26-
from django.utils import importlib
2721
try:
2822
from south.modelsinspector import add_introspection_rules
2923
except ImportError: # south not present
@@ -139,19 +133,14 @@ def copy_fields(self, model):
139133
field.__class__ = models.IntegerField
140134
if isinstance(field, models.ForeignKey):
141135
old_field = field
142-
field_arguments = {}
136+
field_arguments = {'db_constraint': False}
143137
if (getattr(old_field, 'one_to_one', False) or
144138
isinstance(old_field, models.OneToOneField)):
145139
FieldType = models.ForeignKey
146140
else:
147141
FieldType = type(old_field)
148-
if django.get_version() >= "1.6":
149-
field_arguments['db_constraint'] = False
150142
if getattr(old_field, 'to_fields', []):
151143
field_arguments['to_field'] = old_field.to_fields[0]
152-
elif (django.get_version() < "1.6" and
153-
old_field.rel.field_name != 'id'):
154-
field_arguments['to_field'] = old_field.rel.field_name
155144
if getattr(old_field, 'db_column', None):
156145
field_arguments['db_column'] = old_field.db_column
157146
field = FieldType(
@@ -181,17 +170,16 @@ def get_extra_fields(self, model, fields):
181170
def revert_url(self):
182171
"""URL for this change in the default admin site."""
183172
opts = model._meta
184-
try:
185-
app_label, model_name = opts.app_label, opts.model_name
186-
except AttributeError: # Django < 1.7
187-
app_label, model_name = opts.app_label, opts.module_name
173+
app_label, model_name = opts.app_label, opts.model_name
188174
return ('%s:%s_%s_simple_history' %
189175
(admin.site.name, app_label, model_name),
190176
[getattr(self, opts.pk.attname), self.history_id])
191177

192178
def get_instance(self):
193-
return model(**dict([(field.attname, getattr(self, field.attname))
194-
for field in fields.values()]))
179+
return model(**{
180+
field.attname: getattr(self, field.attname)
181+
for field in fields.values()
182+
})
195183

196184
return {
197185
'history_id': models.AutoField(primary_key=True),
@@ -261,81 +249,6 @@ def get_history_user(self, instance):
261249
return None
262250

263251

264-
class CustomForeignKeyField(models.ForeignKey):
265-
266-
def __init__(self, *args, **kwargs):
267-
warnings.warn("CustomForeignKeyField is deprecated.",
268-
DeprecationWarning)
269-
super(CustomForeignKeyField, self).__init__(*args, **kwargs)
270-
self.db_constraint = False
271-
self.generate_reverse_relation = False
272-
273-
def get_attname(self):
274-
return self.name
275-
276-
def get_one_to_one_field(self, to_field, other):
277-
# HACK This creates a new custom foreign key based on to_field,
278-
# and calls itself with that, effectively making the calls
279-
# recursive
280-
temp_field = self.__class__(to_field.rel.to._meta.object_name)
281-
for key, val in to_field.__dict__.items():
282-
if (isinstance(key, six.string_types)
283-
and not key.startswith('_')):
284-
setattr(temp_field, key, val)
285-
field = self.__class__.get_field(
286-
temp_field, other, to_field.rel.to)
287-
return field
288-
289-
def get_field(self, other, cls):
290-
# this hooks into contribute_to_class() and this is
291-
# called specifically after the class_prepared signal
292-
to_field = copy.copy(self.rel.to._meta.pk)
293-
field = self
294-
if isinstance(to_field, models.OneToOneField):
295-
field = self.get_one_to_one_field(to_field, other)
296-
elif isinstance(to_field, models.AutoField):
297-
field.__class__ = convert_auto_field(to_field)
298-
else:
299-
field.__class__ = to_field.__class__
300-
excluded_prefixes = ("_", "__")
301-
excluded_attributes = (
302-
"rel",
303-
"creation_counter",
304-
"validators",
305-
"error_messages",
306-
"attname",
307-
"column",
308-
"help_text",
309-
"name",
310-
"model",
311-
"unique_for_year",
312-
"unique_for_date",
313-
"unique_for_month",
314-
"db_tablespace",
315-
"db_index",
316-
"db_column",
317-
"default",
318-
"auto_created",
319-
"null",
320-
"blank",
321-
)
322-
for key, val in to_field.__dict__.items():
323-
if (isinstance(key, six.string_types)
324-
and not key.startswith(excluded_prefixes)
325-
and key not in excluded_attributes):
326-
setattr(field, key, val)
327-
return field
328-
329-
def do_related_class(self, other, cls):
330-
field = self.get_field(other, cls)
331-
transform_field(field)
332-
field.rel = None
333-
334-
def contribute_to_class(self, cls, name):
335-
# HACK: remove annoying descriptor (don't super())
336-
RelatedField.contribute_to_class(self, cls, name)
337-
338-
339252
def transform_field(field):
340253
"""Customize field appropriately for use in historical model"""
341254
field.name = field.attname

simple_history/tests/tests/test_admin.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@
3131

3232

3333
def get_history_url(obj, history_index=None, site="admin"):
34-
try:
35-
app, model = obj._meta.app_label, obj._meta.module_name
36-
except AttributeError:
37-
app, model = obj._meta.app_label, obj._meta.model_name
34+
app, model = obj._meta.app_label, obj._meta.model_name
3835
if history_index is not None:
3936
history = obj.history.order_by('history_id')[history_index]
4037
return reverse(
@@ -67,12 +64,8 @@ def login(self, user=None):
6764
return form.submit()
6865

6966
def test_history_list(self):
70-
if VERSION >= (1, 5):
71-
try:
72-
module_name = self.user._meta.module_name
73-
except AttributeError:
74-
module_name = self.user._meta.model_name
75-
self.assertEqual(module_name, 'customuser')
67+
model_name = self.user._meta.model_name
68+
self.assertEqual(model_name, 'customuser')
7669
self.login()
7770
poll = Poll(question="why?", pub_date=today)
7871
poll._history_user = self.user
@@ -429,7 +422,8 @@ def test_history_form_view_getting_history(self):
429422
'original_opts': ANY,
430423
'changelist_url': '/admin/tests/poll/',
431424
'change_url': ANY,
432-
'history_url': '/admin/tests/poll/{pk}/history/'.format(pk=poll.pk),
425+
'history_url': '/admin/tests/poll/{pk}/history/'.format(
426+
pk=poll.pk),
433427
'add': False,
434428
'change': True,
435429
'has_add_permission': admin.has_add_permission(request),

tox.ini

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
[tox]
22
envlist =
3-
py{26,27}-django14,
4-
py{26,27,32,33}-django16,
5-
py{27,32,33,34}-django17,
6-
py{27,32,33,34,35}-django18,
3+
py{27,33}-django16,
4+
py{27,33,34}-django17,
5+
py{27,33,34,35}-django18,
76
py{27,34,35}-django19,
87
py{27,34,35}-djangotrunk,
98
docs, flake8
109

1110

1211
[flake8]
1312
ignore = N802
14-
max-complexity = 11
13+
max-complexity = 10
1514
exclude = __init__.py,simple_history/tests/migration_test_app/migrations/*
1615

1716

@@ -30,8 +29,6 @@ commands = sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
3029
[testenv]
3130
deps =
3231
coverage
33-
py26: unittest2
34-
django14: Django>=1.4,<1.5
3532
django16: Django>=1.6,<1.7
3633
django17: Django>=1.7,<1.8
3734
django18: Django>=1.8,<1.9

0 commit comments

Comments
 (0)