--- /dev/null
+#!/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)