def command(args): import sys from sr.tools.trac import Ticket, TracProxy, WrongServer try: server = TracProxy() except WrongServer: print("Error: The specified server is not a Trac instance", file=sys.stderr) sys.exit(1) t = Ticket(args.ticket, server) for n in args.deps: t.deps.remove(n) if args.m is not None: msg = args.m msg += "\n\n" else: msg = "" msg += "Removing dependencies:" for n in args.deps: msg += "\n * #{0}".format(n) updated = t.cleanup(dry_run=args.dry_run, msg=msg) if updated: if args.dry_run: print("Ticket would have been updated if not for --dry-run.") else: print("Ticket updated.")
def command(args): import sys from sr.tools.trac import Ticket, TracProxy, WrongServer try: server = TracProxy() except WrongServer: print("Error: The specified server is not a Trac instance", file=sys.stderr) sys.exit(1) tickets = {} done = set() todo = set([args.ticket]) print("digraph G {") print("rankdir=LR;") while len(todo): for num in list(todo): t = Ticket(num, server) tickets[num] = t for dep in t.deps: if dep not in done: todo.add(dep) print("{0} -> {1};".format(dep, num)) done.add(num) todo.remove(num) for num, ticket in tickets.items(): if args.summaries: label = "#{}: {}".format(num, ticket.summary) else: label = "#{}".format(num) props = {"label": label, "URL": ticket.url} if ticket.status == "closed": props["style"] = "filled" props["color"] = "grey" propstr = "" for name, val in props.items(): propstr += """{0}="{1}" """.format(name, val) print("{0} [{1}]".format(num, propstr)) print("}")
def command(args): import re import sys import six.moves.xmlrpc_client as xmlrpclib from sr.tools import spending from sr.tools.trac import TracProxy try: root = spending.find_root() except spending.NotSpendingRepo: print( "Please run in spending.git top level directory", file=sys.stderr) exit(1) spends = spending.load_transactions(root) spendsumgrp = {} for s in spends: if s.trac in spendsumgrp: spendsumgrp[s.trac] += float(s.cost) else: spendsumgrp[s.trac] = float(s.cost) server = TracProxy(anon=True) mserver = xmlrpclib.MultiCall(server) tickets = server.ticket.query("status!=closed&component=Purchasing") for ticket in tickets: mserver.ticket.get(ticket) costsumgrp = {} for ticket in mserver(): match = re.search( 'Total cost: \xa3([0-9.]+)', ticket[3]['description']) if match is None: print("Unable to determine cost for ticket " + str(ticket[0]) + ". Invalid formatting") continue if ticket[0] in costsumgrp: costsumgrp[ticket[0]] += float(match.groups()[0]) else: costsumgrp[ticket[0]] = float(match.groups()[0]) for val in costsumgrp: if spendsumgrp[val] != costsumgrp[val]: print("Ticket " + str(val) + " does not match transactions") print("\tTicket cost: £" + str(costsumgrp[val])) print("\tTransactions: £" + str(spendsumgrp[val]))
def command(args): import sys from sr.tools.trac import Ticket, TracProxy, WrongServer try: server = TracProxy() except WrongServer: print("Error: The specified server is not a Trac instance", file=sys.stderr) sys.exit(1) t = Ticket(args.ticket, server) current = set(t.deps) new = set(args.deps) to_add = new - current already = new - to_add if len(already): for n in already: print('#{0} is already a dep of #{1}'.format(n, args.ticket), file=sys.stderr) if len(to_add) == 0: sys.exit("No new dependencies to add to #{0}".format(args.ticket)) t.deps += to_add if args.m is not None: msg = args.m msg += "\n\n" else: msg = "" msg += "Adding dependencies:" for n in to_add: msg += "\n * #{0}".format(n) updated = t.cleanup(dry_run=args.dry_run, msg=msg) if updated: if args.dry_run: print("Ticket would have been updated if not for --dry-run.") else: print("Ticket updated.")
def command(args): import os import sys from six.moves.xmlrpc_client import Binary from sr.tools.trac import TracProxy, WrongServer try: server = TracProxy(server=args.server, port=args.port) except WrongServer: print("Error: The specified server is not a Trac instance", file=sys.stderr) sys.exit(1) with open(args.filename, "r") as f: content = f.read() server.ticket.putAttachment(args.ticket, os.path.basename(args.filename), args.desc, Binary(content))
def command(args): import sys from sr.tools.trac import Ticket, TracProxy, WrongServer try: server = TracProxy() except WrongServer: print("Error: The specified server is not a Trac instance", file=sys.stderr) sys.exit(1) search_ticket = args.ticket query = "description=~{}".format(search_ticket) matches = server.ticket.query(query) deps = [] refs = [] for num in matches: t = Ticket(num, server) if search_ticket in t.deps: deps.append(t) else: refs.append(t) if len(deps): print("The following tickets depend on {}:".format(search_ticket)) for t in deps: print("\t{} [{}]".format(t, t.url)) else: print("Nothing depends on {}".format(search_ticket)) if len(refs): print("The following tickets appear to reference {}:".format( search_ticket)) for t in refs: print("\t{} [{}]".format(t, t.url))
def command(args): import sys from sr.tools import spending from sr.tools.trac import TracProxy transactions = spending.load_transactions("./") p = TracProxy(anon=True) tickets = p.ticket.query( "component=purchasing&max=0&resolution=fixed&status=closed") counts = {} for t in tickets: if t < 821 and t not in []: # Tickets before #839 except for those listed above weren't # budgeted continue counts[t] = 0 # Tickets that have been prematurely added to spending.git premature = [] for t in transactions: if t.trac not in counts: premature.append(t.trac) continue counts[t.trac] += 1 missing = [] for tnum, count in counts.items(): if count == 0: missing.append(tnum) missing.sort() if len(missing): print("{0} trac tickets with no spending.git " "entry:".format(len(missing))) for t in missing: print("{0:10} -- http://srobo.org/trac/ticket/{0}".format(t)) else: print("All resolved purchasing tickets exist in spending.git :-)") if len(premature): print("-" * 40) print("Grabbing ticket information...", end='') sys.stdout.flush() states = {} for t in premature: info = p.ticket.get(t)[3] s = (info["status"], info["resolution"]) if s not in states: states[s] = [] states[s].append(t) print("done") print("{0} purchasing tickets have been added to spending.git " "before being closed.".format(len(premature))) print() print("This is non-fatal, " "and generally means that there is more treasurer-related") print("action to be taken on them " "(maybe the treasurer is waiting for some information).") print() for state, tickets in states.items(): tickets.sort() print("{0} tickets in state {1}:{2}:".format( len(tickets), state[0], state[1])) for t in tickets: print("{0:10} -- http://srobo.org/trac/ticket/{0}".format(t)) print() open_tickets = set(p.ticket.query("component=purchasing&max=0&status=new")) print("There are {0} unresolved purchasing tickets in trac right now.". format(len(open_tickets))) print("Here are the ones that don't exist in spending.git") print("(note that they don't need to yet)") n = list(open_tickets.difference(premature)) n.sort() for t in n: print("{0:10} -- http://srobo.org/trac/ticket/{0}".format(t))
def command(args): import datetime import sr.tools.spending as srspending import sr.tools.budget as srbudget from sr.tools.trac import TracProxy, WrongServer try: spending_root = srspending.find_root() except srspending.NotSpendingRepo: print("Please run in spending.git top level directory", file=sys.stderr) sys.exit(1) try: budget = srspending.load_budget_with_spending(spending_root) except srbudget.NoBudgetConfig as nbc: print("Error:", nbc.message, file=sys.stderr) print("Have you initialised the budget submodule?", file=sys.stderr) print("If not, run 'git submodule update --init'.", file=sys.stderr) sys.exit(1) if args.spend_file is not None: spend_request = SpendRequest(args.spend_file) else: spend_request = SpendRequest.from_editor() ticket_text = "Payee: {} \\\\\n".format(spend_request.username) if spend_request.supplier_url is None: ticket_text += "Supplier: {} \\\\\n".format(spend_request.supplier) else: ticket_text += "Supplier: [{url} {supplier}] \\\\\n" \ .format(url=spend_request.supplier_url, supplier=spend_request.supplier) budget_line_totals = {} for purchase in spend_request.purchases: try: budget_line = budget.path(purchase.budget_line) except KeyError: # TODO: Move this check up into the parser so it's caught and the # user can fix it print('Budget line "{0}" not found', file=sys.stderr) sys.exit(1) bl_request_total = D(0) ticket_text += """ === Items from [budget:{budget_line}] === {summary} \\\\ ||= '''Item''' =||= '''Cost''' =|| """.format(budget_line=purchase.budget_line, summary=purchase.summary) for item in purchase.items: ticket_text += "|| {desc} || £{cost} ||\n".format(desc=item.desc, cost=item.cost) bl_request_total += item.cost # How much has already been spent against this budget line spent = budget_line.spent req_total = spent + bl_request_total # It is over the limit? if req_total > budget_line.cost: print( "Warning: This purchase exceeds the budget line '{0}'".format( purchase.budget_line)) print("\tBudget line's value: £{0}".format(budget_line.cost)) print("\tRequested Expenditure: £{0} ({1}%)".format( req_total, 100 * (req_total) / budget_line.cost)) if not input("Continue anyway? [y/N] ").lower() == 'y': sys.exit() if purchase.budget_line not in budget_line_totals: budget_line_totals[purchase.budget_line] = D(0) budget_line_totals[purchase.budget_line] += bl_request_total ticket_text += """ === Budget Line Totals === ||= '''Budget Line''' =||= '''Total''' =|| """ for line, total in budget_line_totals.items(): ticket_text += "|| [budget:{line}] || £{total} ||\n" \ .format(line=line, total=total) print(ticket_text) if args.dry_run: print("Stopping before actually creating ticket.") sys.exit(0) try: server = TracProxy(server=args.server, port=args.port) except WrongServer: print("Error: The specified server is not a Trac instance", file=sys.stderr) sys.exit(1) ticketNum = server.ticket.create(spend_request.summary, ticket_text, { 'component': "Purchasing", 'owner': "treasurer", 'type': "task" }) if not ticketNum > 0: print("Unable to create a valid ticket") sys.exit() if args.port == 443: hostname = args.server else: hostname = "{0}:{1}".format(args.server, args.port) print("Purchasing ticket created: https://{0}/trac/ticket/{1}".format( hostname, ticketNum)) print("Spending Entries:") for purchase in spend_request.purchases: print() today = datetime.date.today() i = "{date} ! {summary}\n" i += " {account}\t£{amount}\n" i += " Liabilities:{payee}\n" i += " ; trac: #{trac}" print( i.format(date=today.isoformat(), summary=purchase.summary, account=srspending.budget_line_to_account( purchase.budget_line), amount=sum([x.cost for x in purchase.items]), payee=spend_request.username, trac=ticketNum))