#!/usr/bin/python # General utilities for Python programs. # This is intended to be imported with "from offog import *". # Adam Sampson import sys, os, stat, subprocess def warn(*args): print >>sys.stderr, "".join(map(str, args)) def die(*args): warn(*args) sys.exit(1) def run_command(*args): """Run a command; die if it exits non-zero.""" rc = subprocess.call(*args) if rc != 0: die("Command failed with returncode ", rc, ": ", args) def ensure_dir(dir): """Like os.makedirs, but don't fail if the directory already exists.""" try: st = os.lstat(dir) if stat.S_ISDIR(st.st_mode): return except OSError: pass os.makedirs(dir) class memoised: """Decorator to memoise a function.""" def __init__(self, function): self.memo = {} self.function = function def __call__(self, *args, **kwargs): key = (args, tuple(kwargs.items())) if key in self.memo: return self.memo[key] r = apply(self.function, args, kwargs) self.memo[key] = r return r class push_dir: """Context guard to change directory.""" def __init__(self, dir): self.dir = dir def __enter__(self): self.previous = os.getcwd() os.chdir(self.dir) def __exit__(self, type, value, traceback): os.chdir(self.previous) class temporary_dir: """Context guard to create a temporary directory. The directory will be forcibly removed at exit.""" def __init__(self, dir): self.dir = dir def __enter__(self): os.makedirs(self.dir) def __exit__(self, type, value, traceback): subprocess.check_call(["rm", "-fr", self.dir])