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
 

Reply via email to