From 09af91a936cc8326fa46db16c61f2e473b609bfd Mon Sep 17 00:00:00 2001 From: Domagoj Kriskovic Date: Mon, 20 Apr 2026 13:49:32 +0200 Subject: [PATCH] info stream GitOrigin-RevId: 5d4cb01c250768ca00e15368b9c616b467e4f9ba --- .../editor/python/pyodide-worker-client.ts | 2 +- .../editor/python/pyodide-worker-messages.ts | 2 +- .../editor/python/python-output-pane.tsx | 9 ++++--- .../components/editor/python/python-runner.ts | 25 ++++++++++++++----- .../pages/editor/ide-redesign.scss | 8 ++++++ .../unit/editor/python-runner.spec.ts | 17 ++++++++----- 6 files changed, 46 insertions(+), 17 deletions(-) diff --git a/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-client.ts b/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-client.ts index c31864692b..6b099cff6b 100644 --- a/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-client.ts +++ b/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-client.ts @@ -5,7 +5,7 @@ import type { } from './pyodide-worker-messages' export type OutputCallback = ( - stream: 'stdout' | 'stderr', + stream: 'stdout' | 'stderr' | 'info', line: string, fileId: string, executionId: string diff --git a/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-messages.ts b/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-messages.ts index c362d0b058..181d91a5c1 100644 --- a/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-messages.ts +++ b/services/web/frontend/js/features/ide-react/components/editor/python/pyodide-worker-messages.ts @@ -28,7 +28,7 @@ export type LoadingFailedEvent = { type: 'loading-failed'; error: string } export type OutputLineEvent = { type: 'output-line' - stream: 'stdout' | 'stderr' + stream: 'stdout' | 'stderr' | 'info' line: string fileId: string executionId: string diff --git a/services/web/frontend/js/features/ide-react/components/editor/python/python-output-pane.tsx b/services/web/frontend/js/features/ide-react/components/editor/python/python-output-pane.tsx index f69cce748e..4ee451bdf0 100644 --- a/services/web/frontend/js/features/ide-react/components/editor/python/python-output-pane.tsx +++ b/services/web/frontend/js/features/ide-react/components/editor/python/python-output-pane.tsx @@ -74,9 +74,12 @@ export default function PythonOutputPane() { {error && (
{error}
)} - {output.map((line, index) => ( -
- {line} + {output.map((entry, index) => ( +
+ {entry.line}
))}
diff --git a/services/web/frontend/js/features/ide-react/components/editor/python/python-runner.ts b/services/web/frontend/js/features/ide-react/components/editor/python/python-runner.ts index 7f126f6062..2b0162ee50 100644 --- a/services/web/frontend/js/features/ide-react/components/editor/python/python-runner.ts +++ b/services/web/frontend/js/features/ide-react/components/editor/python/python-runner.ts @@ -21,8 +21,13 @@ export type ExecutionContext = { type Listener = () => void +export type OutputLine = { + stream: 'stdout' | 'stderr' | 'info' + line: string +} + export type PythonRunnerState = { - output: string[] + output: OutputLine[] status: ExecutionStatus error: string | null } @@ -116,11 +121,13 @@ export class PythonRunner { this.updateState({ status: 'finished' }) } }, - onOutput: (_stream, line, fileId, executionId) => { + onOutput: (stream, line, fileId, executionId) => { if (fileId !== this.fileId || this.activeExecutionId !== executionId) { return } - this.updateState({ output: appendCapped(this.state.output, line) }) + this.updateState({ + output: appendCapped(this.state.output, { stream, line }), + }) }, }) } @@ -185,7 +192,10 @@ export class PythonRunner { status: 'loading', output: this.state.status === 'running' - ? appendCapped(this.state.output, 'Execution interrupted') + ? appendCapped(this.state.output, { + stream: 'info', + line: 'Execution interrupted', + }) : this.state.output, }) } @@ -198,8 +208,11 @@ export class PythonRunner { } } -function appendCapped(existing: string[], line: string): string[] { - const updated = [...existing, line] +function appendCapped( + existing: OutputLine[], + entry: OutputLine +): OutputLine[] { + const updated = [...existing, entry] return updated.length > MAX_OUTPUT_LINES ? updated.slice(-MAX_OUTPUT_LINES) : updated diff --git a/services/web/frontend/stylesheets/pages/editor/ide-redesign.scss b/services/web/frontend/stylesheets/pages/editor/ide-redesign.scss index 2ca1600a8c..ca04e05758 100644 --- a/services/web/frontend/stylesheets/pages/editor/ide-redesign.scss +++ b/services/web/frontend/stylesheets/pages/editor/ide-redesign.scss @@ -92,6 +92,14 @@ word-break: break-word; } +.ide-redesign-python-output-pane-line-info { + color: var(--content-secondary); +} + +.ide-redesign-python-output-pane-line-stderr { + color: var(--red-50); +} + .ide-redesign-python-output-pane-placeholder, .ide-redesign-python-output-pane-error { white-space: pre-wrap; diff --git a/services/web/test/frontend/features/ide-react/unit/editor/python-runner.spec.ts b/services/web/test/frontend/features/ide-react/unit/editor/python-runner.spec.ts index c2aa79b5d4..a8f3aef3a3 100644 --- a/services/web/test/frontend/features/ide-react/unit/editor/python-runner.spec.ts +++ b/services/web/test/frontend/features/ide-react/unit/editor/python-runner.spec.ts @@ -135,7 +135,9 @@ describe('PythonRunner', function () { executionId: runMsg.executionId, outputs: [], }) - expect(runner.getState().output).to.deep.equal(['first run output']) + expect(runner.getState().output).to.deep.equal([ + { stream: 'stdout', line: 'first run output' }, + ]) await runner.run() expect(runner.getState().output).to.deep.equal([]) @@ -193,7 +195,10 @@ describe('PythonRunner', function () { executionId: runMsg.executionId, }) - expect(runner.getState().output).to.deep.equal(['line 1', 'line 2']) + expect(runner.getState().output).to.deep.equal([ + { stream: 'stdout', line: 'line 1' }, + { stream: 'stderr', line: 'line 2' }, + ]) }) it('ignores output for a different fileId', async function () { @@ -250,8 +255,8 @@ describe('PythonRunner', function () { const output = runner.getState().output expect(output).to.have.length(100) - expect(output[0]).to.equal('line 10') - expect(output[99]).to.equal('line 109') + expect(output[0]).to.deep.equal({ stream: 'stdout', line: 'line 10' }) + expect(output[99]).to.deep.equal({ stream: 'stdout', line: 'line 109' }) }) }) @@ -274,8 +279,8 @@ describe('PythonRunner', function () { expect(runner.getState().status).to.equal('loading') expect(runner.getState().output).to.deep.equal([ - 'partial output', - 'Execution interrupted', + { stream: 'stdout', line: 'partial output' }, + { stream: 'info', line: 'Execution interrupted' }, ]) })