|
13 | 13 | GAP and do not fail the run; ``--strict`` makes them fail. The change that lands ADR1 (the pager |
14 | 14 | asks the agent over ACP instead of reading files) has to close them and drop the ``gap`` text, and |
15 | 15 | a gap that has closed shows as FIXED until it is dropped. Exit status 0 when nothing FAILed. |
| 16 | +``zypi export`` is already on that path (it starts an agent and replays the session with |
| 17 | +``session/load``), so its two cases have no gap. |
16 | 18 |
|
17 | 19 | Linux only (it needs a pty); everything but ``run`` is plain Python and is tested on any platform. |
18 | 20 | """ |
@@ -44,6 +46,8 @@ class Outcome: |
44 | 46 | text: str # the screen, or what a run that ended printed |
45 | 47 | stdout: str = "" # `zypi export` only |
46 | 48 | new_sessions: dict[str, str] = field(default_factory=dict) # file name -> id in its header |
| 49 | + # `zypi export` only: the processes of the run that were still alive when it ended |
| 50 | + left_behind: list[str] = field(default_factory=list) |
47 | 51 |
|
48 | 52 | @property |
49 | 53 | def replayed(self) -> bool: |
@@ -156,17 +160,24 @@ class Case: |
156 | 160 | "export <id> prints the transcript", |
157 | 161 | ["export", "{existing}"], |
158 | 162 | "work", |
159 | | - "exit 0 and the conversation on stdout", |
160 | | - lambda o, ids: o.code == 0 and FIRST in o.stdout, |
161 | | - gap="export reads the old layout: \"Session '<id>' not found.\", exit 1", |
| 163 | + "exit 0, both sides of the conversation on stdout, no agent left running", |
| 164 | + lambda o, ids: ( |
| 165 | + o.code == 0 and FIRST in o.stdout and REPLY in o.stdout and not o.left_behind |
| 166 | + ), |
162 | 167 | export=True, |
163 | 168 | ), |
164 | 169 | Case( |
165 | 170 | "export <unknown id> fails without output", |
166 | 171 | ["export", "{unknown}"], |
167 | 172 | "work", |
168 | | - "exit non-zero, nothing on stdout", |
169 | | - lambda o, ids: o.failed and not o.stdout.strip(), |
| 173 | + "exit non-zero, an error that names the id, nothing on stdout, no agent left running", |
| 174 | + lambda o, ids: ( |
| 175 | + o.failed |
| 176 | + and not o.stdout.strip() |
| 177 | + and ids["unknown"] in o.text |
| 178 | + and "not found" in o.text |
| 179 | + and not o.left_behind |
| 180 | + ), |
170 | 181 | export=True, |
171 | 182 | ), |
172 | 183 | ] |
@@ -258,7 +269,13 @@ def finish(term: pt.Term) -> None: |
258 | 269 | done = subprocess.run( |
259 | 270 | [zypi, *argv], env=run_env, cwd=cwd, capture_output=True, text=True, timeout=60 |
260 | 271 | ) |
261 | | - outcome = Outcome(done.returncode, done.stderr, stdout=done.stdout) |
| 272 | + outcome = Outcome( |
| 273 | + done.returncode, |
| 274 | + done.stderr, |
| 275 | + stdout=done.stdout, |
| 276 | + # The export starts an agent of its own; it has to stop it before it exits. |
| 277 | + left_behind=[cmd for _pid, _state, cmd in pt.processes_with_env(marker)], |
| 278 | + ) |
262 | 279 | else: |
263 | 280 | term = start(argv, cwd) |
264 | 281 | try: |
|
0 commit comments