Fix coverage with several contract classes; table annotation and file path checks; clean task dir on write
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
@@ -197,6 +197,12 @@ def lint_files(b):
|
||||
re.I)):
|
||||
errs.append(f"reference class {o.get('name')} has no testclasses_file (local unit tests)")
|
||||
for rel, src in b.get("files", {}).items():
|
||||
# G0121, G0122: SAP says only "Can't save due to errors in source" for these
|
||||
if re.search(r"^\s*define\s+table\b", src, re.I | re.M):
|
||||
for ann in ("tableCategory", "deliveryClass"):
|
||||
if not re.search(rf"@AbapCatalog\.{ann}\s*:", src, re.I):
|
||||
errs.append(f"{rel}: a table needs the annotation @AbapCatalog.{ann} "
|
||||
"(for example #TRANSPARENT, #A)")
|
||||
if DDL_KIND.search(src):
|
||||
for f in re.findall(r"^\s*(?:key\s+)?(\w+)\s*:", src, re.I | re.M):
|
||||
if f.upper() in RESERVED:
|
||||
@@ -278,6 +284,9 @@ def check_bundle(b):
|
||||
errs.append("stop task: expected_gap needs description and keywords")
|
||||
if "spec.md" not in files:
|
||||
errs.append("spec.md missing")
|
||||
for rel in files: # G0106: a key "seed/" (a directory) crashed write_bundle
|
||||
if not rel or rel.endswith("/") or rel.startswith("/") or ".." in rel.split("/"):
|
||||
errs.append(f"files: '{rel}' is not a valid relative file path")
|
||||
for k in ("seed", "hidden_tests", "reference"):
|
||||
for o in t.get(k, []):
|
||||
for fk in ("file", "testclasses_file"):
|
||||
@@ -326,7 +335,16 @@ def floor_budget(task):
|
||||
bud["max_tool_calls"] = max(int(bud.get("max_tool_calls", 0)), 3 * calls)
|
||||
|
||||
|
||||
KEEP_FILES = {"generation.json", "review.json"}
|
||||
|
||||
|
||||
def write_bundle(b, task_dir, task_id):
|
||||
# remove the files of an earlier attempt (G0003 kept an unused seed/course.ddls.abap)
|
||||
if os.path.isdir(task_dir):
|
||||
for name in os.listdir(task_dir):
|
||||
if name not in KEEP_FILES:
|
||||
path = os.path.join(task_dir, name)
|
||||
shutil.rmtree(path) if os.path.isdir(path) else os.remove(path)
|
||||
os.makedirs(task_dir, exist_ok=True)
|
||||
b["task"]["id"] = task_id
|
||||
for k in ("seed", "reference"):
|
||||
|
||||
@@ -322,8 +322,11 @@ class Runner:
|
||||
if st.get("step") == "unittest":
|
||||
own["tests"] += st.get("tests", 0)
|
||||
own["failures"] += st.get("failures", 0)
|
||||
cov = st.get("coverage", {}).get("class", {}).get("statement", {})
|
||||
own["coverage"] = cov.get("percent")
|
||||
# several contract classes (exception classes + main class): only a class with
|
||||
# tests has a coverage figure; a later class without tests must not reset it to 0
|
||||
cov = st.get("coverage", {}).get("class", {}).get("statement", {}).get("percent")
|
||||
if st.get("tests", 0) and cov is not None:
|
||||
own["coverage"] = max(own["coverage"] or 0, cov)
|
||||
if c["type"] == "PROG" and g["G1_active"]: # local test classes inside the report
|
||||
_, t = mcp.call("sap_run_unit_test", {"objectType": "PROG", "objectName": c["name"]})
|
||||
for prog in (_json(t) or {}).get("programs", []):
|
||||
|
||||
Reference in New Issue
Block a user