From: Alex Dehnert Date: Mon, 12 Mar 2012 18:28:52 +0000 (-0400) Subject: script to ~build out a list of lists X-Git-Url: https://www.dehnerts.com/gitweb/?p=user%2Falex%2Fsoftware%2Fmy-snippets.git;a=commitdiff_plain;h=0cb6a3d571338cb941aa95a8c2f4dc686bcd6709 script to ~build out a list of lists In particular, given a starting list, this computes the transitive closure under the operations: * get the lists this list owns * get the lists this list contains * (disabled) get the lists that contain this list It allows specifying a list whose members should be skipped, as well. The code is easy to configure for which of those operations to use, and whether to do it recursively or not. At the moment, this isn't exposed to the command line, though that would be a reasonable feature to add. --- diff --git a/compute-list-closure b/compute-list-closure new file mode 100755 index 0000000..cfbc771 --- /dev/null +++ b/compute-list-closure @@ -0,0 +1,98 @@ +#!/usr/bin/python + +import moira +import sys +import Queue + +def lenient_query(*query): + try: + results = moira.query(*query) + except moira.MoiraException as e: + msg = e[1] + if msg == 'No records in database match query': + results = [] + else: + raise + return results + + +def expand_closure(lst, owns=True, members=True, member_of=True, recursive=True, ): + closure = set() + include_type = 'list' + if recursive: include_type = 'rlist' + if owns: + results = lenient_query('get_ace_use', include_type, lst) + for result in results: + if result['use_type'] == 'LIST': + closure.add(result['use_name']) + + if members: + results = lenient_query('get_members_of_list', lst) + for result in results: + if result['member_type'] == 'LIST': + closure.add(result['member_name']) + + if member_of: + results = lenient_query('get_lists_of_member', include_type, lst) + for result in results: + closure.add(result['list_name']) + + return closure + +def get_exclusions(lst): + exclusions = set() + results = lenient_query('get_members_of_list', lst) + for result in results: + if result['member_type'] == 'LIST': + exclusions.add(result['member_name']) + return exclusions + +def compute_closure(lists, exclude): + closure = set() + parent = {} + + the_queue = Queue.Queue() + for lst in lists: + the_queue.put(lst) + for lst in lists: + parent[lst] = None + + while not the_queue.empty(): + lst = the_queue.get() + if lst in closure: + print "skipping %s" % (lst, ) + continue + closure.add(lst) + try: + new_lists = expand_closure(lst, member_of=False, recursive=False, ) + except moira.MoiraException as e: + msg = e[1] + if msg == 'Insufficient permission to perform requested database access': + new_lists = [] + print >>sys.stderr, "List %s (parent %s) appears to be hidden; ignoring. (Queue length: %d; closure length: %d)" % (lst, parent[lst], the_queue.qsize(), len(closure), ) + else: + raise + for new_list in new_lists: + if new_list in closure: + pass + elif new_list in exclude: + print "Excluding %s (parent %s)" % (new_list, lst) + else: + the_queue.put(new_list) + parent[new_list] = lst + print "%s (from %s)" % (new_list, lst) + return closure + +if __name__ == '__main__': + moira.connect() + moira.auth('awdflu') # client name is awdflu --- Alex Dehnert file-lists-updater + starter_list = sys.argv[1] + exclude_list = sys.argv[2] + exclude = get_exclusions(exclude_list) + closure = compute_closure([starter_list], exclude) + moira.disconnect() + print "\n\n\n" + for lst in closure: + print lst + print + print "Count:", len(closure)