from datetime import date, time, datetime
from collections import OrderedDict
+# Originally from http://code.activestate.com/recipes/576694/
+# cut down to minimum
+
+import collections
+
+class OrderedSet(collections.MutableSet):
+
+ def __init__(self, iterable=None):
+ self.end = end = []
+ end += [None, end, end] # sentinel node for doubly linked list
+ self.map = {} # key --> [key, prev, next]
+ if iterable is not None:
+ self |= iterable
+
+ def __len__(self):
+ return len(self.map)
+
+ def __contains__(self, key):
+ return key in self.map
+
+ def add(self, key):
+ if key in self.map:
+ return
+ end = self.end
+ curr = end[1]
+ curr[2] = end[1] = self.map[key] = [key, curr, end]
+
+ def discard(self, key):
+ if key in self.map:
+ key, prev, next = self.map.pop(key)
+ prev[2] = next
+ next[1] = prev
+
+ def __iter__(self):
+ end = self.end
+ curr = end[2]
+ while curr is not end:
+ yield curr[0]
+ curr = curr[2]
+
+ def __repr__(self):
+ if not self:
+ return '%s()' % (self.__class__.__name__,)
+ return '%s(%r)' % (self.__class__.__name__, list(self))
+
+
class BudgetGraphBaseError(Exception):
pass
self.milestone_payments[node.milestone].append(payment)
return retval
+ def get_milestone_people(self):
+ """get a list of people associated with each milestone
+ """
+ payments = list(self.payments) # just activate the payments
+ retval = OrderedDict()
+ for milestone in self.milestone_payments.keys():
+ retval[milestone] = OrderedSet()
+ for milestone, payments in self.milestone_payments.items():
+ for payment in payments:
+ retval[milestone].add(str(payment.payee.identifier))
+ return retval
+
def __repr__(self):
nodes = [*self.nodes.values()]
try:
"submitted or paid %-9s" % total_req_or_paid)
print ()
+ # and one to display peole
+ milestones_people = budget_graph.get_milestone_people()
+ for milestone, people in milestones_people.items():
+ print (milestone)
+ for person in people:
+ print("\t", person)
+
+ # even quicker hack to create something vaguely resembling a CSV file
+ milestone_csvs = {}
+ for milestone, payments in budget_graph.milestone_payments.items():
+ # first get the list of people, then create some columns
+ people = milestones_people[milestone]
+ headings = []
+ for person in people:
+ name = str(person.identifier).replace(" ", "_")
+ # name, amount, requested (submitted), paid
+ headings.append(name+"_amount")
+ headings.append(name+"_req")
+ headings.append(name+"_paid")
+ # now we go through the whole "payments" thing again...
+ milestone_csvs[milestone] = [] # rows in the CSV file
+ row = {}
+ for payment in payments:
+ name = str(payment.payee.identifier).replace(" ", "_")
+ row[name+"_amount"] = str(payment.amount)
+ if payment.submitted is not None:
+ requested = str(payment.submitted)
+ else:
+ requested = ""
+ if payment.paid is not None:
+ paid = str(payment.paid)
+ else:
+ paid = ""
+ row[name+"_req"] = requested
+ row[name+"_paid"] = paid
+ print (row)
+ milestone_csvs[milestone].append(row)
+
if __name__ == "__main__":
main()