'This searches for all of a user\'s groups from the bottom up. In other
words, it returns the groups that the user belongs to, the groups that
those groups belong to, etc. Circular references will be detected and
pruned.'

def user_groups(self, ldap_user, group_search):

    group_info_map = {}
    member_dn_set = set([ldap_user.dn])
    handled_dn_set = set()
    while (len(member_dn_set) > 0):
        group_infos = self.find_groups_with_any_member(member_dn_set, group_search, ldap_user.connection)
        new_group_info_map = dict([(info[0], info) for info in group_infos])
        group_info_map.update(new_group_info_map)
        handled_dn_set.update(member_dn_set)
        member_dn_set = (set(new_group_info_map.keys()) - handled_dn_set)
    return group_info_map.values()
