diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-01-25 11:51:04 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-03-16 17:16:49 -0400 |
| commit | 9974e9a46bdf6c570c650aa911b76c2dcfd9327b (patch) | |
| tree | 5631c6d247855cb8572d6c634987f23e6c068e0d /test | |
| parent | 63a7b2d2d9402b06f9bc7745eed2d98ae9f8b11c (diff) | |
| download | sqlalchemy-9974e9a46bdf6c570c650aa911b76c2dcfd9327b.tar.gz | |
Add bulk_replace event, integrate with @validates
Added new attribute event :meth:`.AttributeEvents.bulk_replace`.
This event is triggered when a collection is assigned to a
relationship, before the incoming collection is compared with the
existing one. This early event allows for conversion of incoming
non-ORM objects as well. The event is integrated with the
``@validates`` decorator.
The ``@validates`` decorator now allows the decorated method to receive
objects from a "bulk collection set" operation that have not yet
been compared to the existing collection. This allows incoming values
to be converted to compatible ORM objects as is already allowed
from an "append" event. Note that this means that the
``@validates`` method is called for **all** values during a collection
assignment, rather than just the ones that are new.
Change-Id: I27f59db008d9e521d31a3e30143d7cd997e4b7b3
Fixes: #3896
Diffstat (limited to 'test')
| -rw-r--r-- | test/orm/test_validators.py | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/test/orm/test_validators.py b/test/orm/test_validators.py index 99672c7ea..7ceab44dc 100644 --- a/test/orm/test_validators.py +++ b/test/orm/test_validators.py @@ -143,10 +143,47 @@ class ValidatorTest(_fixtures.FixtureTest): call('addresses', a1, False), call('addresses', a2, False), # set to [a2, a3] - this is a remove of a1, # append of a3. the appends are first. + # in 1.2 due to #3896, we also get 'a2' in the + # validates as it is part of the set + call('addresses', a2, False), call('addresses', a3, False), call('addresses', a1, True), ]) + def test_validator_bulk_collection_set(self): + users, addresses, Address = (self.tables.users, + self.tables.addresses, + self.classes.Address) + + class User(fixtures.ComparableEntity): + + @validates('addresses', include_removes=True) + def validate_address(self, key, item, remove): + if not remove: + assert isinstance(item, str) + else: + assert isinstance(item, Address) + item = Address(email_address=item) + return item + + mapper(User, users, properties={ + 'addresses': relationship(Address) + }) + mapper(Address, addresses) + + u1 = User() + u1.addresses.append("e1") + u1.addresses.append("e2") + eq_( + u1.addresses, + [Address(email_address="e1"), Address(email_address="e2")] + ) + u1.addresses = ["e3", "e4"] + eq_( + u1.addresses, + [Address(email_address="e3"), Address(email_address="e4")] + ) + def test_validator_multi_warning(self): users = self.tables.users |
