]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
restore and test correct defaults for validates() keyword args
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 22 May 2023 17:12:58 +0000 (13:12 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 22 May 2023 17:22:37 +0000 (13:22 -0400)
Fixed regression in the 2.0 series where the default value of
:paramref:`_orm.validates.include_backrefs` got changed to ``False`` for
the :func:`_orm.validates` function. This default is now restored to
``True``.

Fixes: #9820
Change-Id: I9b7257b7c6e94c12fc894c7b78e5c1cb92acad67

doc/build/changelog/unreleased_20/9820.rst [new file with mode: 0644]
lib/sqlalchemy/orm/mapper.py
test/orm/test_validators.py

diff --git a/doc/build/changelog/unreleased_20/9820.rst b/doc/build/changelog/unreleased_20/9820.rst
new file mode 100644 (file)
index 0000000..84a0561
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: bug, orm, regression
+    :tickets: 9820
+
+    Fixed regression in the 2.0 series where the default value of
+    :paramref:`_orm.validates.include_backrefs` got changed to ``False`` for
+    the :func:`_orm.validates` function. This default is now restored to
+    ``True``.
index 731983ff47d28c9aceba057c5785703a7abb8eec..0533c82a698401787b4f0d3adde7ceaef2c7132f 100644 (file)
@@ -4300,7 +4300,7 @@ def reconstructor(fn):
 
 
 def validates(
-    *names: str, include_removes: bool = False, include_backrefs: bool = False
+    *names: str, include_removes: bool = False, include_backrefs: bool = True
 ) -> Callable[[_Fn], _Fn]:
     r"""Decorate a method as a 'validator' for one or more named properties.
 
@@ -4329,6 +4329,10 @@ def validates(
      :func:`.validates` usage where only one validator should emit per
      attribute operation.
 
+     .. versionchanged:: 2.0.16 This paramter inadvertently defaulted to
+        ``False `` for releases 2.0.0 through 2.0.15.  Its correct default
+        of ``True`` is restored in 2.0.16.
+
     .. seealso::
 
       :ref:`simple_validators` - usage examples for :func:`.validates`
index 659ee3ca0c6c076fe75306a71ed7563252102e1a..c783b836686968994461fc5ff2664a4a392fc8ee 100644 (file)
@@ -2,6 +2,7 @@ from unittest.mock import call
 from unittest.mock import Mock
 
 from sqlalchemy import exc
+from sqlalchemy import testing
 from sqlalchemy.orm import collections
 from sqlalchemy.orm import relationship
 from sqlalchemy.orm import validates
@@ -309,61 +310,56 @@ class ValidatorTest(_fixtures.FixtureTest):
             users,
         )
 
-    def test_validator_wo_backrefs_wo_removes(self):
-        self._test_validator_backrefs(False, False)
-
-    def test_validator_wo_backrefs_w_removes(self):
-        self._test_validator_backrefs(False, True)
-
-    def test_validator_w_backrefs_wo_removes(self):
-        self._test_validator_backrefs(True, False)
-
-    def test_validator_w_backrefs_w_removes(self):
-        self._test_validator_backrefs(True, True)
-
-    def _test_validator_backrefs(self, include_backrefs, include_removes):
+    @testing.variation("include_backrefs", [True, False, "default"])
+    @testing.variation("include_removes", [True, False, "default"])
+    def test_validator_backrefs(self, include_backrefs, include_removes):
         users, addresses = (self.tables.users, self.tables.addresses)
         canary = Mock()
 
+        need_remove_param = (
+            bool(include_removes) and not include_removes.default
+        )
+        validate_kw = {}
+        if not include_removes.default:
+            validate_kw["include_removes"] = bool(include_removes)
+        if not include_backrefs.default:
+            validate_kw["include_backrefs"] = bool(include_backrefs)
+
+        expect_include_backrefs = include_backrefs.default or bool(
+            include_backrefs
+        )
+        expect_include_removes = (
+            bool(include_removes) and not include_removes.default
+        )
+
         class User(fixtures.ComparableEntity):
 
-            if include_removes:
+            if need_remove_param:
 
-                @validates(
-                    "addresses",
-                    include_removes=True,
-                    include_backrefs=include_backrefs,
-                )
+                @validates("addresses", **validate_kw)
                 def validate_address(self, key, item, remove):
                     canary(key, item, remove)
                     return item
 
             else:
 
-                @validates(
-                    "addresses",
-                    include_removes=False,
-                    include_backrefs=include_backrefs,
-                )
+                @validates("addresses", **validate_kw)
                 def validate_address(self, key, item):
                     canary(key, item)
                     return item
 
         class Address(fixtures.ComparableEntity):
-            if include_removes:
 
-                @validates(
-                    "user",
-                    include_backrefs=include_backrefs,
-                    include_removes=True,
-                )
+            if need_remove_param:
+
+                @validates("user", **validate_kw)
                 def validate_user(self, key, item, remove):
                     canary(key, item, remove)
                     return item
 
             else:
 
-                @validates("user", include_backrefs=include_backrefs)
+                @validates("user", **validate_kw)
                 def validate_user(self, key, item):
                     canary(key, item)
                     return item
@@ -390,8 +386,8 @@ class ValidatorTest(_fixtures.FixtureTest):
         # comparisons don't get caught
         calls = list(canary.mock_calls)
 
-        if include_backrefs:
-            if include_removes:
+        if expect_include_backrefs:
+            if expect_include_removes:
                 eq_(
                     calls,
                     [
@@ -433,7 +429,7 @@ class ValidatorTest(_fixtures.FixtureTest):
                     ],
                 )
         else:
-            if include_removes:
+            if expect_include_removes:
                 eq_(
                     calls,
                     [