'Notify that field ``self`` has been modified on ``records``: prepare the
fields/records to recompute, and return a spec indicating what to
invalidate.'

def modified(self, records):

    spec = [(self, records._ids)]
    bymodel = defaultdict((lambda : defaultdict(list)))
    for (field, path) in records._field_triggers[self]:
        bymodel[field.model_name][path].append(field)
    for (model_name, bypath) in bymodel.iteritems():
        for (path, fields) in bypath.iteritems():
            if (path and any(((field.compute and field.store) for field in fields))):
                stored = set((field for field in fields if (field.compute and field.store)))
                fields = (set(fields) - stored)
                if (path == 'id'):
                    target0 = records
                else:
                    env = records.env(user=SUPERUSER_ID, context={'active_test': False})
                    target0 = env[model_name].search([(path, 'in', records.ids)])
                if target0:
                    for field in stored:
                        target = (target0 - records.env.protected(field))
                        if (not target):
                            continue
                        spec.append((field, target._ids))
                        if field.compute_sudo:
                            target = target.with_env(records.env(user=SUPERUSER_ID))
                        else:
                            target = target.with_env(records.env)
                        target._recompute_todo(field)
            for field in fields:
                spec.append((field, None))
    return spec
