]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Raise when two validators conflict
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 26 Aug 2016 16:56:01 +0000 (12:56 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 26 Aug 2016 16:56:01 +0000 (12:56 -0400)
Two @validates decorators that make use of the same name
is not supported.  Raise an exception.

Change-Id: Ia3e89ffdc9ef345a0de258e2ac0ac5e0bd421c61
Fixes: #3776
doc/build/changelog/changelog_11.rst
lib/sqlalchemy/orm/mapper.py
test/orm/test_validators.py

index e08976f1521341d1ca421a51f0d74a03b2778c56..ba967f9762a255855615184e9778a2461df859ff 100644 (file)
 .. changelog::
     :version: 1.1.0
 
+    .. change::
+        :tags: bug, orm
+        :tickets: 3776
+
+        An exception is raised when two ``@validates`` decorators on a mapping
+        make use of the same name.  Only one validator of a certain name
+        at a time is supported, there's no mechanism to chain these together,
+        as the order of the validators at the level of function decorator
+        can't be made deterministic.
+
+
     .. change::
         :tags: bug, mysql
         :tickets: 3766
index b76a6f7271688179299443aff052b034b3f67036..e8aa0854178a1a38b2c826fd86783c0850d9bce2 100644 (file)
@@ -1204,6 +1204,11 @@ class Mapper(InspectionAttr):
                 elif hasattr(method, '__sa_validators__'):
                     validation_opts = method.__sa_validation_opts__
                     for name in method.__sa_validators__:
+                        if name in self.validators:
+                            raise sa_exc.InvalidRequestError(
+                                "A validation function for mapped "
+                                "attribute %r on mapper %s already exists." %
+                                (name, self))
                         self.validators = self.validators.union(
                             {name: (method, validation_opts)}
                         )
index 417554f46864f814b2492ceae844cded03bd6267..e59bb580a00064f302a93ce69f34814264c6fe4c 100644 (file)
@@ -1,7 +1,9 @@
 from test.orm import _fixtures
-from sqlalchemy.testing import fixtures, assert_raises, eq_, ne_
+from sqlalchemy.testing import fixtures, assert_raises, eq_, ne_, \
+    assert_raises_message
 from sqlalchemy.orm import mapper, Session, validates, relationship
 from sqlalchemy.testing.mock import Mock, call
+from sqlalchemy import exc
 
 
 class ValidatorTest(_fixtures.FixtureTest):
@@ -145,6 +147,41 @@ class ValidatorTest(_fixtures.FixtureTest):
             ]
         )
 
+    def test_validator_multi_warning(self):
+        users = self.tables.users
+
+        class Foo(object):
+            @validates("name")
+            def validate_one(self, key, value):
+                pass
+
+            @validates("name")
+            def validate_two(self, key, value):
+                pass
+
+        assert_raises_message(
+            exc.InvalidRequestError,
+            "A validation function for mapped attribute "
+            "'name' on mapper Mapper|Foo|users already exists",
+            mapper, Foo, users
+        )
+
+        class Bar(object):
+            @validates("id")
+            def validate_three(self, key, value):
+                return value + 10
+
+            @validates("id", "name")
+            def validate_four(self, key, value):
+                return value + "foo"
+
+        assert_raises_message(
+            exc.InvalidRequestError,
+            "A validation function for mapped attribute "
+            "'name' on mapper Mapper|Bar|users already exists",
+            mapper, Bar, users
+        )
+
     def test_validator_wo_backrefs_wo_removes(self):
         self._test_validator_backrefs(False, False)