From 62699eab16008ba20233668294b5ae5258b9eec7 Mon Sep 17 00:00:00 2001 From: Michael Shannon Date: Thu, 18 Aug 2016 08:48:52 -0400 Subject: [PATCH] Update for django-reversion 2.0 --- .travis.yml | 4 +- AUTHORS | 2 + reversion_compare/admin.py | 12 +- reversion_compare/compare.py | 283 ++++++++++------------- reversion_compare/forms.py | 1 + reversion_compare/helpers.py | 5 +- reversion_compare/mixins.py | 21 +- reversion_compare/reversion_api.py | 27 ++- reversion_compare/views.py | 8 +- setup.py | 7 - tests/admin.py | 13 +- tests/models.py | 20 +- tests/test_custom_model.py | 28 +-- tests/test_factory_car_models.py | 47 ++-- tests/test_factory_car_reverse_models.py | 23 +- tests/test_onetoone_field.py | 17 +- tests/test_person_pet_models.py | 72 +++--- tests/test_settings.py | 6 +- tests/test_simple_model.py | 54 ++--- tests/test_utils/test_cases.py | 14 +- tests/test_utils/test_data.py | 19 +- tests/test_variant_model.py | 16 +- tests/test_view.py | 45 ++-- tests/views.py | 2 +- 24 files changed, 348 insertions(+), 398 deletions(-) diff --git a/.travis.yml b/.travis.yml index ca5198af..69fc037f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,11 @@ env: - DJANGO='1.8' REVERSION='1.9' EXTRA='' - DJANGO='1.8' REVERSION='1.10' EXTRA='' - DJANGO='1.9' REVERSION='1.10' EXTRA='' + - DJANGO='1.9' REVERSION='2.0' EXTRA='' - DJANGO='1.8' REVERSION='1.9' EXTRA='diff-match-patch' - - DJANGO='1.8' REVERSION='1.10' EXTRA='diff-match-patch' + - DJANGO='1.8' REVERSION='1.10' EXTRA='diff-match-patch' - DJANGO='1.9' REVERSION='1.10' EXTRA='diff-match-patch' + - DJANGO='1.9' REVERSION='2.0' EXTRA='diff-match-patch' install: - pip install --upgrade pip diff --git a/AUTHORS b/AUTHORS index 3822f061..dfddd840 100644 --- a/AUTHORS +++ b/AUTHORS @@ -33,6 +33,8 @@ CONTRIBUTORS are and/or have been (alphabetic order): Github: * Spencer, Samuel Github: +* Shannon, Michael + Github: * C. Barrionuevo da Luz, Fabio Github: * Wickström, Frank diff --git a/reversion_compare/admin.py b/reversion_compare/admin.py index 5717f6b5..2a022924 100644 --- a/reversion_compare/admin.py +++ b/reversion_compare/admin.py @@ -20,7 +20,7 @@ from django.contrib import admin try: from django.contrib.admin.utils import unquote, quote -except ImportError: # Django < 1.7 +except ImportError: # Django < 1.7 # pragma: no cover from django.contrib.admin.util import unquote, quote from django.core.urlresolvers import reverse from django.http import Http404 @@ -29,12 +29,12 @@ from django.utils.translation import ugettext as _ try: - from reversion import revisions as reversion # django-reversion >= 1.10 + from reversion import revisions as reversion # django-reversion >= 1.10 except ImportError: - import reversion # django-reversion <= 1.9 + import reversion # django-reversion <= 1.9 from reversion.admin import VersionAdmin - +from reversion_compare import reversion_api from reversion_compare.forms import SelectDiffForm from reversion_compare.mixins import CompareMixin, CompareMethodsMixin @@ -111,7 +111,7 @@ def _get_action_list(self, request, object_id, extra_context=None): args=(quote(version.object_id), version.id)), } for version - in self._order_version_queryset(self.revision_manager.get_for_object_reference( + in self._order_version_queryset(reversion_api.get_for_object_reference( self.model, object_id, ).select_related("revision__user")) @@ -168,7 +168,7 @@ def compare_view(self, request, object_id, extra_context=None): object_id = unquote(object_id) # Underscores in primary key get quoted to "_5F" obj = get_object_or_404(self.model, pk=object_id) - queryset = self.revision_manager.get_for_object(obj) + queryset = reversion_api.get_for_object(obj) version1 = get_object_or_404(queryset, pk=version_id1) version2 = get_object_or_404(queryset, pk=version_id2) diff --git a/reversion_compare/compare.py b/reversion_compare/compare.py index ea470ee9..39dcff0b 100644 --- a/reversion_compare/compare.py +++ b/reversion_compare/compare.py @@ -16,11 +16,8 @@ from django.db import models from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils.translation import ugettext as _ - - from reversion_compare import reversion_api - logger = logging.getLogger(__name__) @@ -36,21 +33,21 @@ def __str__(self): class CompareObject(object): - def __init__(self, field, field_name, obj, version, has_int_pk, adapter): + + def __init__(self, field, field_name, obj, version_record, follow): self.field = field self.field_name = field_name self.obj = obj - self.version = version # instance of reversion.models.Version() - self.has_int_pk = has_int_pk - self.adapter = adapter + self.version_record = version_record # instance of reversion.models.Version() + self.follow = follow # try and get a value, if none punt - self.value = version.field_dict.get(field_name, DOES_NOT_EXIST) + self.value = version_record.field_dict.get(field_name, DOES_NOT_EXIST) def _obj_repr(self, obj): # FIXME: How to create a better representation of the current value? try: return str(obj) - except Exception as e: + except Exception: return repr(obj) def _choices_repr(self, obj): @@ -58,12 +55,10 @@ def _choices_repr(self, obj): strings_only=True) def _to_string_ManyToManyField(self): - queryset = self.get_many_to_many() - return ", ".join([self._obj_repr(item) for item in queryset]) + return ", ".join([self._obj_repr(item) for item in self.get_many_to_many()]) def _to_string_ForeignKey(self): - obj = self.get_related() - return self._obj_repr(obj) + return self._obj_repr(self.get_related()) def to_string(self): internal_type = self.field.get_internal_type() @@ -91,9 +86,9 @@ def __eq__(self, other): return False # see - https://hynek.me/articles/hasattr/ - internal_type = getattr(self.field,'get_internal_type',None) + internal_type = getattr(self.field, 'get_internal_type', None) if internal_type is None or internal_type() == "ForeignKey": # FIXME! - if self.version.field_dict != other.version.field_dict: + if self.version_record.field_dict != other.version_record.field_dict: return False return True @@ -101,35 +96,46 @@ def __eq__(self, other): def __ne__(self, other): return not self.__eq__(other) + def get_object_version(self): + if hasattr(self.version_record, '_object_version'): + return getattr(self.version_record, '_object_version') + else: + return getattr(self.version_record, 'object_version') + def get_related(self): if getattr(self.field, 'rel', None): - obj = self.version.object_version.object + obj = self.get_object_version().object try: return getattr(obj, self.field.name, None) except ObjectDoesNotExist: return None def get_reverse_foreign_key(self): - obj = self.version.object_version.object - if self.has_int_pk and self.field.related_name and hasattr(obj, self.field.related_name): + obj = self.get_object_version().object + if self.field.related_name and hasattr(obj, self.field.related_name): if isinstance(self.field, models.fields.related.OneToOneRel): try: - ids = [getattr(obj, str(self.field.related_name)).pk] + ids = {force_text(getattr(obj, str(self.field.related_name)).pk), } except ObjectDoesNotExist: - ids = [] + ids = set() else: - ids = [v.id for v in getattr(obj, str(self.field.related_name)).all()] # is: version.field_dict[field.name] - if ids == [] and any([f.name.endswith('_ptr') for f in obj._meta.fields]): - # If there is a _ptr this is a multiinheritance table and inherits from a non-abstract class + # If there is a _ptr this is a multi-inheritance table and inherits from a non-abstract class + ids = {force_text(v.id) for v in getattr(obj, str(self.field.related_name)).all()} + if not ids and any([f.name.endswith('_ptr') for f in obj._meta.get_fields()]): + # If there is a _ptr this is a multi-inheritance table and inherits from a non-abstract class # lets try and get the parent items associated entries for this field - others = self.version.revision.version_set.filter(object_id=self.version.object_id) + others = self.version_record.revision.version_set.filter( + object_id=self.version_record.object_id + ).all() for p in others: - p_obj = p.object_version.object - if type(p_obj) != type(obj) and hasattr(p_obj,str(self.field.related_name)): - ids = [v.id for v in getattr(p_obj, str(self.field.related_name)).all()] - + if hasattr(p, '_object_version'): + p_obj = getattr(p, '_object_version').object + else: + p_obj = getattr(p, 'object_version').object + if type(p_obj) != type(obj) and hasattr(p_obj, str(self.field.related_name)): + ids = {force_text(v.id) for v in getattr(p_obj, str(self.field.related_name)).all()} else: - return ([], [], [], []) # TODO: refactory that + return {}, {}, [] # TODO: refactor that # Get the related model of the current field: related_model = self.field.field.model @@ -140,66 +146,55 @@ def get_many_to_many(self): returns a queryset with all many2many objects """ if self.field.get_internal_type() != "ManyToManyField": # FIXME! - return ([], [], [], []) # TODO: refactory that + return {}, {}, [] # TODO: refactor that elif self.value is DOES_NOT_EXIST: - return ([], [], [], []) # TODO: refactory that - - related_model = self.field.rel.to + return {}, {}, [] # TODO: refactor that - ids = None - if reversion_api.has_int_pk(related_model): - ids = [int(v) for v in self.value] # is: version.field_dict[field.name] + ids = frozenset(map(force_text, self.value)) # Get the related model of the current field: - return self.get_many_to_something(ids, related_model) - - def get_many_to_something(self, ids, related_model, is_reverse=False): + return self.get_many_to_something(ids, self.field.rel.to) + def get_many_to_something(self, target_ids, related_model, is_reverse=False): # get instance of reversion.models.Revision(): # A group of related object versions. - old_revision = self.version.revision + old_revision = self.version_record.revision # Get a queryset with all related objects. - versions = old_revision.version_set.filter( - content_type=ContentType.objects.get_for_model(related_model), - object_id__in=ids - ) - - if self.has_int_pk: - # The primary_keys would be stored in a text field -> convert it to integers - # This is interesting in different places! - for version in versions: - version.object_id = int(version.object_id) + versions = { + ver.object_id: ver for ver in old_revision.version_set.filter( + content_type=ContentType.objects.get_for_model(related_model), + object_id__in=target_ids + ).all() + } - missing_objects = [] - missing_ids = [] + missing_objects_dict = {} + deleted = [] - if self.field_name not in self.adapter.follow: + if not self.follow: # This models was not registered with follow relations # Try to fill missing related objects - target_ids = set(ids) - actual_ids = set([version.object_id for version in versions]) - missing_ids1 = target_ids.difference(actual_ids) - - # logger.debug(self.field_name, "target: %s - actual: %s - missing: %s" % (target_ids, actual_ids, missing_ids1)) - if missing_ids1: - missing_objects = related_model.objects.all().filter(pk__in=missing_ids1) - missing_ids = list(target_ids.difference(set(missing_objects.values_list('pk', flat=True)))) + potentially_missing_ids = target_ids.difference(frozenset(versions)) + # logger.debug(self.field_name, "target: %s - actual: %s - missing: %s" % (target_ids, versions, potentially_missing_ids)) + if potentially_missing_ids: + missing_objects_dict = { + force_text(rel.pk): rel + for rel in related_model.objects.filter(pk__in=potentially_missing_ids).iterator() + } - deleted = [] if is_reverse: - true_missing_objects = [] - for o in missing_objects: - for ver in reversion_api.get_for_object(o): - # An object can only be missing if it actually existed prior to this version - # Otherwise its a new item - if ver.revision.date_created < old_revision.date_created: - true_missing_objects.append(o) - missing_objects = true_missing_objects + missing_objects_dict = { + ver.object_id: ver + for o in missing_objects_dict.values() + for ver in reversion_api.get_for_object(o) + if ver.revision.date_created < old_revision.date_created + } + deleted = [d for d in reversion_api.get_deleted(related_model) if d.revision == old_revision] - return versions, missing_objects, missing_ids, deleted - def get_debug(self): + return versions, missing_objects_dict, deleted + + def get_debug(self): # pragma: no cover if not settings.DEBUG: return @@ -207,11 +202,9 @@ def get_debug(self): "field..............: %r" % self.field, "field_name.........: %r" % self.field_name, "field internal type: %r" % self.field.get_internal_type(), - "field_dict.........: %s" % repr(self.version.field_dict), - "adapter............: %r (follow: %r)" % (self.adapter, ", ".join(self.adapter.follow)), - "has_int_pk ........: %r" % self.has_int_pk, + "field_dict.........: %s" % repr(self.version_record.field_dict), "obj................: %r (pk: %s, id: %s)" % (self.obj, self.obj.pk, id(self.obj)), - "version............: %r (pk: %s, id: %s)" % (self.version, self.version.pk, id(self.version)), + "version............: %r (pk: %s, id: %s)" % (self.version_record, self.version_record.pk, id(self.version_record)), "value..............: %r" % self.value, "to string..........: %s" % repr(self.to_string()), "related............: %s" % repr(self.get_related()), @@ -220,12 +213,12 @@ def get_debug(self): if m2m_versions or missing_objects or missing_ids: result.append( "many-to-many.......: %s" % ", ".join( - ["%s (%s)" % ( - item, - item.type - ) for item in m2m_versions] + ["%s (%s)" % ( + item, + item.type + ) for item in m2m_versions] + ) ) - ) if missing_objects: result.append("missing m2m objects: %s" % repr(missing_objects)) @@ -241,7 +234,7 @@ def get_debug(self): return result - def debug(self): + def debug(self): # pragma: no cover if not settings.DEBUG: return for item in self.get_debug(): @@ -249,31 +242,30 @@ def debug(self): class CompareObjects(object): - def __init__(self, field, field_name, obj, version1, version2, manager, is_reversed): + def __init__(self, field, field_name, obj, version1, version2, is_reversed): self.field = field self.field_name = field_name self.obj = obj - model = self.obj.__class__ - self.has_int_pk = reversion_api.has_int_pk(model) - self.adapter = manager.get_adapter(model) # VersionAdapter instance - # is a related field (ForeignKey, ManyToManyField etc.) self.is_related = getattr(self.field, 'rel', None) is not None self.is_reversed = is_reversed if not self.is_related: self.follow = None - elif self.field_name in self.adapter.follow: + elif self.field_name in reversion_api._get_options(self.obj.__class__).follow: self.follow = True else: self.follow = False - self.compare_obj1 = CompareObject(field, field_name, obj, version1, self.has_int_pk, self.adapter) - self.compare_obj2 = CompareObject(field, field_name, obj, version2, self.has_int_pk, self.adapter) + self.compare_obj1 = CompareObject(field, field_name, obj, version1, self.follow) + self.compare_obj2 = CompareObject(field, field_name, obj, version2, self.follow) self.value1 = self.compare_obj1.value self.value2 = self.compare_obj2.value + self.M2O_CHANGE_INFO = None + self.M2M_CHANGE_INFO = None + def changed(self): """ return True if at least one field has changed values. """ @@ -294,31 +286,17 @@ def changed(self): return self.compare_obj1 != self.compare_obj2 - def _get_result(self, compare_obj, func_name): - func = getattr(compare_obj, func_name) - result = func() - return result - - def _get_both_results(self, func_name): - result1 = self._get_result(self.compare_obj1, func_name) - result2 = self._get_result(self.compare_obj2, func_name) - return (result1, result2) - def to_string(self): - return self._get_both_results("to_string") + return self.compare_obj1.to_string(), self.compare_obj2.to_string() def get_related(self): - return self._get_both_results("get_related") + return self.compare_obj1.get_related(), self.compare_obj2.get_related() def get_many_to_many(self): - # return self._get_both_results("get_many_to_many") - m2m_data1, m2m_data2 = self._get_both_results("get_many_to_many") - return m2m_data1, m2m_data2 + return self.compare_obj1.get_many_to_many(), self.compare_obj2.get_many_to_many() def get_reverse_foreign_key(self): - return self._get_both_results("get_reverse_foreign_key") - - M2O_CHANGE_INFO = None + return self.compare_obj1.get_reverse_foreign_key(), self.compare_obj2.get_reverse_foreign_key() def get_m2o_change_info(self): if self.M2O_CHANGE_INFO is not None: @@ -329,8 +307,6 @@ def get_m2o_change_info(self): self.M2O_CHANGE_INFO = self.get_m2s_change_info(m2o_data1, m2o_data2) return self.M2O_CHANGE_INFO - M2M_CHANGE_INFO = None - def get_m2m_change_info(self): if self.M2M_CHANGE_INFO is not None: return self.M2M_CHANGE_INFO @@ -341,51 +317,39 @@ def get_m2m_change_info(self): return self.M2M_CHANGE_INFO # Abstract Many-to-Something (either -many or -one) as both - # many2many and many2one relationships looks the same from the refered object. + # many2many and many2one relationships looks the same from the referred object. def get_m2s_change_info(self, obj1_data, obj2_data): - result1, missing_objects1, missing_ids1, deleted1 = obj1_data - result2, missing_objects2, missing_ids2, deleted2 = obj2_data - - # missing_objects_pk1 = [obj.pk for obj in missing_objects1] - # missing_objects_pk2 = [obj.pk for obj in missing_objects2] - missing_objects_dict2 = dict([(obj.pk, obj) for obj in missing_objects2]) - - # logger.debug("missing_objects1: %s", missing_objects1) - # logger.debug("missing_objects2: %s", missing_objects2) - # logger.debug("missing_ids1: %s", missing_ids1) - # logger.debug("missing_ids2: %s", missing_ids2) - - missing_object_set1 = set(missing_objects1) - missing_object_set2 = set(missing_objects2) - # logger.debug("%s %s", missing_object_set1, missing_object_set2) - - same_missing_objects = missing_object_set1.intersection(missing_object_set2) - removed_missing_objects = missing_object_set1.difference(missing_object_set2) - added_missing_objects = missing_object_set2.difference(missing_object_set1) - - # logger.debug("same_missing_objects: %s", same_missing_objects) - # logger.debug("removed_missing_objects: %s", removed_missing_objects) - # logger.debug("added_missing_objects: %s", added_missing_objects) - + result_dict1, missing_objects_dict1, deleted1 = obj1_data + result_dict2, missing_objects_dict2, deleted2 = obj2_data # Create same_items, removed_items, added_items with related m2m items - changed_items = [] removed_items = [] added_items = [] same_items = [] - primary_keys1 = [version.object_id for version in result1] - primary_keys2 = [version.object_id for version in result2] - - result_dict1 = dict([(version.object_id, version) for version in result1]) - result_dict2 = dict([(version.object_id, version) for version in result2]) + same_missing_objects_dict = { + k: v for k, v in + missing_objects_dict1.items() + if k in missing_objects_dict2 + } + removed_missing_objects_dict = { + k: v for k, v in + missing_objects_dict1.items() + if k not in missing_objects_dict2 + } + added_missing_objects_dict = { + k: v for k, v in + missing_objects_dict2.items() + if k not in missing_objects_dict1 + } - # logger.debug(result_dict1) - # logger.debug(result_dict2) + # logger.debug("same_missing_objects: %s", same_missing_objects_dict) + # logger.debug("removed_missing_objects: %s", removed_missing_objects_dict) + # logger.debug("added_missing_objects: %s", added_missing_objects_dict) - for primary_key in set(primary_keys1).union(set(primary_keys2)): + for primary_key in set().union(result_dict1.keys(), result_dict2.keys()): if primary_key in result_dict1: version1 = result_dict1[primary_key] else: @@ -396,33 +360,40 @@ def get_m2s_change_info(self, obj1_data, obj2_data): else: version2 = None - #logger.debug("%r - %r - %r", primary_key, version1, version2) + # logger.debug("%r - %r - %r", primary_key, version1, version2) if version1 is not None and version2 is not None: # In both -> version changed or the same if version1.serialized_data == version2.serialized_data: - #logger.debug("same item: %s", version1) + # logger.debug("same item: %s", version1) same_items.append(version1) else: changed_items.append((version1, version2)) elif version1 is not None and version2 is None: # In 1 but not in 2 -> removed - #logger.debug("%s %s", primary_key, missing_objects_pk2) - #logger.debug("%s %s", repr(primary_key), repr(missing_objects_pk2)) - if primary_key in missing_objects_dict2: - missing_object = missing_objects_dict2[primary_key] - added_missing_objects.remove(missing_object) - same_missing_objects.add(missing_object) + # logger.debug("%s %s", primary_key, missing_objects_dict2) + # logger.debug("%s %s", repr(primary_key), repr(missing_objects_dict2)) + if primary_key in added_missing_objects_dict: + added_missing_objects_dict.pop(primary_key) + same_missing_objects_dict[primary_key] = missing_objects_dict2[primary_key] continue - removed_items.append(version1) elif version1 is None and version2 is not None: # In 2 but not in 1 -> added - #logger.debug("added: %s", version2) + # logger.debug("added: %s", version2) added_items.append(version2) else: raise RuntimeError() + # In Place Sorting of Lists (exclude changed since its a tuple) + removed_items.sort(key=lambda item: str(item)) + added_items.sort(key=lambda item: str(item)) + same_items.sort(key=lambda item: str(item)) + deleted1.sort(key=lambda item: str(item)) + same_missing_objects = sorted(same_missing_objects_dict.values(), key=lambda item: str(item)) + removed_missing_objects = sorted(removed_missing_objects_dict.values(), key=lambda item: str(item)) + added_missing_objects = sorted(added_missing_objects_dict.values(), key=lambda item: str(item)) + return { "changed_items": changed_items, "removed_items": removed_items, @@ -434,8 +405,7 @@ def get_m2s_change_info(self, obj1_data, obj2_data): "deleted_items": deleted1, } - - def debug(self): + def debug(self): # pragma: no cover if not settings.DEBUG: return logger.debug("_______________________________") @@ -469,4 +439,3 @@ def debug(self): logger.debug(item) logger.debug("-" * 79) - diff --git a/reversion_compare/forms.py b/reversion_compare/forms.py index f80b51bc..d9471c79 100644 --- a/reversion_compare/forms.py +++ b/reversion_compare/forms.py @@ -2,6 +2,7 @@ from django import forms + class SelectDiffForm(forms.Form): version_id1 = forms.IntegerField(min_value=1) version_id2 = forms.IntegerField(min_value=1) diff --git a/reversion_compare/helpers.py b/reversion_compare/helpers.py index 8df0f84e..dfd3561d 100644 --- a/reversion_compare/helpers.py +++ b/reversion_compare/helpers.py @@ -15,7 +15,6 @@ :license: GNU GPL v3 or above, see LICENSE for more details. """ - import difflib import logging @@ -38,7 +37,6 @@ else: google_diff_match_patch = True dmp = diff_match_patch() -#google_diff_match_patch = False # manually disable, for testing def highlight_diff(diff_text): @@ -220,10 +218,9 @@ class PatchedModelAdmin(AdminClass, ModelAdmin): admin_site.register(model, PatchedModelAdmin) - if __name__ == "__main__": import doctest print(doctest.testmod( -# verbose=True verbose=False + # verbose=True )) diff --git a/reversion_compare/mixins.py b/reversion_compare/mixins.py index c69748f5..98b54f3f 100644 --- a/reversion_compare/mixins.py +++ b/reversion_compare/mixins.py @@ -12,14 +12,12 @@ from django.template.loader import render_to_string from reversion_compare.helpers import html_diff -from reversion.revisions import default_revision_manager - from reversion_compare.compare import CompareObjects + class CompareMixin(object, ): """A mixin to add comparison capabilities to your views""" - - revision_manager = default_revision_manager + # list/tuple of field names for the compare view. Set to None for all existing fields compare_fields = None @@ -45,8 +43,8 @@ def _get_compare(self, obj_compare): """ def _get_compare_func(suffix): - func_name = "compare_%s" % suffix # logger.debug("func_name: %s", func_name) + func_name = "compare_%s" % suffix if hasattr(self, func_name): func = getattr(self, func_name) return func @@ -102,7 +100,7 @@ def compare(self, obj, version1, version2): ) if isinstance(f, models.ForeignKey) and f not in fields: self.reverse_fields.append(f.rel) - #print(self.reverse_fields) + fields += self.reverse_fields has_unfollowed_fields = False @@ -121,8 +119,8 @@ def compare(self, obj, version1, version2): continue is_reversed = field in self.reverse_fields - obj_compare = CompareObjects(field, field_name, obj, version1, version2, self.revision_manager, is_reversed) - #obj_compare.debug() + obj_compare = CompareObjects(field, field_name, obj, version1, version2, is_reversed) + # obj_compare.debug() is_related = obj_compare.is_related follow = obj_compare.follow @@ -171,9 +169,8 @@ def generic_add_remove(self, raw_value1, raw_value2, value1, value2): def compare_ForeignKey(self, obj_compare): related1, related2 = obj_compare.get_related() - obj_compare.debug() + # obj_compare.debug() value1, value2 = str(related1), str(related2) - # value1, value2 = repr(related1), repr(related2) return self.generic_add_remove(related1, related2, value1, value2) def simple_compare_ManyToManyField(self, obj_compare): @@ -215,7 +212,7 @@ def compare_FileField(self, obj_compare): return self.generic_add_remove(value1, value2, value1, value2) def compare_DateTimeField(self, obj_compare): - ''' compare all model datetime field in ISO format ''' + """ compare all model datetime field in ISO format """ context = { "date1": obj_compare.value1, "date2": obj_compare.value2, @@ -223,7 +220,7 @@ def compare_DateTimeField(self, obj_compare): return render_to_string("reversion-compare/compare_DateTimeField.html", context) def compare_BooleanField(self, obj_compare): - ''' compare booleans as a complete field, rather than as a string ''' + """ compare booleans as a complete field, rather than as a string """ context = { "bool1": obj_compare.value1, "bool2": obj_compare.value2, diff --git a/reversion_compare/reversion_api.py b/reversion_compare/reversion_api.py index 2bfe2abb..545093ac 100644 --- a/reversion_compare/reversion_api.py +++ b/reversion_compare/reversion_api.py @@ -1,19 +1,30 @@ - import reversion -if reversion.__version__ > (1,10): +from reversion.models import Revision, Version + +if reversion.__version__ > (2, 0): from reversion import revisions as reversion from reversion.revisions import ( register, unregister, is_registered, - get_for_object, get_registered_models, get_deleted, - create_revision, set_comment + get_registered_models, + create_revision, set_comment, _get_options ) + get_for_object_reference = Version.objects.get_for_object_reference + get_for_object = Version.objects.get_for_object + get_deleted = Version.objects.get_deleted +elif reversion.__version__ > (1, 10): + from reversion import revisions as reversion + from reversion.revisions import ( + register, unregister, is_registered, + get_for_object, get_for_object_reference, get_registered_models, get_deleted, + create_revision, set_comment, default_revision_manager + ) + _get_options = default_revision_manager.get_adapter else: # django-reversion <= 1.9 from reversion import ( register, unregister, is_registered, - get_for_object, get_registered_models, get_deleted, - create_revision, set_comment + get_for_object, get_for_object_reference, get_registered_models, get_deleted, + create_revision, set_comment, default_revision_manager ) + _get_options = default_revision_manager.get_adapter - -from reversion.models import Revision, Version, has_int_pk \ No newline at end of file diff --git a/reversion_compare/views.py b/reversion_compare/views.py index 754b7ed3..7f181f3b 100644 --- a/reversion_compare/views.py +++ b/reversion_compare/views.py @@ -2,9 +2,11 @@ from django.shortcuts import get_object_or_404 from django.views.generic.detail import DetailView +from reversion_compare import reversion_api from reversion_compare.forms import SelectDiffForm from reversion_compare.mixins import CompareMixin, CompareMethodsMixin + class HistoryCompareDetailView(CompareMixin, CompareMethodsMixin, DetailView): """This class can be used to add a non-admin view for comparing your object's versions. @@ -49,14 +51,13 @@ class SimpleModelHistoryCompareView(HistoryCompareDetailView): """ def _get_action_list(self, ): - opts = self.model._meta action_list = [ { "version": version, "revision": version.revision, } for version - in self._order_version_queryset(self.revision_manager.get_for_object( + in self._order_version_queryset(reversion_api.get_for_object( self.get_object(), ).select_related("revision__user")) ] @@ -93,7 +94,7 @@ def get_context_data(self, **kwargs): version_id1, version_id2 = version_id2, version_id1 obj = self.get_object() - queryset = self.revision_manager.get_for_object(obj) + queryset = reversion_api.get_for_object(obj) version1 = get_object_or_404(queryset, pk=version_id1) version2 = get_object_or_404(queryset, pk=version_id2) @@ -120,7 +121,6 @@ def get_context_data(self, **kwargs): ) context.update({'prev_url': prev_url}) - # Compile the context. context.update({ "action_list": action_list, diff --git a/setup.py b/setup.py index 2e6ad628..994111ee 100755 --- a/setup.py +++ b/setup.py @@ -182,10 +182,6 @@ def rmtree(path): sys.exit(0) - - - - def get_authors(): try: with open(os.path.join(PACKAGE_ROOT, "AUTHORS"), "r") as f: @@ -217,12 +213,9 @@ def get_authors(): ], zip_safe=False, classifiers=[ -# "Development Status :: 4 - Beta", "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", -# "Intended Audience :: Education", -# "Intended Audience :: End Users/Desktop", "License :: OSI Approved :: GNU General Public License (GPL)", "Programming Language :: Python", "Programming Language :: Python :: 2.7", diff --git a/tests/admin.py b/tests/admin.py index f6da10d0..4152ab56 100644 --- a/tests/admin.py +++ b/tests/admin.py @@ -12,10 +12,6 @@ from __future__ import unicode_literals, print_function - -from reversion.models import Revision, Version -from reversion.revisions import RevisionManager - from django.contrib import admin from reversion_compare.admin import CompareVersionAdmin @@ -23,7 +19,6 @@ VariantModel, CustomModel, Identity - class SimpleModelAdmin(CompareVersionAdmin): pass admin.site.register(SimpleModel, SimpleModelAdmin) @@ -33,6 +28,7 @@ class FactoryAdmin(CompareVersionAdmin): pass admin.site.register(Factory, FactoryAdmin) + class CarAdmin(CompareVersionAdmin): pass admin.site.register(Car, CarAdmin) @@ -42,6 +38,7 @@ class PersonAdmin(CompareVersionAdmin): pass admin.site.register(Person, PersonAdmin) + class PetAdmin(CompareVersionAdmin): pass admin.site.register(Pet, PetAdmin) @@ -52,16 +49,14 @@ class VariantModelAdmin(CompareVersionAdmin): admin.site.register(VariantModel, VariantModelAdmin) -custom_revision_manager = RevisionManager("custom") - class CustomModelAdmin(CompareVersionAdmin): - revision_manager = custom_revision_manager + pass + admin.site.register(CustomModel, CustomModelAdmin) admin.site.register(Identity, CustomModelAdmin) - """ class RelatedModelInline(admin.StackedInline): model = RelatedModel diff --git a/tests/models.py b/tests/models.py index 74e32051..e06dc1c6 100644 --- a/tests/models.py +++ b/tests/models.py @@ -24,10 +24,11 @@ @python_2_unicode_compatible class SimpleModel(models.Model): text = models.CharField(max_length=255) + def __str__(self): return "SimpleModel pk: %r text: %r" % (self.pk, self.text) -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ """ models with relationships @@ -42,23 +43,29 @@ def __str__(self): https://github.com/etianen/django-reversion/wiki/Low-level-API """ + @python_2_unicode_compatible class Building(models.Model): address = models.CharField(max_length=128) + def __str__(self): return self.address + @python_2_unicode_compatible class Factory(Building): name = models.CharField(max_length=128) + def __str__(self): return self.name + @python_2_unicode_compatible class Car(models.Model): name = models.CharField(max_length=128) manufacturer = models.ForeignKey(Factory, related_name="cars") supplier = models.ManyToManyField(Factory, related_name="suppliers", blank=True) + def __str__(self): return "%s from %s supplier(s): %s" % (self.name, self.manufacturer, ", ".join([s.name for s in self.supplier.all()])) @@ -66,27 +73,31 @@ def __str__(self): @python_2_unicode_compatible class Pet(models.Model): name = models.CharField(max_length=100) + def __str__(self): return self.name + @python_2_unicode_compatible class Person(models.Model): name = models.CharField(max_length=100) pets = models.ManyToManyField(Pet, blank=True) # If you work someone, its at a build, but maybe not a factory! workplace = models.ForeignKey(Building, related_name="workers", null=True) + def __str__(self): return self.name + @python_2_unicode_compatible class Identity(models.Model): id_numer = models.CharField(max_length=100) person = models.OneToOneField(Person, related_name='_identity') + def __str__(self): return self.id_numer reversion_api.register(Person, follow=["pets"]) -#reversion_api.register(Pet, follow=["person_set"]) reversion_api.register(Pet) @@ -130,6 +141,8 @@ class VariantModel(models.Model): email = models.EmailField(blank=True, null=True) url = models.URLField(blank=True, null=True) + file_field = models.FileField(blank=True, null=True) + filepath = models.FilePathField( path=settings.UNITTEST_TEMP_PATH, blank=True, null=True @@ -140,10 +153,9 @@ class VariantModel(models.Model): def __str__(self): return "VariantModel instance pk: %i" % self.pk -#------------------------------------------------------------------------------ class CustomModel(models.Model): - "Model which uses a custom version manager." + """Model which uses a custom version manager.""" text = models.TextField() """ diff --git a/tests/test_custom_model.py b/tests/test_custom_model.py index 2ee73b87..21d08aa5 100644 --- a/tests/test_custom_model.py +++ b/tests/test_custom_model.py @@ -17,8 +17,6 @@ from __future__ import absolute_import, division, print_function -from django.core.urlresolvers import reverse - try: import django_tools except ImportError as err: @@ -29,21 +27,15 @@ ) % err raise ImportError(msg) - +from django.core.urlresolvers import reverse from reversion_compare import reversion_api - - from tests.models import CustomModel - -# Needs to import admin module to register all models via CompareVersionAdmin/VersionAdmin -from tests.admin import custom_revision_manager - from .test_utils.test_cases import BaseTestCase from .test_utils.test_data import TestData class CustomModelTest(BaseTestCase): - "Test a model which uses a custom reversion manager." + """Test a model which uses a custom reversion manager.""" def setUp(self): super(CustomModelTest, self).setUp() @@ -51,18 +43,17 @@ def setUp(self): self.item = test_data.create_CustomModel_data() def test_initial_state(self): - "Test initial data creation and model registration." - self.assertTrue(custom_revision_manager.is_registered(CustomModel)) + """"Test initial data creation and model registration.""" self.assertEqual(CustomModel.objects.count(), 1) - self.assertEqual(custom_revision_manager.get_for_object(self.item).count(), 1) + self.assertEqual(reversion_api.get_for_object(self.item).count(), 1) self.assertEqual(reversion_api.Revision.objects.all().count(), 1) def test_text_diff(self): - "Generate a new revision and check for a correctly generated diff." + """"Generate a new revision and check for a correctly generated diff.""" with reversion_api.create_revision(): self.item.text = "version two" self.item.save() - queryset = custom_revision_manager.get_for_object(self.item) + queryset = reversion_api.get_for_object(self.item) version_ids = queryset.values_list("pk", flat=True) self.assertEqual(len(version_ids), 2) url_name = 'admin:%s_%s_compare' % (CustomModel._meta.app_label, CustomModel._meta.model_name) @@ -73,20 +64,21 @@ def test_text_diff(self): self.assertContains(response, "+ version two") def test_version_selection(self): - "Generate two revisions and view the version history selection." + """Generate two revisions and view the version history selection.""" with reversion_api.create_revision(): self.item.text = "version two" self.item.save() with reversion_api.create_revision(): self.item.text = "version three" self.item.save() - queryset = custom_revision_manager.get_for_object(self.item) + queryset = reversion_api.get_for_object(self.item) version_ids = queryset.values_list("pk", flat=True) self.assertEqual(len(version_ids), 3) url_name = 'admin:%s_%s_history' % (CustomModel._meta.app_label, CustomModel._meta.model_name) history_url = reverse(url_name, args=(self.item.pk, )) response = self.client.get(history_url) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, '', '' % version_ids[0], '' % version_ids[0], diff --git a/tests/test_factory_car_models.py b/tests/test_factory_car_models.py index 17d70f3c..3f4363cb 100644 --- a/tests/test_factory_car_models.py +++ b/tests/test_factory_car_models.py @@ -17,7 +17,6 @@ from __future__ import absolute_import, division, print_function - try: import django_tools except ImportError as err: @@ -27,18 +26,13 @@ " - Original error: %s" ) % err raise ImportError(msg) -from django_tools.unittest_utils.BrowserDebug import debug_response - from reversion_compare import reversion_api - - -from reversion_compare import helpers - from .models import Factory, Car from .test_utils.test_cases import BaseTestCase from .test_utils.test_data import TestData + class FactoryCarModelTest(BaseTestCase): """ unittests that used: @@ -52,7 +46,7 @@ def setUp(self): super(FactoryCarModelTest, self).setUp() test_data = TestData(verbose=False) -# test_data = TestData(verbose=True) + # test_data = TestData(verbose=True) self.car = test_data.create_FactoryCar_data() queryset = reversion_api.get_for_object(self.car) @@ -68,8 +62,9 @@ def test_initial_state(self): def test_select_compare(self): response = self.client.get("/admin/tests/car/%s/history/" % self.car.pk) -# debug_response(response) # from django-tools - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '', '' % self.version_ids[0], '' % self.version_ids[0], @@ -82,11 +77,11 @@ def test_select_compare(self): def test_diff1(self): response = self.client.get( "/admin/tests/car/%s/history/compare/" % self.car.pk, - data={"version_id2":self.version_ids[1], "version_id1":self.version_ids[2]} + data={"version_id2": self.version_ids[1], "version_id1": self.version_ids[2]} ) -# debug_response(response) # from django-tools - - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '

