import ConfigParser import argparse import os import re import subprocess import sys here = os.path.abspath(os.path.dirname(__file__)) local_requirements = { "mozinfo": "testing/mozbase/mozinfo", "mozlog": "testing/mozbase/mozlog", "mozdebug": "testing/mozbase/mozdebug", "marionette_driver": "testing/marionette/client/", "mozprofile": "testing/mozbase/mozprofile", "mozprocess": "testing/mozbase/mozprocess", "mozcrash": "testing/mozbase/mozcrash", "mozrunner": "testing/mozbase/mozrunner", "mozleak": "testing/mozbase/mozleak", "mozversion": "testing/mozbase/mozversion", } requirements_re = re.compile(r"(%s)[^\w]" % "|".join(local_requirements.keys())) class ReplaceRequirements(object): def __init__(self, top_src_path, tox_path): self.top_src_path = top_src_path self.tox_path = tox_path self.file_cache = {} def __enter__(self): self.file_cache = {} deps = self.read_deps() for dep in deps: self.replace_path(dep) def __exit__(self, *args, **kwargs): for path, data in self.file_cache.iteritems(): with open(path, "wb") as f: f.write(data) def read_deps(self): rv = [] parser = ConfigParser.ConfigParser() path = os.path.join(self.tox_path, "tox.ini") with open(path) as f: parser.readfp(f) deps = parser.get("testenv", "deps") dep_re = re.compile("(?:.*:\s*)?-r(.*)") # This can break if we start using more features of tox for dep in deps.splitlines(): m = dep_re.match(dep) if m: rv.append(m.group(1).replace("{toxinidir}", self.tox_path)) return rv def replace_path(self, requirements_path): lines = [] with open(requirements_path, "rb") as f: self.file_cache[requirements_path] = f.read() f.seek(0) for line in f: m = requirements_re.match(line) if not m: lines.append(line) else: key = m.group(1) path = local_requirements[key] lines.append("-e %s\n" % (os.path.join(self.top_src_path, path),)) with open(requirements_path, "wb") as f: for line in lines: f.write(line.encode("utf8")) with open(requirements_path, "rb") as f: print(f.read()) def get_parser(): parser = argparse.ArgumentParser() parser.add_argument("--no-tools", dest="tools", action="store_false", default=True, help="Don't run the tools unittests") parser.add_argument("--no-wptrunner", dest="wptrunner", action="store_false", default=True, help="Don't run the wptrunner unittests") parser.add_argument("tox_kwargs", nargs=argparse.REMAINDER, help="Arguments to pass through to tox") return parser def run(top_src_dir, tools=True, wptrunner=True, tox_kwargs=None, **kwargs): tox_paths = [] if tox_kwargs is None: tox_kwargs = [] if tools: tox_paths.append(os.path.join(top_src_dir, "testing", "web-platform", "tests", "tools")) if wptrunner: tox_paths.append(os.path.join(top_src_dir, "testing", "web-platform", "tests", "tools", "wptrunner")) success = True for tox_path in tox_paths: with ReplaceRequirements(top_src_dir, tox_path): cmd = ["tox"] + tox_kwargs try: subprocess.check_call(cmd, cwd=tox_path) except subprocess.CalledProcessError: success = False return success def main(): kwargs = vars(get_parser().parse_args()) top_src_path = os.path.abspath(os.path.join(here, os.pardir, os.pardir)) return run(top_src_path, **kwargs) if __name__ == "__main__": if not main(): sys.exit(1)