"""Reading what a driver reported.""" import json class DriverReport: """The JSON one driver run wrote to stdout.""" def __init__(self, result): self.result = result @staticmethod def tail(text, lines=20): return "\n".join(text.splitlines()[-lines:]) @staticmethod def last_json_object(text): """The driver's report, however it ended up on the line. Not "the last line starting with {": worlds write to raw stdout during generation, and one that writes without a trailing newline leaves its output glued to the front of the report - Super Metroid's randomizer emits a bare "*" per retry, so the report arrives as "*{...}" and would read as no report at all. """ for line in reversed(text.splitlines()): line = line.strip() start = line.find("{") while start != -1: try: return json.loads(line[start:]) except json.JSONDecodeError: start = line.find("{", start + 1) return None @property def data(self): return self.last_json_object(self.result.stdout) def parsed(self): """The report, or a failure built from what it printed.""" report = self.data if report is not None: report.setdefault("stderr_tail", self.tail(self.result.stderr)) return report return { "game": None, "outcome": "failed", "detail": ("no JSON report on stdout " f"(exit code {self.result.returncode})"), "elapsed_seconds": None, "stdout_tail": self.tail(self.result.stdout), "stderr_tail": self.tail(self.result.stderr), }