manufacturer

', '

supplier

', ''' @@ -97,18 +92,18 @@ def test_diff1(self): always the same supplier

''', - '', # info for non-follow related informations - '
version 2: change ForeignKey and ManyToManyField.
', # edit comment + '', # info for non-follow related informations + '
version 2: change ForeignKey and ManyToManyField.
', ) def test_diff2(self): response = self.client.get( "/admin/tests/car/%s/history/compare/" % self.car.pk, - data={"version_id2":self.version_ids[0], "version_id1":self.version_ids[1]} + data={"version_id2": self.version_ids[0], "version_id1":self.version_ids[1]} ) -# debug_response(response) # from django-tools - - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, "- motor-car one", "+ motor-car II", @@ -120,12 +115,11 @@ def test_diff2(self): always the same supplier

''', - '', # info for non-follow related informations - '
version 3: change CharField, ForeignKey and ManyToManyField.
', # edit comment + '', # info for non-follow related informations + '
version 3: change CharField, ForeignKey and ManyToManyField.
', ) - class FactoryCarModelTest2(BaseTestCase): """ unittests that used: @@ -161,7 +155,7 @@ def test_deleted_objects(self): with reversion_api.create_revision(): factory2 = Factory.objects.create(name="factory two", address="1 Fake Plaza") - car.manufacturer=factory2 + car.manufacturer = factory2 car.save() with reversion_api.create_revision(): @@ -173,9 +167,8 @@ def test_deleted_objects(self): # response = self.client.get("/admin/tests/car/%s/history/" % car.pk) # debug_response(response) # from django-tools - - response = self.client.get( + self.client.get( "/admin/tests/car/%s/history/compare/" % car.pk, - data={"version_id2":version_ids[0], "version_id1":version_ids[1]} + data={"version_id2": version_ids[0], "version_id1": version_ids[1]} ) # debug_response(response) # from django-tools diff --git a/tests/test_factory_car_reverse_models.py b/tests/test_factory_car_reverse_models.py index b034d079..310978bf 100644 --- a/tests/test_factory_car_reverse_models.py +++ b/tests/test_factory_car_reverse_models.py @@ -27,14 +27,13 @@ " - Original error: %s" ) % err raise ImportError(msg) -from django_tools.unittest_utils.BrowserDebug import debug_response from reversion_compare import reversion_api - from .models import Factory, Car, Person from .test_utils.test_cases import BaseTestCase from .test_utils.test_data import TestData + class FactoryCarReverseRelationModelTest(BaseTestCase): """ unittests that used: @@ -48,7 +47,7 @@ def setUp(self): reversion_api.unregister(Person) reversion_api.unregister(Car) reversion_api.unregister(Factory) - reversion_api.register(Factory, follow=["building_ptr","cars","workers"]) + reversion_api.register(Factory, follow=["building_ptr", "cars", "workers"]) reversion_api.register(Car) reversion_api.register(Person, follow=["pets"]) super(FactoryCarReverseRelationModelTest, self).setUp() @@ -61,15 +60,16 @@ def setUp(self): def test_initial_state(self): self.assertTrue(reversion_api.is_registered(Factory)) self.assertTrue(reversion_api.is_registered(Car)) + self.assertTrue(reversion_api.is_registered(Person)) self.assertEqual(reversion_api.Revision.objects.all().count(), 3) self.assertEqual(len(self.version_ids), 3) self.assertEqual(reversion_api.Version.objects.all().count(), 19) def test_select_compare(self): response = self.client.get("/admin/tests/factory/%s/history/" % self.factory.pk) -# debug_response(response) # from django-tools - - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '', '' % self.version_ids[0], '' % self.version_ids[0], @@ -79,14 +79,14 @@ def test_select_compare(self): '' % self.version_ids[2], ) - def test_diff1(self): response = self.client.get( "/admin/tests/factory/%s/history/compare/" % self.factory.pk, - data={"version_id2":self.version_ids[2], "version_id1":self.version_ids[1]} + data={"version_id2": self.version_ids[1], "version_id1": self.version_ids[2]} ) - #debug_response(response) # from django-tools - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '''

