From f8cd281dac48b46becf57555ad2e601564659e58 Mon Sep 17 00:00:00 2001 From: Eli Lamb Date: Sat, 21 Jan 2023 18:35:47 +1300 Subject: [PATCH] WIP access globals --- src/hooks/useGlobals.ts | 24 ++++++++++++++++++++ src/hooks/usePython.ts | 9 ++++++++ src/types/Runner.ts | 4 ++++ src/workers/python-console-worker.ts | 8 +++++-- src/workers/python-worker.ts | 19 ++++++++++++++-- website/docs/examples/playground.md | 20 ----------------- website/docs/examples/playground.mdx | 26 +++++++++++++++++++++ website/src/components/ScopeExample.tsx | 30 +++++++++++++++++++++++++ 8 files changed, 116 insertions(+), 24 deletions(-) create mode 100644 src/hooks/useGlobals.ts delete mode 100644 website/docs/examples/playground.md create mode 100644 website/docs/examples/playground.mdx create mode 100644 website/src/components/ScopeExample.tsx diff --git a/src/hooks/useGlobals.ts b/src/hooks/useGlobals.ts new file mode 100644 index 00000000..8c077e57 --- /dev/null +++ b/src/hooks/useGlobals.ts @@ -0,0 +1,24 @@ +import { Remote } from 'comlink' +import { Runner } from '../types/Runner' + +interface UseGlobalsProps { + runner: Remote | undefined +} + +export default function useGlobals(props: UseGlobalsProps) { + const { runner } = props + + const getGlobal = (variable: string) => { + return runner?.getGlobal(variable) + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const setGlobal = (variable: string, value: any) => { + return runner?.setGlobal(variable, value) + } + + return { + getGlobal, + setGlobal + } +} diff --git a/src/hooks/usePython.ts b/src/hooks/usePython.ts index 197fdd69..4cea886b 100644 --- a/src/hooks/usePython.ts +++ b/src/hooks/usePython.ts @@ -1,6 +1,7 @@ import { useContext, useEffect, useMemo, useRef, useState } from 'react' import { PythonContext, suppressedMessages } from '../providers/PythonProvider' import { proxy, Remote, wrap } from 'comlink' +import useGlobals from './useGlobals' import useFilesystem from './useFilesystem' import { Packages } from '../types/Packages' @@ -32,6 +33,8 @@ export default function usePython(props?: UsePythonProps) { const workerRef = useRef() const runnerRef = useRef>() + const { getGlobal, setGlobal } = useGlobals({ runner: runnerRef?.current }) + const { readFile, writeFile, @@ -144,6 +147,7 @@ import sys sys.tracebacklimit = 0 +# Patch time.sleep import time def sleep(seconds): start = now = time.time() @@ -151,7 +155,10 @@ def sleep(seconds): now = time.time() time.sleep = sleep +globals_ = {} + def run(code, preamble=''): + global globals_ globals_ = {} try: exec(preamble, globals_) @@ -251,6 +258,8 @@ del sys isReady, isRunning, interruptExecution, + getGlobal, + setGlobal, readFile, writeFile, mkdir, diff --git a/src/types/Runner.ts b/src/types/Runner.ts index 6c245c53..40895592 100644 --- a/src/types/Runner.ts +++ b/src/types/Runner.ts @@ -4,6 +4,10 @@ export interface Runner { onLoad: ({ version, banner }: { version: string; banner?: string }) => void, packages?: string[][] ) => Promise + // eslint-disable-next-line @typescript-eslint/no-explicit-any + getGlobal: (variable: string) => any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + setGlobal: (variable: string, value: any) => void interruptExecution: () => void readFile: (name: string) => void writeFile: (name: string, data: string) => void diff --git a/src/workers/python-console-worker.ts b/src/workers/python-console-worker.ts index 534f5c9e..466097ca 100644 --- a/src/workers/python-console-worker.ts +++ b/src/workers/python-console-worker.ts @@ -12,8 +12,12 @@ interface Pyodide { mkdir: (name: string) => void rmdir: (name: string) => void } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - globals: any + globals: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get: (variable: string) => any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + set: (variable: string, value: any) => void + } isPyProxy: (value: unknown) => boolean } diff --git a/src/workers/python-worker.ts b/src/workers/python-worker.ts index 487b5352..726a7188 100644 --- a/src/workers/python-worker.ts +++ b/src/workers/python-worker.ts @@ -12,8 +12,12 @@ interface Pyodide { mkdir: (name: string) => void rmdir: (name: string) => void } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - globals: any + globals: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get: (variable: string) => any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + set: (variable: string, value: any) => void + } isPyProxy: (value: unknown) => boolean } @@ -60,6 +64,17 @@ const python = { }, async run(code: string) { await self.pyodide.runPythonAsync(code) + const g = self.pyodide.globals.get('globals_') // dict + console.debug('y', g.get('y')) // 5 + }, + getGlobal(variable: string) { + const g = self.pyodide.globals.get('globals_') // undefined + console.debug('y', g.get('y')) // (crashed in prev step) + + return g.get(variable) + }, + setGlobal(variable: string, value: unknown) { + return self.pyodide.globals.set(variable, value) }, readFile(name: string) { return self.pyodide.FS.readFile(name, { encoding: 'utf8' }) diff --git a/website/docs/examples/playground.md b/website/docs/examples/playground.md deleted file mode 100644 index f11f7113..00000000 --- a/website/docs/examples/playground.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -sidebar_position: 0 -draft: true ---- - -# Playground - -Used for testing bugs etc. - -```python -with open("/hello.txt", "w") as fh: - fh.write("hello world!") - print("done") -``` - -```python -with open("/hello.txt", "r") as fh: - data = fh.read() -print(data) -``` diff --git a/website/docs/examples/playground.mdx b/website/docs/examples/playground.mdx new file mode 100644 index 00000000..8c1e308a --- /dev/null +++ b/website/docs/examples/playground.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 0 +draft: true +--- + +import ScopeExample from '../../src/components/ScopeExample' + +# Playground + +Used for testing bugs etc. + +```python +# x = 2 + 3 +y = 2 + 3 +print(y) +``` + + + + + +```python +square(3) +``` diff --git a/website/src/components/ScopeExample.tsx b/website/src/components/ScopeExample.tsx new file mode 100644 index 00000000..d2bf9e94 --- /dev/null +++ b/website/src/components/ScopeExample.tsx @@ -0,0 +1,30 @@ +import React, { useState } from 'react' +import { usePython } from '@site/../dist' + +export default function ScopeExample() { + const { getGlobal, setGlobal } = usePython() + + const [x, setX] = useState() + + return ( +
+

Scope

+ +
+ x: {JSON.stringify(x)} +
+ ) +}