def __init__(self, user=None, password=None, server=None, port=None, anon=False): """Initialise an SR trac object.""" config = Config() if server is None: server = config["server"] if port is None: port = config["https_port"] self.server = server self.port = port rpc_settings = {"server": server, "port": port} if anon: rpc_url = "https://{server}:{port}/trac/rpc" else: rpc_url = "https://{user}:{password}@{server}:{port}/trac/login" \ "/rpc" user = config.get_user(user) rpc_settings["user"] = user rpc_settings["password"] = config.get_password(password, user=user) rpc_url = rpc_url.format(**rpc_settings) ServerProxy.__init__(self, rpc_url) if 'ticket.create' not in self.system.listMethods(): raise WrongServer()
def command(args): import sys import subprocess from sr.tools.config import Config config = Config() username = config.get_user() url = GIT_URL.format(username=username, team=args.team.upper(), project=args.project) cmdline = ["git", "clone", url] if args.dir is not None: cmdline.append(args.dir) sys.exit(subprocess.call(cmdline))
def cmd(args): """ Run the given Gerrit command and return the response. This will get the Gerrit SSH host from the configuration file. :param list args: The arguments to run on Gerrit. :returns: The contents from the result. """ conf = Config() c = ["ssh", conf["gerrit_ssh"], "gerrit"] + args return subprocess.check_output(c, universal_newlines=True).strip()
def command(args): from sr.tools.config import Config with UsermanServer.from_config(Config()) as userman: user_info = userman.get('user', args.username) description = describe_user(user_info, userman) if user_info['has_media_consent']: exit("{0} already granted media-consent!".format(description)) question = "Confirm media-consent for {0}? [Y/n]: ".format(description) confirm = query(question, ('', 'y'), ('n',)) if not confirm: exit() # Yes, really, we need to pass 'true' as a string userman.post('user', args.username, media_consent='true')
def command(args): import os import sys from sr.tools import spending from sr.tools.config import Config from sr.tools.environment import get_config_filename # Invoke ledger on the SR spending repo # Check that we are indeed invoking it on spending.git config = Config() # Default to using the spending.git specified in the config root = config["spending"] if root is not None: root = os.path.expanduser(root) else: # Not specified in the config root = os.getcwd() try: # Check that it's actually spending.git root = spending.find_root(path=root) except spending.NotSpendingRepo: print("This isn't SR spending.git", file=sys.stderr) print("Solve this by either:", file=sys.stderr) print(" - Changing working directory to spending.git", file=sys.stderr) print(" - Set the 'spending' config option in {}".format( get_config_filename()), file=sys.stderr) sys.exit(1) ledger_args = ['ledger'] + args.command if "--file" not in args: # Tell ledger where to look ledger_args = ['ledger', "--file", os.path.join(root, "spending.dat")] \ + args.command os.execvp("ledger", ledger_args)
def command(args): import os import subprocess from sr.tools.config import Config config = Config() if args.anonymous: prefix = "git://{0}/".format(config["server"]) else: prefix = "{0}:".format(config["gerrit_ssh"]) repo = args.repo if repo[:len(prefix)] != prefix: repo = "{0}{1}".format(prefix, repo) cmd = ["git", "clone", "--recursive", repo] if args.dir is not None: cmd += [args.dir] subprocess.check_call(cmd) clonedir = args.dir if clonedir is None: clonedir = os.path.basename(args.repo) if clonedir[-4:] == ".git": clonedir = clonedir[:-4] if not args.anonymous: # Set up the gerrit Change-Id commit hook cmd = [ "scp", "{}:hooks/commit-msg".format(config["gerrit_ssh"]), os.path.join(clonedir, ".git", "hooks") ] subprocess.check_call(cmd)
def command(args): from decimal import Decimal as D import os from subprocess import check_output import sys import yaml from sr.tools import budget, spending from sr.tools.config import Config config = Config() try: root = budget.find_root() except budget.NotBudgetRepo: print("Error: Please run in budget.git", file=sys.stderr) exit(1) os.chdir(root) b = budget.load_budget("./") try: f = open("funds-in.yaml", "r") except IOError: if os.path.exists("check"): os.execv("./check", ["./check"] + sys.argv[1:]) exit(1) funds_in = yaml.load(f) total_in = D(0) for i in funds_in["incoming"]: # Convert to str to avoid some rounding issues! total_in += D(str(i["amount"])) # All the lines in funds-in.yaml are divided by 1.1 at the moment MAX = total_in * budget.FUDGE_FACTOR # Calculate how much has been budgeted in total budgeted = D(0) for line in b.walk(): budgeted += (D(1) + line.uncertainty) * line.cost if budgeted > MAX: print("Fail: Budget is £%s too high" % (budgeted - MAX), file=sys.stderr) exit(1) print("OK: ", end='') if budgeted == MAX: print("Budget is at maximum.") else: print("Budget is £%s below maximum." % (MAX - budgeted)) def list_referenced_lines(root): """Return a list of budget lines referenced in ``spending.git``.""" cmd = [ "ledger", "--file", os.path.join(root, "spending.dat"), "reg", "^Expenses:", "--format", "%A\n" ] output = check_output(cmd, universal_newlines=True).strip() lines = output.splitlines() return [spending.account_to_budget_line(line) for line in lines] spending_root = args.spending if spending_root is None: spending_root_config = config.get("spending") if spending_root_config is not None: spending_root = os.path.expanduser(spending_root_config) if spending_root is not None: # Check stuff with spending.git inv_budget_lines = set() # Check that all transactions reference valid budget lines for line in list_referenced_lines(spending_root): try: b.path(line) except budget.InvalidPath: inv_budget_lines.add(line) if len(inv_budget_lines): print("{} non-existent budget lines referenced from spending.git:". format(len(inv_budget_lines))) for line in inv_budget_lines: print(" -", line) else: print("OK: All spending.git budget line references are valid.") # Lines that have been closed but don't match their spends close_fail = {} # Lines that are over budget over_budget = {} # Load the budget again with spending information b = spending.load_budget_with_spending(spending_root) # Check that the spends line up with the budget moneywise for bline in b.walk(): if bline.closed: # Closed lines must match their spent amount if bline.cost != bline.spent: close_fail[bline] = bline.spent continue line_max = bline.cost * (D(1) + bline.uncertainty) if bline.spent > line_max: over_budget[bline] = bline.spent if len(close_fail): print("{0} closed lines do not match the amount spent against " "them:".format(len(close_fail))) for line, spent in close_fail.items(): print(" - {0}: £{1} spent, £{2} allocated".format( line.name, spent, line.cost)) else: print("OK: All closed lines have the correct value.") if len(over_budget): print("{0} lines are over budget:".format(len(over_budget))) for line, spent in over_budget.items(): print(" - {0}: £{1} spent, £{2} allocated (including fudge)". format(line.name, spent, line.cost * budget.FUDGE_FACTOR)) else: print("OK: No open budget lines are overspent.")
def command(args): from decimal import Decimal as D import os from subprocess import check_output import sys import yaml from sr.tools import budget, spending from sr.tools.config import Config config = Config() try: root = budget.find_root() except budget.NotBudgetRepo: print("Error: Please run in budget.git", file=sys.stderr) exit(1) os.chdir(root) b = budget.load_budget("./") try: f = open("funds-in.yaml", "r") except IOError: if os.path.exists("check"): os.execv("./check", ["./check"] + sys.argv[1:]) exit(1) funds_in = yaml.load(f) total_in = D(0) for i in funds_in["incoming"]: # Convert to str to avoid some rounding issues! total_in += D(str(i["amount"])) # All the lines in funds-in.yaml are divided by 1.1 at the moment MAX = total_in * budget.FUDGE_FACTOR # Calculate how much has been budgeted in total budgeted = D(0) for line in b.walk(): budgeted += (D(1) + line.uncertainty) * line.cost if budgeted > MAX: print("Fail: Budget is £%s too high" % (budgeted - MAX), file=sys.stderr) exit(1) print("OK: ", end='') if budgeted == MAX: print("Budget is at maximum.") else: print("Budget is £%s below maximum." % (MAX - budgeted)) def list_referenced_lines(root): """Return a list of budget lines referenced in ``spending.git``.""" cmd = ["ledger", "--file", os.path.join(root, "spending.dat"), "reg", "^Expenses:", "--format", "%A\n"] output = check_output(cmd, universal_newlines=True).strip() lines = output.splitlines() return [spending.account_to_budget_line(line) for line in lines] spending_root = args.spending if spending_root is None: spending_root_config = config.get("spending") if spending_root_config is not None: spending_root = os.path.expanduser(spending_root_config) if spending_root is not None: # Check stuff with spending.git inv_budget_lines = set() # Check that all transactions reference valid budget lines for line in list_referenced_lines(spending_root): try: b.path(line) except budget.InvalidPath: inv_budget_lines.add(line) if len(inv_budget_lines): print("{} non-existent budget lines referenced from spending.git:" .format(len(inv_budget_lines))) for line in inv_budget_lines: print(" -", line) else: print("OK: All spending.git budget line references are valid.") # Lines that have been closed but don't match their spends close_fail = {} # Lines that are over budget over_budget = {} # Load the budget again with spending information b = spending.load_budget_with_spending(spending_root) # Check that the spends line up with the budget moneywise for bline in b.walk(): if bline.closed: # Closed lines must match their spent amount if bline.cost != bline.spent: close_fail[bline] = bline.spent continue line_max = bline.cost * (D(1) + bline.uncertainty) if bline.spent > line_max: over_budget[bline] = bline.spent if len(close_fail): print("{0} closed lines do not match the amount spent against " "them:".format(len(close_fail))) for line, spent in close_fail.items(): print(" - {0}: £{1} spent, £{2} allocated".format( line.name, spent, line.cost)) else: print("OK: All closed lines have the correct value.") if len(over_budget): print("{0} lines are over budget:".format(len(over_budget))) for line, spent in over_budget.items(): print(" - {0}: £{1} spent, £{2} allocated (including fudge)" .format(line.name, spent, line.cost * budget.FUDGE_FACTOR)) else: print("OK: No open budget lines are overspent.")