Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-django-reversion for openSUSE:Factory checked in at 2023-01-14 20:32:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-django-reversion (Old) and /work/SRC/openSUSE:Factory/.python-django-reversion.new.32243 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-reversion" Sat Jan 14 20:32:48 2023 rev:14 rq:1058386 version:5.0.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-django-reversion/python-django-reversion.changes 2021-12-29 21:11:18.454302837 +0100 +++ /work/SRC/openSUSE:Factory/.python-django-reversion.new.32243/python-django-reversion.changes 2023-01-14 20:32:48.953601999 +0100 @@ -1,0 +2,15 @@ +Sat Jan 7 16:58:21 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 5.0.4: + * Fix warning log formatting for failed reverts (@tony). + * A revision will no longer be created if a transaction is marked as + rollback, as this would otherwise cause an additional database error + * A warning log is now emitted if a revert fails due to database integrity + errors, making debugging the final + ``RevertError`` easier. + * Fixed doc builds on readthedocs (@etianen). + * Fix admin detail view in multi-database configuration (@atten). + * Added support for using django-reversion contexts in ``asyncio`` tasks + * Improved performance of `createinitialrevisions` management command + +------------------------------------------------------------------- Old: ---- django-reversion-4.0.1.tar.gz New: ---- django-reversion-5.0.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-django-reversion.spec ++++++ --- /var/tmp/diff_new_pack.QUNaCD/_old 2023-01-14 20:32:50.189609298 +0100 +++ /var/tmp/diff_new_pack.QUNaCD/_new 2023-01-14 20:32:50.197609346 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-django-reversion # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-django-reversion -Version: 4.0.1 +Version: 5.0.4 Release: 0 Summary: A Django extension that provides version control for model instances License: BSD-3-Clause @@ -27,6 +27,7 @@ Source: https://files.pythonhosted.org/packages/source/d/django-reversion/django-reversion-%{version}.tar.gz Patch0: only-sqlite-test-db.patch BuildRequires: %{python_module Django > 2.0} +BuildRequires: %{python_module base > 3.7} BuildRequires: %{python_module pytest-django} BuildRequires: %{python_module setuptools} BuildRequires: fdupes ++++++ django-reversion-4.0.1.tar.gz -> django-reversion-5.0.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/CHANGELOG.rst new/django-reversion-5.0.4/CHANGELOG.rst --- old/django-reversion-4.0.1/CHANGELOG.rst 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/CHANGELOG.rst 2022-11-12 15:45:23.000000000 +0100 @@ -3,6 +3,46 @@ django-reversion changelog ========================== +5.0.4 - 2022-11-12 +------------------ + +- Fix warning log formatting for failed reverts (@tony). + + +5.0.3 - 2022-10-02 +------------------ + +- A revision will no longer be created if a transaction is marked as rollback, as this would otherwise cause an + additional database error (@proofit404). +- A warning log is now emitted if a revert fails due to database integrity errors, making debugging the final + ``RevertError`` easier. + + +5.0.2 - 2022-08-06 +------------------ + +- Fixed doc builds on readthedocs (@etianen). + + +5.0.1 - 2022-06-18 +------------------ + +- Fix admin detail view in multi-database configuration (@atten). + + +5.0.0 - 2022-02-20 +------------------ + +- Added support for using django-reversion contexts in ``asyncio`` tasks (@bellini666). +- **Breaking:** Dropped support for Python 3.6. + + +4.0.2 - 2022-01-30 +------------------ + +- Improved performance of `createinitialrevisions` management command (@philipstarkey). + + 4.0.1 - 2021-11-04 ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/PKG-INFO new/django-reversion-5.0.4/PKG-INFO --- old/django-reversion-4.0.1/PKG-INFO 2021-11-04 10:01:03.002541500 +0100 +++ new/django-reversion-5.0.4/PKG-INFO 2022-11-12 15:45:34.012175800 +0100 @@ -1,25 +1,23 @@ Metadata-Version: 2.1 Name: django-reversion -Version: 4.0.1 +Version: 5.0.4 Summary: An extension to the Django web framework that provides version control for model instances. Home-page: http://github.com/etianen/django-reversion Author: Dave Hall Author-email: d...@etianen.com License: BSD -Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Framework :: Django -Requires-Python: >=3.6 +Requires-Python: >=3.7 License-File: LICENSE ================ @@ -35,8 +33,8 @@ Requirements ============ -- Python 3.6 or later -- Django 2.0 or later +- Python 3.7 or later +- Django 3.2 or later Features ======== @@ -103,5 +101,3 @@ :target: https://pypi.python.org/pypi/django-reversion .. |Github actions| image:: https://github.com/etianen/django-reversion/workflows/Python%20package/badge.svg :target: https://github.com/etianen/django-reversion - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/README.rst new/django-reversion-5.0.4/README.rst --- old/django-reversion-4.0.1/README.rst 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/README.rst 2022-11-12 15:45:23.000000000 +0100 @@ -11,8 +11,8 @@ Requirements ============ -- Python 3.6 or later -- Django 2.0 or later +- Python 3.7 or later +- Django 3.2 or later Features ======== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/django_reversion.egg-info/PKG-INFO new/django-reversion-5.0.4/django_reversion.egg-info/PKG-INFO --- old/django-reversion-4.0.1/django_reversion.egg-info/PKG-INFO 2021-11-04 10:01:02.000000000 +0100 +++ new/django-reversion-5.0.4/django_reversion.egg-info/PKG-INFO 2022-11-12 15:45:33.000000000 +0100 @@ -1,25 +1,23 @@ Metadata-Version: 2.1 Name: django-reversion -Version: 4.0.1 +Version: 5.0.4 Summary: An extension to the Django web framework that provides version control for model instances. Home-page: http://github.com/etianen/django-reversion Author: Dave Hall Author-email: d...@etianen.com License: BSD -Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Framework :: Django -Requires-Python: >=3.6 +Requires-Python: >=3.7 License-File: LICENSE ================ @@ -35,8 +33,8 @@ Requirements ============ -- Python 3.6 or later -- Django 2.0 or later +- Python 3.7 or later +- Django 3.2 or later Features ======== @@ -103,5 +101,3 @@ :target: https://pypi.python.org/pypi/django-reversion .. |Github actions| image:: https://github.com/etianen/django-reversion/workflows/Python%20package/badge.svg :target: https://github.com/etianen/django-reversion - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/django_reversion.egg-info/requires.txt new/django-reversion-5.0.4/django_reversion.egg-info/requires.txt --- old/django-reversion-4.0.1/django_reversion.egg-info/requires.txt 2021-11-04 10:01:02.000000000 +0100 +++ new/django-reversion-5.0.4/django_reversion.egg-info/requires.txt 2022-11-12 15:45:33.000000000 +0100 @@ -1 +1 @@ -django>=2.0 +django>=3.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/docs/conf.py new/django-reversion-5.0.4/docs/conf.py --- old/django-reversion-4.0.1/docs/conf.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/docs/conf.py 2022-11-12 15:45:23.000000000 +0100 @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # # django-reversion documentation build configuration file, created by # sphinx-quickstart on Thu Jun 2 08:41:36 2016. @@ -74,7 +73,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/__init__.py new/django-reversion-5.0.4/reversion/__init__.py --- old/django-reversion-4.0.1/reversion/__init__.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/__init__.py 2022-11-12 15:45:23.000000000 +0100 @@ -36,4 +36,4 @@ get_registered_models, ) -__version__ = VERSION = (4, 0, 1) +__version__ = VERSION = (5, 0, 4) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/admin.py new/django-reversion-5.0.4/reversion/admin.py --- old/django-reversion-4.0.1/reversion/admin.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/admin.py 2022-11-12 15:45:23.000000000 +0100 @@ -1,5 +1,5 @@ from contextlib import contextmanager -from django.db import models, transaction, connection +from django.db import models, transaction, connections from django.contrib import admin, messages from django.contrib.admin import options from django.contrib.admin.utils import unquote, quote @@ -53,8 +53,8 @@ def _reversion_get_template_list(self, template_name): opts = self.model._meta return ( - "reversion/%s/%s/%s" % (opts.app_label, opts.object_name.lower(), template_name), - "reversion/%s/%s" % (opts.app_label, template_name), + f"reversion/{opts.app_label}/{opts.object_name.lower()}/{template_name}", + f"reversion/{opts.app_label}/{template_name}", "reversion/%s" % template_name, ) @@ -163,7 +163,7 @@ def _reversion_revisionform_view(self, request, version, template_name, extra_context=None): # Check that database transactions are supported. - if not connection.features.uses_savepoints: + if not connections[version.db].features.uses_savepoints: raise ImproperlyConfigured("Cannot use VersionAdmin with a database that does not support savepoints.") # Run the view. try: @@ -185,7 +185,7 @@ except (RevertError, models.ProtectedError) as ex: opts = self.model._meta messages.error(request, force_str(ex)) - return redirect("{}:{}_{}_changelist".format(self.admin_site.name, opts.app_label, opts.model_name)) + return redirect(f"{self.admin_site.name}:{opts.app_label}_{opts.model_name}_changelist") except _RollBackRevisionView as ex: return ex.response return response @@ -275,7 +275,7 @@ { "revision": version.revision, "url": reverse( - "%s:%s_%s_revision" % (self.admin_site.name, opts.app_label, opts.model_name), + f"{self.admin_site.name}:{opts.app_label}_{opts.model_name}_revision", args=(quote(version.object_id), version.id) ), } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/management/commands/__init__.py new/django-reversion-5.0.4/reversion/management/commands/__init__.py --- old/django-reversion-4.0.1/reversion/management/commands/__init__.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/management/commands/__init__.py 2022-11-12 15:45:23.000000000 +0100 @@ -43,7 +43,7 @@ try: model = apps.get_model(label) except LookupError: - raise CommandError("Unknown model: {}".format(label)) + raise CommandError(f"Unknown model: {label}") selected_models.add(model) else: # This is just an app - no model qualifier. @@ -51,7 +51,7 @@ try: app = apps.get_app_config(app_label) except LookupError: - raise CommandError("Unknown app: {}".format(app_label)) + raise CommandError(f"Unknown app: {app_label}") selected_models.update(app.get_models()) for model in selected_models: if is_registered(model): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/management/commands/createinitialrevisions.py new/django-reversion-5.0.4/reversion/management/commands/createinitialrevisions.py --- old/django-reversion-4.0.1/reversion/management/commands/createinitialrevisions.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/management/commands/createinitialrevisions.py 2022-11-12 15:45:23.000000000 +0100 @@ -2,7 +2,7 @@ from django.apps import apps from django.core.management import CommandError -from django.db import reset_queries, transaction, router +from django.db import connections, reset_queries, transaction, router from reversion.models import Revision, Version, _safe_subquery from reversion.management.commands import BaseRevisionCommand from reversion.revisions import create_revision, set_comment, add_to_revision, add_meta @@ -48,10 +48,13 @@ model = apps.get_model(label) meta_models.append(model) except LookupError: - raise CommandError("Unknown model: {}".format(label)) + raise CommandError(f"Unknown model: {label}") meta_values = meta.values() - # Create revisions. + # Determine if we should use queryset.iterator() using = using or router.db_for_write(Revision) + server_side_cursors = not connections[using].settings_dict.get('DISABLE_SERVER_SIDE_CURSORS') + use_iterator = connections[using].vendor in ("postgresql",) and server_side_cursors + # Create revisions. with transaction.atomic(using=using): for model in self.get_models(options): # Check all models for empty revisions. @@ -70,28 +73,48 @@ ), "object_id", ) + live_objs = live_objs.order_by() # Save all the versions. - ids = list(live_objs.values_list("pk", flat=True).order_by()) - total = len(ids) - for i in range(0, total, batch_size): - chunked_ids = ids[i:i+batch_size] - objects = live_objs.in_bulk(chunked_ids) - for obj in objects.values(): - with create_revision(using=using): - if meta: - for model, values in zip(meta_models, meta_values): - add_meta(model, **values) - set_comment(comment) - add_to_revision(obj, model_db=model_db) - created_count += 1 - reset_queries() - if verbosity >= 2: - self.stdout.write("- Created {created_count} / {total}".format( - created_count=created_count, - total=total, - )) + if use_iterator: + total = live_objs.count() + if total: + for obj in live_objs.iterator(batch_size): + self.create_revision(obj, using, meta, meta_models, meta_values, comment, model_db) + created_count += 1 + # Print out a message every batch_size if feeling extra verbose + if not created_count % batch_size: + self.batch_complete(verbosity, created_count, total) + else: + # Save all the versions. + ids = list(live_objs.values_list("pk", flat=True)) + total = len(ids) + for i in range(0, total, batch_size): + chunked_ids = ids[i:i+batch_size] + objects = live_objs.in_bulk(chunked_ids) + for obj in objects.values(): + self.create_revision(obj, using, meta, meta_models, meta_values, comment, model_db) + created_count += 1 + # Print out a message every batch_size if feeling extra verbose + self.batch_complete(verbosity, created_count, total) + # Print out a message, if feeling verbose. if verbosity >= 1: self.stdout.write("- Created {total} / {total}".format( total=total, )) + + def create_revision(self, obj, using, meta, meta_models, meta_values, comment, model_db): + with create_revision(using=using): + if meta: + for model, values in zip(meta_models, meta_values): + add_meta(model, **values) + set_comment(comment) + add_to_revision(obj, model_db=model_db) + + def batch_complete(self, verbosity, created_count, total): + reset_queries() + if verbosity >= 2: + self.stdout.write("- Created {created_count} / {total}".format( + created_count=created_count, + total=total, + )) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/migrations/0001_squashed_0004_auto_20160611_1202.py new/django-reversion-5.0.4/reversion/migrations/0001_squashed_0004_auto_20160611_1202.py --- old/django-reversion-4.0.1/reversion/migrations/0001_squashed_0004_auto_20160611_1202.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/migrations/0001_squashed_0004_auto_20160611_1202.py 2022-11-12 15:45:23.000000000 +0100 @@ -44,6 +44,6 @@ ), migrations.AlterUniqueTogether( name='version', - unique_together=set([('db', 'content_type', 'object_id', 'revision')]), + unique_together={('db', 'content_type', 'object_id', 'revision')}, ), ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/models.py new/django-reversion-5.0.4/reversion/models.py --- old/django-reversion-4.0.1/reversion/models.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/models.py 2022-11-12 15:45:23.000000000 +0100 @@ -1,5 +1,6 @@ from collections import defaultdict from itertools import chain, groupby +import logging import django from django.apps import apps @@ -22,6 +23,9 @@ _get_content_type, _get_options) +logger = logging.getLogger(__name__) + + def _safe_revert(versions): unreverted_versions = [] for version in versions: @@ -29,6 +33,7 @@ with transaction.atomic(using=version.db): version.revert() except (IntegrityError, ObjectDoesNotExist): + logger.warning(f'Could not revert to {version}', exc_info=True) unreverted_versions.append(version) if len(unreverted_versions) == len(versions): raise RevertError(gettext("Could not save %(object_repr)s version - missing dependency.") % { @@ -366,25 +371,25 @@ ) ): return getattr(left_query, method)(**{ - "{}__in".format(left_field_name): list(right_subquery.iterator()), + f"{left_field_name}__in": list(right_subquery.iterator()), }) else: # If the left hand side is not a text field, we need to cast it. if not isinstance(left_field, (models.CharField, models.TextField)): - left_field_name_str = "{}_str".format(left_field_name) + left_field_name_str = f"{left_field_name}_str" left_query = left_query.annotate(**{ left_field_name_str: _Str(left_field_name), }) left_field_name = left_field_name_str # If the right hand side is not a text field, we need to cast it. if not isinstance(right_field, (models.CharField, models.TextField)): - right_field_name_str = "{}_str".format(right_field_name) + right_field_name_str = f"{right_field_name}_str" right_subquery = right_subquery.annotate(**{ right_field_name_str: _Str(right_field_name), }).values_list(right_field_name_str, flat=True) right_field_name = right_field_name_str # Use Exists if running on the same DB, it is much much faster - exist_annotation_name = "{}_annotation_str".format(right_subquery.model._meta.db_table) + exist_annotation_name = f"{right_subquery.model._meta.db_table}_annotation_str" right_subquery = right_subquery.filter(**{right_field_name: models.OuterRef(left_field_name)}) left_query = left_query.annotate(**{exist_annotation_name: models.Exists(right_subquery)}) return getattr(left_query, method)(**{exist_annotation_name: True}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/revisions.py new/django-reversion-5.0.4/reversion/revisions.py --- old/django-reversion-4.0.1/reversion/revisions.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/revisions.py 2022-11-12 15:45:23.000000000 +0100 @@ -1,7 +1,7 @@ +from contextvars import ContextVar from collections import namedtuple, defaultdict from contextlib import contextmanager from functools import wraps -from threading import local from django.apps import apps from django.core import serializers from django.core.exceptions import ObjectDoesNotExist @@ -34,23 +34,17 @@ )) -class _Local(local): - - def __init__(self): - self.stack = () - - -_local = _Local() +_stack = ContextVar("reversion-stack", default=[]) def is_active(): - return bool(_local.stack) + return bool(_stack.get()) def _current_frame(): if not is_active(): raise RevisionManagementError("There is no active revision for this thread") - return _local.stack[-1] + return _stack.get()[-1] def _copy_db_versions(db_versions): @@ -79,16 +73,17 @@ db_versions={using: {}}, meta=(), ) - _local.stack += (stack_frame,) + _stack.set(_stack.get() + [stack_frame]) def _update_frame(**kwargs): - _local.stack = _local.stack[:-1] + (_current_frame()._replace(**kwargs),) + _stack.get()[-1] = _current_frame()._replace(**kwargs) def _pop_frame(): prev_frame = _current_frame() - _local.stack = _local.stack[:-1] + stack = _stack.get() + del stack[-1] if is_active(): current_frame = _current_frame() db_versions = { @@ -147,8 +142,7 @@ if isinstance(follow_obj, models.Model): yield follow_obj elif isinstance(follow_obj, (models.Manager, QuerySet)): - for follow_obj_instance in follow_obj.all(): - yield follow_obj_instance + yield from follow_obj.all() elif follow_obj is not None: raise RegistrationError("{name}.{follow_name} should be a Model or QuerySet".format( name=obj.__class__.__name__, @@ -283,8 +277,15 @@ _push_frame(manage_manually, using) try: yield + if transaction.get_connection(using).in_atomic_block and transaction.get_rollback(using): + # Transaction is in invalid state due to catched exception within yield statement. + # Do not try to create Revision, otherwise it would lead to the transaction management error. + # + # Atomic block could be called manually around `create_revision` context manager. + # That's why we have to check connection flag instead of `atomic` variable value. + return # Only save for a db if that's the last stack frame for that db. - if not any(using in frame.db_versions for frame in _local.stack[:-1]): + if not any(using in frame.db_versions for frame in _stack.get()[:-1]): current_frame = _current_frame() _save_revision( versions=current_frame.db_versions[using].values(), @@ -304,7 +305,7 @@ return _ContextWrapper(_create_revision_context, (manage_manually, using, atomic)) -class _ContextWrapper(object): +class _ContextWrapper: def __init__(self, func, args): self._func = func diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/reversion/views.py new/django-reversion-5.0.4/reversion/views.py --- old/django-reversion-4.0.1/reversion/views.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/reversion/views.py 2022-11-12 15:45:23.000000000 +0100 @@ -34,7 +34,7 @@ return decorator -class RevisionMixin(object): +class RevisionMixin: """ A class-based view mixin that wraps the request in a revision. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/setup.py new/django-reversion-5.0.4/setup.py --- old/django-reversion-4.0.1/setup.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/setup.py 2022-11-12 15:45:23.000000000 +0100 @@ -16,7 +16,7 @@ def read(filepath): - with open(filepath, "r", encoding="utf-8") as f: + with open(filepath, encoding="utf-8") as f: return f.read() @@ -35,9 +35,9 @@ "reversion": ["locale/*/LC_MESSAGES/django.*", "templates/reversion/*.html"]}, cmdclass=cmdclass, install_requires=[ - "django>=2.0", + "django>=3.2", ], - python_requires='>=3.6', + python_requires='>=3.7', classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", @@ -45,7 +45,6 @@ "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_app/migrations/0001_initial.py new/django-reversion-5.0.4/tests/test_app/migrations/0001_initial.py --- old/django-reversion-4.0.1/tests/test_app/migrations/0001_initial.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_app/migrations/0001_initial.py 2022-11-12 15:45:23.000000000 +0100 @@ -108,4 +108,11 @@ ('revision', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='reversion.revision')), ], ), + migrations.CreateModel( + name='TestModelWithUniqueConstraint', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=191, unique=True)), + ], + ), ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_app/models.py new/django-reversion-5.0.4/tests/test_app/models.py --- old/django-reversion-4.0.1/tests/test_app/models.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_app/models.py 2022-11-12 15:45:23.000000000 +0100 @@ -142,3 +142,11 @@ TestModelWithNaturalKey, on_delete=models.CASCADE, ) + + +class TestModelWithUniqueConstraint(models.Model): + + name = models.CharField( + max_length=191, + unique=True, + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_app/tests/base.py new/django-reversion-5.0.4/tests/test_app/tests/base.py --- old/django-reversion-4.0.1/tests/test_app/tests/base.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_app/tests/base.py 2022-11-12 15:45:23.000000000 +0100 @@ -17,9 +17,9 @@ # Test helpers. -class TestBaseMixin(object): +class TestBaseMixin: - multi_db = True + databases = "__all__" def reloadUrls(self): reload(import_module(settings.ROOT_URLCONF)) @@ -76,7 +76,7 @@ pass -class TestModelMixin(object): +class TestModelMixin: def setUp(self): super().setUp() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_app/tests/test_admin.py new/django-reversion-5.0.4/tests/test_app/tests/test_admin.py --- old/django-reversion-4.0.1/tests/test_app/tests/test_admin.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_app/tests/test_admin.py 2022-11-12 15:45:23.000000000 +0100 @@ -218,7 +218,7 @@ response = self.client.get(history_url) self.assertContains(response, revision_url) response = self.client.get(revision_url) - self.assertContains(response, 'value="{}"'.format(pk)) + self.assertContains(response, f'value="{pk}"') class TestModelInlineAdmin(admin.TabularInline): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_app/tests/test_api.py new/django-reversion-5.0.4/tests/test_app/tests/test_api.py --- old/django-reversion-4.0.1/tests/test_app/tests/test_api.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_app/tests/test_api.py 2022-11-12 15:45:23.000000000 +0100 @@ -32,7 +32,7 @@ class GetRegisteredModelsTest(TestModelMixin, TestBase): def testGetRegisteredModels(self): - self.assertEqual(set(reversion.get_registered_models()), set((TestModel,))) + self.assertEqual(set(reversion.get_registered_models()), {TestModel}) class RegisterTest(TestBase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_app/tests/test_models.py new/django-reversion-5.0.4/tests/test_app/tests/test_models.py --- old/django-reversion-4.0.1/tests/test_app/tests/test_models.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_app/tests/test_models.py 2022-11-12 15:45:23.000000000 +0100 @@ -4,6 +4,7 @@ TestModel, TestModelRelated, TestModelParent, TestModelInline, TestModelNestedInline, TestModelInlineByNaturalKey, TestModelWithNaturalKey, + TestModelWithUniqueConstraint, ) from test_app.tests.base import TestBase, TestModelMixin, TestModelParentMixin import json @@ -317,7 +318,7 @@ obj.related.add(v1) obj.related.add(v2) version = Version.objects.get_for_object(obj).first() - self.assertEqual(set(version.field_dict["related"]), set((v1.pk, v2.pk,))) + self.assertEqual(set(version.field_dict["related"]), {v1.pk, v2.pk}) class RevertTest(TestModelMixin, TestBase): @@ -443,3 +444,17 @@ 'test_model_id': 1, 'id': 1, }) + + +class TransactionRollbackTest(TestBase): + + def setUp(self): + reversion.register(TestModelWithUniqueConstraint) + + def testTransactionInRollbackState(self): + with reversion.create_revision(): + try: + TestModelWithUniqueConstraint.objects.create(name='A') + TestModelWithUniqueConstraint.objects.create(name='A') + except Exception: + pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_app/views.py new/django-reversion-5.0.4/tests/test_app/views.py --- old/django-reversion-4.0.1/tests/test_app/views.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_app/views.py 2022-11-12 15:45:23.000000000 +0100 @@ -23,7 +23,7 @@ class RevisionMixinView(RevisionMixin, View): def revision_request_creates_revision(self, request): - silent = request.META.get("HTTP_X_NOREVISION", "false") == "true" + silent = request.headers.get('X-Norevision', "false") == "true" return super().revision_request_creates_revision(request) and not silent def dispatch(self, request): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-reversion-4.0.1/tests/test_project/urls.py new/django-reversion-5.0.4/tests/test_project/urls.py --- old/django-reversion-4.0.1/tests/test_project/urls.py 2021-11-04 10:00:54.000000000 +0100 +++ new/django-reversion-5.0.4/tests/test_project/urls.py 2022-11-12 15:45:23.000000000 +0100 @@ -1,4 +1,4 @@ -from django.conf.urls import include +from django.urls import include from django.urls import path from django.contrib import admin