mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 06:33:55 +01:00
Merge pull request #32943 from overleaf/cd-auto-install-python-packages
Auto-install python packages from the executing python script GitOrigin-RevId: e343312d61e1804d927688bf4e0de00b2bdb5382
This commit is contained in:
+5
@@ -30,6 +30,7 @@ export type LifecycleCallback = (
|
||||
export class PyodideWorkerClient {
|
||||
private worker: Worker
|
||||
private baseAssetPath: string
|
||||
private packageBaseUrl: string | undefined
|
||||
private createWorker: () => Worker
|
||||
private listening = false
|
||||
private destroyed = false
|
||||
@@ -40,11 +41,13 @@ export class PyodideWorkerClient {
|
||||
|
||||
constructor(options: {
|
||||
baseAssetPath: string
|
||||
packageBaseUrl?: string
|
||||
createWorker: () => Worker
|
||||
onOutput?: OutputCallback
|
||||
onLifecycle?: LifecycleCallback
|
||||
}) {
|
||||
this.baseAssetPath = options.baseAssetPath
|
||||
this.packageBaseUrl = options.packageBaseUrl
|
||||
this.createWorker = options.createWorker
|
||||
this.outputCallback = options.onOutput ?? null
|
||||
this.lifecycleCallback = options.onLifecycle ?? null
|
||||
@@ -54,6 +57,7 @@ export class PyodideWorkerClient {
|
||||
this.queueMessage({
|
||||
type: 'init',
|
||||
baseAssetPath: this.baseAssetPath,
|
||||
packageBaseUrl: this.packageBaseUrl,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -97,6 +101,7 @@ export class PyodideWorkerClient {
|
||||
this.queueMessage({
|
||||
type: 'init',
|
||||
baseAssetPath: this.baseAssetPath,
|
||||
packageBaseUrl: this.packageBaseUrl,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ export type OutputFileData = {
|
||||
export type InitRequest = {
|
||||
type: 'init'
|
||||
baseAssetPath: string
|
||||
packageBaseUrl?: string
|
||||
}
|
||||
|
||||
export type RunCodeRequest = {
|
||||
|
||||
+10
-1
@@ -3,6 +3,7 @@ import path from 'path-browserify'
|
||||
import type { PyodideInterface } from 'pyodide'
|
||||
import type {
|
||||
OutputFileData,
|
||||
InitRequest,
|
||||
ProjectFileData,
|
||||
PyodideWorkerRequest,
|
||||
RunCodeRequest,
|
||||
@@ -14,6 +15,7 @@ type PyodideModule = typeof import('pyodide')
|
||||
const PROJECT_FS_ROOT = '/project'
|
||||
const PROJECT_FS_PREFIX = `${PROJECT_FS_ROOT}/`
|
||||
const PYODIDE_INDEX_PATH = 'js/libs/pyodide/'
|
||||
const PYODIDE_CDN_URL = 'https://cdn.jsdelivr.net/pyodide/v'
|
||||
|
||||
function ensureDirectoryExists(fs: PyodideFS, filePath: string) {
|
||||
const directory = path.dirname(filePath)
|
||||
@@ -49,6 +51,7 @@ function syncProjectFiles(fs: PyodideFS, files: ProjectFileData[]) {
|
||||
}
|
||||
|
||||
let pyodideModule: PyodideModule | null = null
|
||||
let packageBaseUrlOverride: string | undefined
|
||||
|
||||
async function loadPyodideModule(pyodideIndexUrl: string) {
|
||||
const runtimeModuleUrl = `${pyodideIndexUrl}pyodide.mjs`
|
||||
@@ -66,12 +69,14 @@ async function loadPyodideModule(pyodideIndexUrl: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleInit(msg: { baseAssetPath: string }) {
|
||||
async function handleInit(msg: InitRequest) {
|
||||
const pyodideIndexUrl = new URL(
|
||||
PYODIDE_INDEX_PATH,
|
||||
msg.baseAssetPath
|
||||
).toString()
|
||||
|
||||
packageBaseUrlOverride = msg.packageBaseUrl
|
||||
|
||||
try {
|
||||
pyodideModule = await loadPyodideModule(pyodideIndexUrl)
|
||||
self.postMessage({ type: 'loaded' })
|
||||
@@ -109,6 +114,9 @@ async function handleRunCode(msg: RunCodeRequest) {
|
||||
|
||||
const instance = await pyodideModule.loadPyodide({
|
||||
env: { MPLBACKEND: 'Agg' },
|
||||
packageBaseUrl:
|
||||
packageBaseUrlOverride ??
|
||||
`${PYODIDE_CDN_URL}${pyodideModule.version}/full/`,
|
||||
})
|
||||
|
||||
const writtenPaths = new Set<string>()
|
||||
@@ -157,6 +165,7 @@ async function handleRunCode(msg: RunCodeRequest) {
|
||||
return originalWrite.call(fs, ...args)
|
||||
}) as PyodideFS['write']
|
||||
|
||||
await instance.loadPackagesFromImports(msg.code)
|
||||
const result = await instance.runPythonAsync(msg.code)
|
||||
if (result !== undefined) {
|
||||
self.postMessage({
|
||||
|
||||
+5
-1
@@ -43,6 +43,7 @@ export class PythonRunner {
|
||||
readonly fileId: string
|
||||
private client: PyodideWorkerClient | null = null
|
||||
private readonly baseAssetPath: string
|
||||
private readonly packageBaseUrl: string | undefined
|
||||
private readonly createWorker: () => Worker
|
||||
private readonly getExecutionContext: () => Promise<ExecutionContext | null>
|
||||
private listeners = new Set<Listener>()
|
||||
@@ -54,10 +55,12 @@ export class PythonRunner {
|
||||
fileId: string,
|
||||
baseAssetPath: string,
|
||||
getExecutionContext: () => Promise<ExecutionContext | null>,
|
||||
createWorker: () => Worker
|
||||
createWorker: () => Worker,
|
||||
packageBaseUrl?: string
|
||||
) {
|
||||
this.fileId = fileId
|
||||
this.baseAssetPath = baseAssetPath
|
||||
this.packageBaseUrl = packageBaseUrl
|
||||
this.createWorker = createWorker
|
||||
this.getExecutionContext = getExecutionContext
|
||||
}
|
||||
@@ -99,6 +102,7 @@ export class PythonRunner {
|
||||
|
||||
this.client = new PyodideWorkerClient({
|
||||
baseAssetPath: this.baseAssetPath,
|
||||
packageBaseUrl: this.packageBaseUrl,
|
||||
createWorker: this.createWorker,
|
||||
onLifecycle: event => {
|
||||
switch (event.type) {
|
||||
|
||||
Reference in New Issue
Block a user