Add a 'changed' event for sqlalchemy.ext.mutable attributes; new AttributeEvent for the generic "flag_modified" event handler

Issue #3303 resolved
zoomorph created an issue

Listening for changes to a scalar attribute can be done via the 'set' event:

def validate_phone(target, value, oldvalue, initiator):
    """Strip non-numeric characters from a phone number"""

    return re.sub(r'(?![0-9])', '', value)

# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, 'set', validate_phone, retval=True)

When Mutable attributes are set, they also emit the 'set' event. However, they do not emit any events when they are merely changed.

A new event such as 'changed' should be added to cover this case. It would work like so:

def favorites_changed(target, value, oldvalue, initiator):
    logger.info("Favorites was set or changed")
    # do something

# setup listeners on UserContact.favorites attribute (a MutableList for example)
listen(UserContact.favorites, 'set', favorites_changed)
listen(UserContact.favorites, 'changed', favorites_changed)

u = session.query(UserContact).first()
u.favorites = [1, 2, 3]  # emits 'set'
u.favorites.append(4)  # should emit 'changed'
u.favorites[-1] = 5  # should emit 'changed'

Related to issue #3297

Comments (6)

  1. Mike Bayer repo owner
    • changed milestone to 1.2

    putting things that we can and should definitely do onto solid milestone targets.

  2. Mike Bayer repo owner

    Add AttributeEvents.modified

    Added new event handler :meth:.AttributeEvents.modified which is triggered when the func:.attributes.flag_modified function is invoked, which is common when using the :mod:sqlalchemy.ext.mutable extension module.

    Change-Id: Ic152f1d5c53087d780b24ed7f1f1571527b9e8fc Fixes: #3303

    → <<cset f46551de450a>>

  3. Log in to comment