- motor-car three from factory one supplier(s): → Deleted
@@ -99,6 +99,5 @@ def test_diff1(self): + Bob Bobertson

''', - '
version 2: discontinued car-three, add car-four, add Bob the worker
', # edit comment + '
version 2: discontinued car-three, add car-four, add Bob the worker
', # edit comment ) - diff --git a/tests/test_onetoone_field.py b/tests/test_onetoone_field.py index 01ed783a..a105793c 100644 --- a/tests/test_onetoone_field.py +++ b/tests/test_onetoone_field.py @@ -16,7 +16,6 @@ from __future__ import absolute_import, division, print_function - try: import django_tools except ImportError as err: @@ -27,11 +26,7 @@ ) % err raise ImportError(msg) -try: - from reversion.revisions import get_for_object -except ImportError: - from reversion import get_for_object - +from reversion_compare import reversion_api from .test_utils.test_cases import BaseTestCase from .test_utils.test_data import TestData @@ -44,13 +39,14 @@ def setUp(self): test_data = TestData(verbose=False) self.person, self.item = test_data.create_PersonIdentity_data() - queryset = get_for_object(self.person) + queryset = reversion_api.get_for_object(self.person) self.version_ids = queryset.values_list("pk", flat=True) def test_select_compare(self): response = self.client.get("/admin/tests/person/%s/history/" % self.person.pk) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, '', '' % self.version_ids[0], '' % self.version_ids[0], @@ -61,10 +57,11 @@ def test_select_compare(self): def test_compare(self): response = self.client.get( "/admin/tests/person/%s/history/compare/" % self.person.pk, - data={"version_id2":self.version_ids[0], "version_id1":self.version_ids[1]} + data={"version_id2": self.version_ids[0], "version_id1": self.version_ids[1]} ) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, """
                 - Dave
diff --git a/tests/test_person_pet_models.py b/tests/test_person_pet_models.py
index 6bf7dabc..71e7b2dd 100644
--- a/tests/test_person_pet_models.py
+++ b/tests/test_person_pet_models.py
@@ -17,7 +17,6 @@
 
 from __future__ import absolute_import, division, print_function
 
-
 try:
     import django_tools
 except ImportError as err:
@@ -28,17 +27,14 @@
     ) % err
     raise ImportError(msg)
 
-
 from reversion_compare import reversion_api
-
-
 from tests.models import Person, Pet
 
 # Needs to import admin module to register all models via CompareVersionAdmin/VersionAdmin
-
 from .test_utils.test_cases import BaseTestCase
 from .test_utils.test_data import TestData
 
+
 class PersonPetModelTest(BaseTestCase):
     """
     unittests that used:
@@ -55,7 +51,7 @@ def setUp(self):
         super(PersonPetModelTest, self).setUp()
 
         test_data = TestData(verbose=False)
-#        test_data = TestData(verbose=True)
+        # test_data = TestData(verbose=True)
         self.pet1, self.pet2, self.person = test_data.create_PersonPet_data()
 
         queryset = reversion_api.get_for_object(self.person)
@@ -72,8 +68,9 @@ def test_initial_state(self):
 
     def test_select_compare(self):
         response = self.client.get("/admin/tests/person/%s/history/" % self.person.pk)
-#        debug_response(response) # from django-tools
-        self.assertContainsHtml(response,
+        # debug_response(response) # from django-tools
+        self.assertContainsHtml(
+            response,
             '',
             '' % self.version_ids[0],
             '' % self.version_ids[0],
@@ -84,11 +81,11 @@ def test_select_compare(self):
     def test_diff(self):
         response = self.client.get(
             "/admin/tests/person/%s/history/compare/" % self.person.pk,
-            data={"version_id2":self.version_ids[0], "version_id1":self.version_ids[1]}
+            data={"version_id2": self.version_ids[0], "version_id1": self.version_ids[1]}
         )
-#        debug_response(response) # from django-tools
-
-        self.assertContainsHtml(response,
+        # debug_response(response) # from django-tools
+        self.assertContainsHtml(
+            response,
             """
             

would be changed petIs changed pet
@@ -97,11 +94,12 @@ def test_diff(self): always the same pet

""", - "
version 2: change follow related pets.
", # edit comment + "
version 2: change follow related pets.
", # edit comment ) - self.assertNotContainsHtml(response, - "

name

", # person name doesn't changed - 'class="follow"'# All fields are under reversion control + self.assertNotContainsHtml( + response, + "

name

", # person name doesn't changed + 'class="follow"' # All fields are under reversion control ) def test_add_m2m(self): @@ -119,8 +117,9 @@ def test_add_m2m(self): self.assertEqual(len(version_ids), 3) response = self.client.get("/admin/tests/person/%s/history/" % self.person.pk) -# debug_response(response) # from django-tools - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '', '' % version_ids[0], '' % version_ids[0], @@ -132,11 +131,12 @@ def test_add_m2m(self): response = self.client.get( "/admin/tests/person/%s/history/compare/" % self.person.pk, - data={"version_id2":version_ids[0], "version_id1":version_ids[1]} + data={"version_id2": version_ids[0], "version_id1": version_ids[1]} ) -# debug_response(response) # from django-tools + # debug_response(response) # from django-tools - self.assertContainsHtml(response, + self.assertContainsHtml( + response, """

+ added pet
@@ -144,11 +144,12 @@ def test_add_m2m(self): always the same pet

""", - "
version 3: add a pet
", # edit comment + "
version 3: add a pet
", # edit comment ) - self.assertNotContainsHtml(response, - "

name

", # person name doesn't changed - 'class="follow"'# All fields are under reversion control + self.assertNotContainsHtml( + response, + "

name

", # person name doesn't changed + 'class="follow"' # All fields are under reversion control ) def test_m2m_not_changed(self): @@ -165,8 +166,9 @@ def test_m2m_not_changed(self): self.assertEqual(len(version_ids), 3) response = self.client.get("/admin/tests/person/%s/history/" % self.person.pk) -# debug_response(response) # from django-tools - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '', '' % version_ids[0], '' % version_ids[0], @@ -178,22 +180,22 @@ def test_m2m_not_changed(self): response = self.client.get( "/admin/tests/person/%s/history/compare/" % self.person.pk, - data={"version_id2":version_ids[0], "version_id1":version_ids[1]} + data={"version_id2": version_ids[0], "version_id1": version_ids[1]} ) -# debug_response(response) # from django-tools + # debug_response(response) # from django-tools - self.assertContainsHtml(response, + self.assertContainsHtml( + response, '''

             - Dave
             + David
             

