Apply selector to transform each object in objs.

    This operates in-place on objs. Empty objects are removed from the list.

    Args:
        mode: either KEEP (to keep selected items & their ancestors) or DELETE
              (to delete selected items and their children).

def apply_filter(objs, selector, mode):
    '''Apply selector to transform each object in objs.

    This operates in-place on objs. Empty objects are removed from the list.

    Args:
        mode: either KEEP (to keep selected items & their ancestors) or DELETE
              (to delete selected items and their children).
    '''
    indices_to_delete = []
    presumption = DELETE if mode == KEEP else KEEP
    for i, obj in enumerate(objs):
        timer.log('Applying selector: %s' % selector)
        marks = {k: mode for k in selector_to_ids(selector, obj, mode)}
        timer.log('done applying selector')
        timer.log('filtering object...')
        filter_object(obj, marks, presumption=presumption)
        timer.log('done filtering')
        if obj is None:
            indices_to_delete.append(i)

    for index in reversed(indices_to_delete):
        del objs[index]