Просмотр исходного кода

Merge pull request #33895 from overleaf/cd-pyodide-unsupported-module-message

Improve error messaging for python modules unsupported by Pyodide

GitOrigin-RevId: 038c672ad9da46ea6d4640b8ed37426c92d22e72
Chris Dryden 4 месяцев назад
Родитель
Сommit
db1deb1617

+ 15 - 1
services/web/frontend/js/features/ide-react/components/editor/python/pyodide.worker.ts

@@ -31,6 +31,15 @@ function classifyErrorType(errorMessage: string): ExecutionErrorType {
   return 'generic'
 }
 
+function moduleNotFoundHelpMessage(): string {
+  return (
+    "Note: Only Pyodide's built-in packages are available in the browser. " +
+    'Packages installed via pip cannot be used here. ' +
+    'See https://pyodide.org/en/stable/usage/packages-in-pyodide.html ' +
+    'for the list of supported packages.'
+  )
+}
+
 function ensureDirectoryExists(fs: PyodideFS, filePath: string) {
   const directory = path.dirname(filePath)
   if (directory === '.' || directory === '/') {
@@ -221,7 +230,12 @@ async function handleRunCode(msg: RunCodeRequest) {
   if (runError) {
     const errorMessage =
       runError instanceof Error ? runError.message : String(runError)
-    postFailure('stderr', errorMessage, classifyErrorType(errorMessage))
+    const errorType = classifyErrorType(errorMessage)
+    const fullMessage =
+      errorType === 'ModuleNotFoundError'
+        ? `${errorMessage}\n${moduleNotFoundHelpMessage()}`
+        : errorMessage
+    postFailure('stderr', fullMessage, errorType)
     return
   }
 

+ 42 - 0
services/web/test/frontend/features/ide-react/components/python-output-pane.spec.tsx

@@ -257,6 +257,9 @@ describe('<PythonOutputPane />', function () {
       'have.class',
       'ide-redesign-python-output-pane-line-stderr'
     )
+    cy.findByText("Only Pyodide's built-in packages", { exact: false }).should(
+      'not.exist'
+    )
   })
 
   it('renders the interrupt message as an info line', function () {
@@ -380,4 +383,43 @@ describe('<PythonOutputPane />', function () {
     )
     cy.findByText('hello from tomli').should('exist')
   })
+
+  it('augments ModuleNotFoundError output with help text about supported Pyodide packages', function () {
+    const executablePythonFileContents =
+      'import this_module_does_not_exist_in_pyodide\n'
+    const projectFiles = {
+      [pythonExecutableScript.filename]: executablePythonFileContents,
+    }
+    const ProjectProvider = makeProjectProvider(projectFiles)
+
+    cy.mount(
+      <EditorProviders
+        scope={{
+          editor: {
+            sharejs_doc: {
+              doc_id: pythonExecutableScript.file_id,
+              getSnapshot: () => executablePythonFileContents,
+            },
+            currentDocumentId: pythonExecutableScript.file_id,
+            openDocName: pythonExecutableScript.filename,
+          },
+        }}
+        providers={{ FileTreePathProvider, ProjectProvider }}
+      >
+        <PythonExecutionProvider>
+          <PythonOutputPane />
+        </PythonExecutionProvider>
+      </EditorProviders>
+    )
+
+    cy.findByRole('button', { name: 'Run Python code' })
+      .should('not.be.disabled')
+      .click()
+
+    cy.findByText('ModuleNotFoundError', { exact: false }).should('exist')
+    cy.findByText("Only Pyodide's built-in packages", { exact: false }).should(
+      'have.class',
+      'ide-redesign-python-output-pane-line-stderr'
+    )
+  })
 })