[web] Add PythonExecutionContext with per-file output buffers (#32737)

* [web] extract PythonExecutionContext and PythonRunner to manage pyodide execution per file

* [web] define worker URL in python execution context in order to avoid breaking cjs-based tests

* [web] use null check for doc contents to allow running empty python files

* [web] flush buffered editor ops before refreshing snapshot for python execution

* [web] catch getExecutionContext errors in python runner to prevent unhandled rejections

* [web] add PythonRunner unit tests and extract shared WorkerMock

* refactor: rename snapshot to state in PythonRunner

* fix: remove unnecessary path normalization in PythonExecutionProvider

* fix cypress tests

GitOrigin-RevId: 9c55586d982fe8df5b90374227005c6b83e94d1f
This commit is contained in:
Domagoj Kriskovic
2026-04-21 08:05:50 +00:00
committed by Copybot
parent e30a2a5beb
commit 415db24ba4
13 changed files with 938 additions and 345 deletions
@@ -7,6 +7,7 @@ import {
import { FileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
import { ProjectContext } from '@/shared/context/project-context'
import { ProjectSnapshot } from '@/infrastructure/project-snapshot'
import { PythonExecutionProvider } from '@/features/ide-react/context/python-execution-context'
const pythonExecutableScript: Record<string, string> = {
file_id: 'test-py-doc-id',
@@ -83,11 +84,13 @@ describe('<PythonOutputPane />', function () {
}}
providers={{ FileTreePathProvider, ProjectProvider }}
>
<PythonOutputPane />
<PythonExecutionProvider>
<PythonOutputPane />
</PythonExecutionProvider>
</EditorProviders>
)
cy.findByRole('button', { name: 'Run Python Code' })
cy.findByRole('button', { name: 'Run Python code' })
.should('not.be.disabled')
.click()
cy.findByText('hello!').should('exist')
@@ -122,11 +125,13 @@ describe('<PythonOutputPane />', function () {
}}
providers={{ FileTreePathProvider, ProjectProvider }}
>
<PythonOutputPane />
<PythonExecutionProvider>
<PythonOutputPane />
</PythonExecutionProvider>
</EditorProviders>
)
cy.findByRole('button', { name: 'Run Python Code' })
cy.findByRole('button', { name: 'Run Python code' })
.should('not.be.disabled')
.click()
cy.findByText('hello!').should('exist')
@@ -195,11 +200,13 @@ describe('<PythonOutputPane />', function () {
ProjectProvider,
}}
>
<PythonOutputPane />
<PythonExecutionProvider>
<PythonOutputPane />
</PythonExecutionProvider>
</EditorProviders>
)
cy.findByRole('button', { name: 'Run Python Code' })
cy.findByRole('button', { name: 'Run Python code' })
.should('not.be.disabled')
.click()
cy.findByText('name,type').should('exist')