Proxy: ADT REST write+activate fallback when EPOD does not activate a second PROG/FUNC write

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
Kral
2026-10-03 14:29:37 +02:00
parent 39769afce8
commit 428b3565b2
4 changed files with 61 additions and 1 deletions

View File

@@ -70,3 +70,31 @@ class AdtClient:
out[uri.group(1) if uri else "?"] = (ok is not None and ok.group(1) == "true",
msg.group(1) if msg else "")
return out
def write_activate(self, uri, name, source):
"""Lock, write source/main, unlock, activate. Fallback for EPOD: a second sap_push_source on a
PROG or FUNC writes an inactive version that is not in the inactive list, so no activation runs
(probe Z0ZZZ999_PROBE_PROG, 2026-10-03). Returns (activated, [(severity, text)])."""
if not self.csrf:
self.fetch_csrf()
st = {"X-sap-adt-sessiontype": "stateful"}
_, _, t = self._req("POST", uri + "?_action=LOCK&accessMode=MODIFY", None,
dict(st, Accept="application/vnd.sap.as+xml;charset=UTF-8;"
"dataname=com.sap.adt.lock.result"))
lh = re.search(r"<LOCK_HANDLE>(.*?)</LOCK_HANDLE>", t).group(1)
try:
self._req("PUT", f"{uri}/source/main?lockHandle={lh}", source,
dict(st, **{"Content-Type": "text/plain; charset=utf-8"}))
finally:
self._req("POST", f"{uri}?_action=UNLOCK&lockHandle={lh}", None, st)
body = ('<?xml version="1.0" encoding="UTF-8"?><adtcore:objectReferences '
'xmlns:adtcore="http://www.sap.com/adt/core">'
f'<adtcore:objectReference adtcore:uri={quoteattr(uri)} adtcore:name={quoteattr(name)}/>'
'</adtcore:objectReferences>')
_, _, t = self._req("POST", "/sap/bc/adt/activation?method=activate&preauditRequested=true", body,
{"Content-Type": "application/xml", "Accept": "application/xml"})
msgs = [(m.group(1), re.sub(r"<[^>]+>", "", m.group(2)).strip())
for m in re.finditer(r'<msg\b[^>]*\btype="(\w)"[^>]*>(.*?)</msg>', t, re.S)]
done = 'activationExecuted="true"' in t and not any(sev in ("E", "A") for sev, _ in msgs)
return done, msgs