''', - "
version 3: change the name
", # edit comment + "
version 3: change the name
", # edit comment ) - self.assertNotContainsHtml(response, + self.assertNotContainsHtml( + response, "pet", - 'class="follow"'# All fields are under reversion control + 'class="follow"' # All fields are under reversion control ) - - diff --git a/tests/test_settings.py b/tests/test_settings.py index 1e378a28..bc00297f 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -15,8 +15,6 @@ 'django.contrib.messages.middleware.MessageMiddleware', "reversion.middleware.RevisionMiddleware", - - #'django_tools.middlewares.QueryLogMiddleware.QueryLogMiddleware', ) LANGUAGE_CODE = "en" @@ -58,7 +56,7 @@ } } -DEBUG=True +DEBUG = True # add reversion models to django admin: -ADD_REVERSION_ADMIN=True \ No newline at end of file +ADD_REVERSION_ADMIN = True \ No newline at end of file diff --git a/tests/test_simple_model.py b/tests/test_simple_model.py index c542a122..9e446a61 100644 --- a/tests/test_simple_model.py +++ b/tests/test_simple_model.py @@ -26,12 +26,8 @@ " - Original error: %s" ) % err raise ImportError(msg) -from django_tools.unittest_utils.BrowserDebug import debug_response - from reversion_compare import reversion_api, helpers - - from .test_utils.test_cases import BaseTestCase from .models import SimpleModel from .test_utils.test_data import TestData @@ -46,7 +42,7 @@ class SimpleModelTest(BaseTestCase): def setUp(self): super(SimpleModelTest, self).setUp() test_data = TestData(verbose=False) -# test_data = TestData(verbose=True) + # test_data = TestData(verbose=True) self.item1, self.item2 = test_data.create_Simple_data() queryset = reversion_api.get_for_object(self.item1) @@ -72,8 +68,9 @@ def test_initial_state(self): def test_select_compare1(self): response = self.client.get("/admin/tests/simplemodel/%s/history/" % self.item1.pk) -# debug_response(response) # from django-tools - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '', '' % self.version_ids1[0], '' % self.version_ids1[0], @@ -85,12 +82,13 @@ def test_select_compare2(self): response = self.client.get("/admin/tests/simplemodel/%s/history/" % self.item2.pk) # debug_response(response) # from django-tools for i in range(4): - if i==0: + if i == 0: comment = "create v%i" % i else: comment = "change to v%i" % i - self.assertContainsHtml(response, + self.assertContainsHtml( + response, "%s" % comment, '', ) @@ -98,42 +96,45 @@ def test_select_compare2(self): def test_diff(self): response = self.client.get( "/admin/tests/simplemodel/%s/history/compare/" % self.item1.pk, - data={"version_id2":self.version_ids1[0], "version_id1":self.version_ids1[1]} + data={"version_id2": self.version_ids1[0], "version_id1": self.version_ids1[1]} ) - #debug_response(response) # from django-tools - - self.assertContainsHtml(response, + # debug_response(response) # from django-tools + self.assertContainsHtml( + response, '- version one', '+ version two', - '
simply change the CharField text.
', # edit comment + '
simply change the CharField text.
', # edit comment ) if self.google_diff_match_patch: # google-diff-match-patch is available helpers.google_diff_match_patch = True try: - self.assertContainsHtml(response, + self.assertContainsHtml( + response, """

version one two

""", - '
simply change the CharField text.
', # edit comment + '
simply change the CharField text.
', # edit comment ) finally: helpers.google_diff_match_patch = False # revert def test_prev_next_buttons(self): - base_url="/admin/tests/simplemodel/%s/history/compare/" % self.item2.pk + base_url = "/admin/tests/simplemodel/%s/history/compare/" % self.item2.pk for i in range(4): # IDs: 3,4,5,6 - id1=i+3 - id2=i+4 - response = self.client.get(base_url, - data={"version_id2":id2, "version_id1":id1} + id1 = i+3 + id2 = i+4 + response = self.client.get( + base_url, + data={"version_id2": id2, "version_id1": id1} ) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, '- v%i' % i, '+ v%i' % (i+1), '
change to v%i
' % (i+1), @@ -142,7 +143,6 @@ def test_prev_next_buttons(self): # for line in response.content.decode("utf-8").split("\n"): # if "next" in line or "previous" in line: # print(line) - """ +++ 0
  • next ›
  • @@ -157,17 +157,17 @@ def test_prev_next_buttons(self): """ next = 'next ›' % (i+4, i+5) - prev = '‹ previous' % (i+2,i+3) + prev = '‹ previous' % (i+2, i+3) - if i==0: + if i == 0: self.assertNotContains(response, "previous") self.assertContains(response, "next") self.assertContainsHtml(response, next) - elif i==3: + elif i == 3: self.assertContains(response, "previous") self.assertNotContains(response, "next") self.assertContainsHtml(response, prev) else: self.assertContains(response, "previous") self.assertContains(response, "next") - self.assertContainsHtml(response, prev, next) \ No newline at end of file + self.assertContainsHtml(response, prev, next) diff --git a/tests/test_utils/test_cases.py b/tests/test_utils/test_cases.py index c946d897..5c5b7dae 100644 --- a/tests/test_utils/test_cases.py +++ b/tests/test_utils/test_cases.py @@ -29,14 +29,11 @@ " - Original error: %s" ) % err raise ImportError(msg) -from django_tools.unittest_utils.BrowserDebug import debug_response - +from django_tools.unittest_utils.BrowserDebug import debug_response from reversion_compare import reversion_api, helpers - # Needs to import admin module to register all models via CompareVersionAdmin/VersionAdmin -from tests.admin import custom_revision_manager from .test_data import TestData @@ -73,7 +70,7 @@ def assertContainsHtml(self, response, *args): try: self.assertContains(response, html, html=True) except AssertionError as e: - debug_response(response, msg="%s" % e) # from django-tools + debug_response(response, msg="%s" % e) # from django-tools raise def assertNotContainsHtml(self, response, *args): @@ -81,7 +78,7 @@ def assertNotContainsHtml(self, response, *args): try: self.assertNotContains(response, html, html=True) except AssertionError as e: - debug_response(response, msg="%s" % e) # from django-tools + debug_response(response, msg="%s" % e) # from django-tools raise @@ -96,6 +93,5 @@ def test_model_registering(self): models = test_app_config.get_models( include_auto_created=False, include_deferred=False, include_swapped=False ) - default_registered = len(reversion_api.get_registered_models()) - custom_registered = len(custom_revision_manager.get_registered_models()) - self.assertEqual(default_registered + custom_registered, len(tuple(models))) + default_registered = len(list(reversion_api.get_registered_models())) + self.assertEqual(default_registered, len(tuple(models))) diff --git a/tests/test_utils/test_data.py b/tests/test_utils/test_data.py index 9e892c1f..a055f369 100644 --- a/tests/test_utils/test_data.py +++ b/tests/test_utils/test_data.py @@ -35,13 +35,8 @@ ) % err raise ImportError(msg) - from reversion_compare import reversion_api - - -from tests.models import SimpleModel, Person, Pet, \ - Factory, Car, VariantModel, CustomModel, Identity - +from tests.models import SimpleModel, Person, Pet, Factory, Car, VariantModel, CustomModel, Identity class TestData(object): @@ -50,8 +45,8 @@ class TestData(object): This will be also used from external scripts, too! """ - TEST_USERNAME="test" - TEST_USERPASS="12345678" + TEST_USERNAME = "test" + TEST_USERPASS = "12345678" def __init__(self, verbose=False): self.verbose = verbose @@ -68,7 +63,6 @@ def create_all(self): func = getattr(self, method_name) func() - def create_testuser_data(self): if self.verbose: print("\t+++ user name.......: %r" % self.TEST_USERNAME) @@ -94,7 +88,7 @@ def create_Simple_data(self): for no in range(5): with reversion_api.create_revision(): - if no==0: + if no == 0: item2 = SimpleModel.objects.create(text="v0") reversion_api.set_comment("create v%i" % no) else: @@ -227,6 +221,7 @@ def create_Factory_reverse_relation_data(self): name="Bob Bobertson", workplace=manufacturer ) + worker1.save() manufacturer.save() reversion_api.set_comment("version 2: discontinued car-three, add car-four, add Bob the worker") @@ -329,6 +324,8 @@ def create_VariantModel_data(self): email = "one@foo-bar.com", url = "http://www.pylucid.org/", + file_field = os.path.join(settings.UNITTEST_TEMP_PATH, "foo"), + filepath = os.path.join(settings.UNITTEST_TEMP_PATH, "foo"), ip_address = "192.168.0.1", @@ -357,6 +354,7 @@ def create_VariantModel_data(self): ("float", 3.1415), ("email", "two@foo-bar.com"), ("url", "https://github.com/jedie/"), + ("file_field", os.path.join(settings.UNITTEST_TEMP_PATH, "bar")), ("filepath", os.path.join(settings.UNITTEST_TEMP_PATH, "bar")), ("ip_address", "10.0.0.0"), ) @@ -377,7 +375,6 @@ def create_CustomModel_data(self): return item1 - def create_PersonIdentity_data(self): with reversion_api.create_revision(): person = Person.objects.create(name="Dave") diff --git a/tests/test_variant_model.py b/tests/test_variant_model.py index 31e31c36..61572c9d 100644 --- a/tests/test_variant_model.py +++ b/tests/test_variant_model.py @@ -20,7 +20,6 @@ import os from django.conf import settings - try: import django_tools except ImportError as err: @@ -30,14 +29,10 @@ " - Original error: %s" ) % err raise ImportError(msg) -from django_tools.unittest_utils.BrowserDebug import debug_response - from reversion_compare import reversion_api - from tests.models import VariantModel # Needs to import admin module to register all models via CompareVersionAdmin/VersionAdmin - from .test_utils.test_cases import BaseTestCase from .test_utils.test_data import TestData @@ -71,12 +66,10 @@ def test_textfield(self): last line""" item.save() - # debug_response(self.client.get("/admin/tests/variantmodel/1/history/")) response = self.client.get( "/admin/tests/variantmodel/1/history/compare/", data={"version_id2": 1, "version_id1": 2} ) - # debug_response(response) # from django-tools self.assertContains(response, """\ -nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit @@ -111,7 +104,6 @@ def test_initial_state(self): def test_all_changes(self): # debug_response(self.client.get("/admin/tests/variantmodel/1/history/")) - # compare initial with last version response = self.client.get( "/admin/tests/variantmodel/1/history/compare/", @@ -120,14 +112,14 @@ def test_all_changes(self): "version_id1": len(self.test_data) + 1 # incl. initial } ) - # debug_response(response) # from django-tools field_headlines = [ "

    %s

    " % field_name.replace("_", " ") for field_name, value in self.test_data ] self.assertContainsHtml(response, *field_headlines) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, "

    boolean

    ", '

    False changed to: True

    ', @@ -191,8 +183,8 @@ def test_all_changes(self): "+ https://github.com/jedie/", "

    filepath

    ", - #"- %s/foo" % settings.UNITTEST_TEMP_PATH, - #"+ %s/bar" % settings.UNITTEST_TEMP_PATH, + # "- %s/foo" % settings.UNITTEST_TEMP_PATH, + # "+ %s/bar" % settings.UNITTEST_TEMP_PATH, "- %s" % os.path.join(settings.UNITTEST_TEMP_PATH, 'foo'), "+ %s" % os.path.join(settings.UNITTEST_TEMP_PATH, 'bar'), diff --git a/tests/test_view.py b/tests/test_view.py index 50885f99..ad3549d7 100644 --- a/tests/test_view.py +++ b/tests/test_view.py @@ -23,12 +23,9 @@ " - Original error: %s" ) % err raise ImportError(msg) -from django_tools.unittest_utils.BrowserDebug import debug_response from reversion_compare import reversion_api - - from .test_utils.test_cases import BaseTestCase from .models import SimpleModel from .test_utils.test_data import TestData @@ -65,7 +62,8 @@ def test_initial_state(self): def test_select_compare1(self): response = self.client.get("/test_view/%s" % self.item1.pk) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, '', '' % self.version_ids1[0], '' % self.version_ids1[0], @@ -75,56 +73,63 @@ def test_select_compare1(self): def test_select_compare2(self): response = self.client.get("/test_view/%s" % self.item2.pk) - # debug_response(response) # from django-tools for i in range(4): - if i==0: + if i == 0: comment = "create v%i" % i else: comment = "change to v%i" % i - self.assertContainsHtml(response, + self.assertContainsHtml( + response, "%s" % comment, '', ) def test_select_compare_and_diff(self): - response = self.client.get("/test_view/%s" % self.item1.pk, data={"version_id2":self.version_ids1[0], "version_id1":self.version_ids1[1]}) - self.assertContainsHtml(response, + response = self.client.get("/test_view/%s" % self.item1.pk, data={ + "version_id2": self.version_ids1[0], + "version_id1": self.version_ids1[1] + }) + self.assertContainsHtml( + response, '', '' % self.version_ids1[0], '' % self.version_ids1[0], '' % self.version_ids1[1], '' % self.version_ids1[1], ) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, '- version one', '+ version two', - '
    simply change the CharField text.
    ', # edit comment + '
    simply change the CharField text.
    ', # edit comment ) def test_prev_next_buttons(self): - base_url="/test_view/%s" % self.item2.pk + base_url = "/test_view/%s" % self.item2.pk for i in range(4): # IDs: 3,4,5,6 - id1=i+3 - id2=i+4 - response = self.client.get(base_url, - data={"version_id2":id2, "version_id1":id1} + id1 = i+3 + id2 = i+4 + response = self.client.get( + base_url, + data={"version_id2": id2, "version_id1": id1} ) - self.assertContainsHtml(response, + self.assertContainsHtml( + response, '- v%i' % i, '+ v%i' % (i+1), '
    change to v%i
    ' % (i+1), ) next = 'next ›' % (i+4, i+5) - prev = '‹ previous' % (i+2,i+3) + prev = '‹ previous' % (i+2, i+3) - if i==0: + if i == 0: self.assertNotContains(response, "previous") self.assertContains(response, "next") self.assertContainsHtml(response, next) - elif i==3: + elif i == 3: self.assertContains(response, "previous") self.assertNotContains(response, "next") self.assertContainsHtml(response, prev) diff --git a/tests/views.py b/tests/views.py index ac94a229..b9c856f2 100644 --- a/tests/views.py +++ b/tests/views.py @@ -2,6 +2,6 @@ from reversion_compare.views import HistoryCompareDetailView from .models import SimpleModel + class SimpleModelHistoryCompareView(HistoryCompareDetailView): model = SimpleModel - \ No newline at end of file