mirror of
https://github.com/astral-sh/ruff.git
synced 2026-05-06 08:56:57 -04:00
[ty] Fix the Pyodide assets deployment in the ty playground. (#24994)
<!-- Thank you for contributing to Ruff/ty! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? (Please prefix with `[ty]` for ty pull requests.) - Does this pull request include references to any relevant issues? - Does this PR follow our AI policy (https://github.com/astral-sh/.github/blob/main/AI_POLICY.md)? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> - Adds some graceful degradation to Pyodide loading failures in the ty playground (with the result that the entire playground UI doesn't disappear if we only fail to execute a code run). - Corrects the placement of assets in our playground deployment, and adds some validation to the deployment workflow as a simple regression test Closes https://github.com/astral-sh/ty/issues/3409. ## Test Plan I've verified the new asset layout in a local build of the playground. I think that's sufficient, but I will monitor the production playground deployment and revert this change if necessary. <!-- How was it tested? -->
This commit is contained in:
@@ -50,6 +50,13 @@ jobs:
|
||||
- name: "Build ty playground"
|
||||
run: npm run build --workspace ty-playground
|
||||
working-directory: playground
|
||||
- name: "Verify Pyodide assets"
|
||||
run: |
|
||||
test -f ty/dist/assets/pyodide.asm.js
|
||||
test -f ty/dist/assets/pyodide.asm.wasm
|
||||
test -f ty/dist/assets/pyodide-lock.json
|
||||
test -f ty/dist/assets/python_stdlib.zip
|
||||
working-directory: playground
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@9acf94ace14e7dc412b076f2c5c20b8ce93c79cd # v3.15.0
|
||||
|
||||
@@ -4,39 +4,40 @@ import { SerializedFiles } from "../Playground";
|
||||
const SANDBOX_BASE_DIRECTORY = "/playground/";
|
||||
|
||||
export async function runPython(workspace: SerializedFiles): Promise<string> {
|
||||
const pyodide = await loadPyodide({
|
||||
env: {
|
||||
HOME: SANDBOX_BASE_DIRECTORY,
|
||||
},
|
||||
});
|
||||
|
||||
let combinedOutput = "";
|
||||
|
||||
const outputHandler = (output: string) => {
|
||||
combinedOutput += output + "\n";
|
||||
};
|
||||
|
||||
pyodide.setStdout({ batched: outputHandler });
|
||||
pyodide.setStderr({ batched: outputHandler });
|
||||
try {
|
||||
const pyodide = await loadPyodide({
|
||||
env: {
|
||||
HOME: SANDBOX_BASE_DIRECTORY,
|
||||
},
|
||||
});
|
||||
|
||||
for (const [fileName, content] of Object.entries(workspace.files)) {
|
||||
const lastSeparator = fileName.lastIndexOf("/");
|
||||
pyodide.setStdout({ batched: outputHandler });
|
||||
pyodide.setStderr({ batched: outputHandler });
|
||||
|
||||
if (lastSeparator !== -1) {
|
||||
const directory =
|
||||
SANDBOX_BASE_DIRECTORY + fileName.slice(0, lastSeparator);
|
||||
pyodide.FS.mkdirTree(directory);
|
||||
for (const [fileName, content] of Object.entries(workspace.files)) {
|
||||
const lastSeparator = fileName.lastIndexOf("/");
|
||||
|
||||
if (lastSeparator !== -1) {
|
||||
const directory =
|
||||
SANDBOX_BASE_DIRECTORY + fileName.slice(0, lastSeparator);
|
||||
pyodide.FS.mkdirTree(directory);
|
||||
}
|
||||
|
||||
pyodide.FS.writeFile(SANDBOX_BASE_DIRECTORY + fileName, content);
|
||||
}
|
||||
|
||||
pyodide.FS.writeFile(SANDBOX_BASE_DIRECTORY + fileName, content);
|
||||
}
|
||||
const dict = pyodide.globals.get("dict");
|
||||
const globals = dict();
|
||||
|
||||
const dict = pyodide.globals.get("dict");
|
||||
const globals = dict();
|
||||
|
||||
try {
|
||||
// Patch `reveal_type` to print runtime values
|
||||
pyodide.runPython(`
|
||||
try {
|
||||
pyodide.runPython(`
|
||||
import builtins
|
||||
|
||||
def reveal_type(obj):
|
||||
@@ -46,17 +47,18 @@ export async function runPython(workspace: SerializedFiles): Promise<string> {
|
||||
|
||||
builtins.reveal_type = reveal_type`);
|
||||
|
||||
pyodide.runPython(workspace.files[workspace.current] ?? "", {
|
||||
globals,
|
||||
locals: globals,
|
||||
filename: workspace.current,
|
||||
});
|
||||
pyodide.runPython(workspace.files[workspace.current] ?? "", {
|
||||
globals,
|
||||
locals: globals,
|
||||
filename: workspace.current,
|
||||
});
|
||||
} finally {
|
||||
globals.destroy();
|
||||
dict.destroy();
|
||||
}
|
||||
|
||||
return combinedOutput;
|
||||
} catch (error) {
|
||||
return `Failed to run Python script: ${error}`;
|
||||
} finally {
|
||||
globals.destroy();
|
||||
dict.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export function viteStaticCopyPyodide() {
|
||||
{
|
||||
src: [pyodideDir, ...PYODIDE_EXCLUDE],
|
||||
dest: "assets",
|
||||
rename: { stripBase: true },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user