Files
abap-llm/harness/task.py

63 lines
1.8 KiB
Python

"""Task loading and prefix substitution."""
import json
import os
_B36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def _b36(n, width):
out = ""
while n:
n, r = divmod(n, 36)
out = _B36[r] + out
return out.rjust(width, "0")[-width:]
def prefix_for(run_no, task_id):
"""Z + run (4 chars base36) + task (3 chars base36) + '_'.
Run numbers below 36**3 keep a digit at position 2; the proxy uses this to tell
harness objects from other Z objects. Old prefixes (Z201001_) match the same pattern.
"""
task_no = int("".join(ch for ch in task_id if ch.isdigit()) or 0)
return f"Z{_b36(int(run_no), 4)}{_b36(task_no, 3)}_"
class Task:
def __init__(self, task_dir, prefix):
self.dir = task_dir
self.prefix = prefix
self.meta = json.loads(self._read("task.json"))
self.id = self.meta["id"]
def _read(self, rel):
with open(os.path.join(self.dir, rel)) as f:
return f.read()
def sub(self, text):
return text.replace("{{P}}", self.prefix).replace("{{p}}", self.prefix.lower())
def text(self, rel):
return self.sub(self._read(rel))
def objects(self, key):
"""List of dicts with substituted names and loaded source (if 'file')."""
out = []
for o in self.meta.get(key, []):
o = {k: self.sub(v) if isinstance(v, str) else v for k, v in o.items()}
if "file" in o:
o["source"] = self.text(o["file"])
if "testclasses_file" in o:
o["testclasses_source"] = self.text(o["testclasses_file"])
out.append(o)
return out
@property
def spec(self):
return self.text("spec.md")
@property
def out_of_scope(self):
return [self.sub(n) for n in self.meta.get("out_of_scope", [])]