Roundup Tracker

The following code implements a loop-check for objects in roundup (not just issues) that refer to the same type of object via a link or multilink property. The code is intended to be called by an auditor. The first parameter is a gettext method for localisation of the error message in Reject. The other paramerts are cl: roundup class, id: id of the current item (can be None for a new item), prop: the name of the link or multilink property of the class for which no loop should occur, and attr: the contents of the prop attribute of the current item. The parameter ids is only used for recursive calls of the function:

from   roundup.hyperdb    import String, Link, Multilink
def check_loop (_, cl, id, prop, attr, ids = []) :
    is_multi = isinstance (cl.properties [prop], Multilink)
    assert (is_multi or isinstance (cl.properties [prop], Link))
    label = cl.labelprop ()
    if id :
        ids.append (id)
    if attr :
        if not is_multi :
            attr = [attr]
        for a in attr :
            if a in ids :
                raise Reject, _ ("%s loop: %s") % \
                    (_ (prop), ','.join ([cl.get (i, label) for i in ids]))
            check_loop (_, cl, a, prop, cl.get (a, prop), ids)
            ids.pop ()
# end def check_loop

Usage example: Say, we have a supervisor attribute in the user class. Now we want to check that there is no supervisor-loop (one person being supervised by him or herself recursively). We'd call the following in an auditor for the user class:

if 'supervisor' in new_values :
    check_loop (_, cl, nodeid, 'supervisor', new_values ['supervisor'])