fix(runtime): survive SystemExit in persistent REPL
136 unmodified linesExpand all1371381391401411421431441451461471481491501511521531931 unmodified linesExpand all136 unmodified linesExpand all
events = self.repl.execute("d", "_ + 40") self.assertEqual(one(events, "result")["text"], "42")
def test_system_exit_is_reported_without_stopping_runtime(self): events = self.repl.execute("exit", "raise SystemExit(3)") self.assertEqual(one(events, "error")["ename"], "SystemExit") self.assertEqual(one(events, "done")["status"], "error")
follow = self.repl.execute("after-exit", "1 + 1") self.assertEqual(one(follow, "result")["text"], "2") self.assertEqual(one(follow, "done")["status"], "ok")
def test_stdout_stderr_and_direct_fd_writes(self): code = "\n".join( [ "import os, sys",1931 unmodified linesExpand all68 unmodified lines6970717273747576777879808182838485151 unmodified linesExpand all68 unmodified lines expect(r.error?.evalue).toBe("nope"); expect(r.error?.traceback.join("")).toContain("raise ValueError('nope')"); }, 30_000);
it("remains usable after a cell raises SystemExit", async () => { manager = new ReplKernelManager({ python: python as string, cwd: dir }); const exited = await manager.execute("raise SystemExit(3)"); expect(exited.status).toBe("error"); expect(exited.error?.ename).toBe("SystemExit");
await expect(manager.execute("1 + 1")).resolves.toMatchObject({ status: "ok", result: "2" }); }, 30_000);
it("parses emitted display payloads into diffs, attachments, and sent messages", async () => { manager = new ReplKernelManager({ python: python as string, cwd: dir }); const code = [ "from rlm import emit",151 unmodified linesExpand all1157 unmodified linesExpand all11581159116011611162116211631164116511662 unmodified lines1157 unmodified linesExpand all # run_until_complete; the interrupt is already recorded, so resume serving. while not _serve_task.done(): try: _loop.run_until_complete(_serve_task) except KeyboardInterrupt: except (KeyboardInterrupt, SystemExit): continue _loop.close()
2 unmodified lines