diff --git a/scripts/prepare-pyodide.js b/scripts/prepare-pyodide.js index 64c380e3a7..577b97854f 100644 --- a/scripts/prepare-pyodide.js +++ b/scripts/prepare-pyodide.js @@ -14,15 +14,17 @@ const packages = [ 'seaborn', 'pytz', 'black', - 'openai', - 'openpyxl' + 'openai' ]; // Pure-Python packages whose wheels must be downloaded from PyPI and saved into // static/pyodide/ so that the browser can install them offline via micropip. // Packages already provided by the Pyodide distribution (click, platformdirs, // typing_extensions, etc.) do NOT need to be listed here. -const pypiPackages = ['black', 'pathspec', 'mypy_extensions', 'pytokens']; +// Spell them canonically (dashed): that is the only form pyodide resolves lock entries by. +const pypiPackages = ['black', 'pathspec', 'mypy-extensions', 'pytokens', 'openpyxl', 'et-xmlfile']; + +const pypiDepends = { openpyxl: ['et-xmlfile'] }; import { loadPyodide } from 'pyodide'; import { setGlobalDispatcher, ProxyAgent } from 'undici'; @@ -175,19 +177,18 @@ async function downloadPyPIWheels() { } // Inject into pyodide-lock.json so micropip resolves locally - const normalizedName = pkg.replace(/-/g, '_'); - if (!lockData.packages[normalizedName]) { - lockData.packages[normalizedName] = { - name: normalizedName, + if (!lockData.packages[pkg]) { + lockData.packages[pkg] = { + name: pkg, version: version, file_name: wheel.filename, install_dir: 'site', sha256: wheel.digests?.sha256 || '', package_type: 'package', - imports: [normalizedName], - depends: [] + imports: [pkg.replace(/-/g, '_')], + depends: pypiDepends[pkg] || [] }; - console.log(` Added ${normalizedName}==${version} to pyodide-lock.json`); + console.log(` Added ${pkg}==${version} to pyodide-lock.json`); } } diff --git a/src/lib/components/chat/Messages/CodeBlock.svelte b/src/lib/components/chat/Messages/CodeBlock.svelte index 23ef519ea5..7889592120 100644 --- a/src/lib/components/chat/Messages/CodeBlock.svelte +++ b/src/lib/components/chat/Messages/CodeBlock.svelte @@ -233,7 +233,9 @@ /\bimport\s+seaborn\b|\bfrom\s+seaborn\b/.test(code) ? 'seaborn' : null, /\bimport\s+sympy\b|\bfrom\s+sympy\b/.test(code) ? 'sympy' : null, /\bimport\s+tiktoken\b|\bfrom\s+tiktoken\b/.test(code) ? 'tiktoken' : null, - /\bimport\s+pytz\b|\bfrom\s+pytz\b/.test(code) ? 'pytz' : null + /\bimport\s+pytz\b|\bfrom\s+pytz\b/.test(code) ? 'pytz' : null, + /\bimport\s+openpyxl\b|\bfrom\s+openpyxl\b/.test(code) ? 'openpyxl' : null, + /\.(read|to)_excel\(|\.Excel(Writer|File)\(/.test(code) ? 'openpyxl' : null ].filter(Boolean); console.log(packages); diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 71221fba94..d23eb89038 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -311,7 +311,9 @@ /\bimport\s+seaborn\b|\bfrom\s+seaborn\b/.test(code) ? 'seaborn' : null, /\bimport\s+sympy\b|\bfrom\s+sympy\b/.test(code) ? 'sympy' : null, /\bimport\s+tiktoken\b|\bfrom\s+tiktoken\b/.test(code) ? 'tiktoken' : null, - /\bimport\s+pytz\b|\bfrom\s+pytz\b/.test(code) ? 'pytz' : null + /\bimport\s+pytz\b|\bfrom\s+pytz\b/.test(code) ? 'pytz' : null, + /\bimport\s+openpyxl\b|\bfrom\s+openpyxl\b/.test(code) ? 'openpyxl' : null, + /\.(read|to)_excel\(|\.Excel(Writer|File)\(/.test(code) ? 'openpyxl' : null ].filter(Boolean); const worker = getOrCreateWorker(); diff --git a/static/pyodide/pyodide-lock.json b/static/pyodide/pyodide-lock.json index a29df9c9ce..192f49b42b 100644 --- a/static/pyodide/pyodide-lock.json +++ b/static/pyodide/pyodide-lock.json @@ -5131,8 +5131,8 @@ ], "depends": [] }, - "mypy_extensions": { - "name": "mypy_extensions", + "mypy-extensions": { + "name": "mypy-extensions", "version": "1.1.0", "file_name": "mypy_extensions-1.1.0-py3-none-any.whl", "install_dir": "site", @@ -5154,6 +5154,32 @@ "pytokens" ], "depends": [] + }, + "openpyxl": { + "name": "openpyxl", + "version": "3.1.5", + "file_name": "openpyxl-3.1.5-py2.py3-none-any.whl", + "install_dir": "site", + "sha256": "5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", + "package_type": "package", + "imports": [ + "openpyxl" + ], + "depends": [ + "et-xmlfile" + ] + }, + "et-xmlfile": { + "name": "et-xmlfile", + "version": "2.0.0", + "file_name": "et_xmlfile-2.0.0-py3-none-any.whl", + "install_dir": "site", + "sha256": "7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", + "package_type": "package", + "imports": [ + "et_xmlfile" + ], + "depends": [] } } } \ No newline at end of file