mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-20 10:47:35 -05:00
Compare commits
9 Commits
better-don
...
2023.05.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
848d77b1c2 | ||
|
|
e4e8f2edae | ||
|
|
ea9bdcc961 | ||
|
|
79ad39260e | ||
|
|
f4936316ab | ||
|
|
8879187e6a | ||
|
|
258b80a6a5 | ||
|
|
a108e6e97e | ||
|
|
dfef7eda3b |
6
.github/workflows/build-unstable.yml
vendored
6
.github/workflows/build-unstable.yml
vendored
@@ -20,7 +20,7 @@ on:
|
||||
|
||||
jobs:
|
||||
BuildAndTest:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
defaults:
|
||||
run:
|
||||
working-directory: pyscriptjs
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
path: pyscriptjs/test_results
|
||||
if-no-files-found: error
|
||||
eslint:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
defaults:
|
||||
run:
|
||||
working-directory: pyscriptjs
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
run: npx eslint src -c .eslintrc.js
|
||||
|
||||
Deploy:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
needs: BuildAndTest
|
||||
if: github.ref == 'refs/heads/main' # Only deploy on merge into main
|
||||
permissions:
|
||||
|
||||
2
.github/workflows/docs-release.yml
vendored
2
.github/workflows/docs-release.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
2
.github/workflows/docs-review.yml
vendored
2
.github/workflows/docs-review.yml
vendored
@@ -19,7 +19,7 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner == 'pyscript'
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
2
.github/workflows/docs-unstable.yml
vendored
2
.github/workflows/docs-unstable.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
18
.github/workflows/prepare-release.yml
vendored
18
.github/workflows/prepare-release.yml
vendored
@@ -15,7 +15,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
@@ -44,8 +44,20 @@ jobs:
|
||||
- name: Setup Environment
|
||||
run: make setup
|
||||
|
||||
- name: Build and Test
|
||||
run: make test
|
||||
- name: Build
|
||||
run: make build
|
||||
|
||||
- name: TypeScript Tests
|
||||
run: make test-ts
|
||||
|
||||
- name: Python Tests
|
||||
run: make test-py
|
||||
|
||||
- name: Integration Tests
|
||||
run: make test-integration-parallel
|
||||
|
||||
- name: Examples Tests
|
||||
run: make test-examples
|
||||
|
||||
- name: Zip build folder
|
||||
run: zip -r -q ./build.zip ./build
|
||||
|
||||
18
.github/workflows/publish-release.yml
vendored
18
.github/workflows/publish-release.yml
vendored
@@ -14,7 +14,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -46,8 +46,20 @@ jobs:
|
||||
- name: Setup Environment
|
||||
run: make setup
|
||||
|
||||
- name: Build and Test
|
||||
run: make test
|
||||
- name: Build
|
||||
run: make build
|
||||
|
||||
- name: TypeScript Tests
|
||||
run: make test-ts
|
||||
|
||||
- name: Python Tests
|
||||
run: make test-py
|
||||
|
||||
- name: Integration Tests
|
||||
run: make test-integration-parallel
|
||||
|
||||
- name: Examples Tests
|
||||
run: make test-examples
|
||||
|
||||
# Upload to S3
|
||||
- name: Configure AWS credentials
|
||||
|
||||
2
.github/workflows/publish-snapshot.yml
vendored
2
.github/workflows/publish-snapshot.yml
vendored
@@ -11,7 +11,7 @@ on:
|
||||
|
||||
jobs:
|
||||
snapshot:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
2
.github/workflows/sync-examples.yml
vendored
2
.github/workflows/sync-examples.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
128
.github/workflows/test-next.yml
vendored
Normal file
128
.github/workflows/test-next.yml
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
name: "[CI] Test Next"
|
||||
|
||||
on:
|
||||
push: # Only run on merges into main that modify files under pyscriptjs/ and examples/
|
||||
branches:
|
||||
- next
|
||||
paths:
|
||||
- pyscript.core/**
|
||||
- pyscriptjs/**
|
||||
- examples/**
|
||||
- .github/workflows/test-next.yml # Test that workflow works when changed
|
||||
|
||||
pull_request: # Run on any PR that modifies files under pyscriptjs/ and examples/
|
||||
branches:
|
||||
- next
|
||||
paths:
|
||||
- pyscript.core/**
|
||||
- pyscriptjs/**
|
||||
- examples/**
|
||||
- .github/workflows/test-next.yml # Test that workflow works when changed
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
BuildAndTest:
|
||||
runs-on: ubuntu-latest-8core
|
||||
defaults:
|
||||
run:
|
||||
working-directory: pyscriptjs
|
||||
env:
|
||||
MINICONDA_PYTHON_VERSION: py38
|
||||
MINICONDA_VERSION: 4.11.0
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: setup Miniconda
|
||||
uses: conda-incubator/setup-miniconda@v2
|
||||
|
||||
- name: Setup Environment
|
||||
run: make setup
|
||||
|
||||
- name: Build
|
||||
run: make build
|
||||
|
||||
- name: TypeScript Tests (core)
|
||||
run: make test-ts
|
||||
|
||||
- name: Python Tests
|
||||
run: make test-py
|
||||
|
||||
- name: install next deps
|
||||
working-directory: pyscript.core
|
||||
run: npm i
|
||||
|
||||
- name: Run next tests
|
||||
working-directory: pyscript.core
|
||||
run: npm test
|
||||
|
||||
- name: Integration Tests
|
||||
run: make test-integration-parallel
|
||||
|
||||
- name: Examples Tests
|
||||
run: make test-examples
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: pyscript
|
||||
path: |
|
||||
pyscriptjs/build/
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: success() || failure()
|
||||
with:
|
||||
name: test_results
|
||||
path: pyscriptjs/test_results
|
||||
if-no-files-found: error
|
||||
eslint:
|
||||
runs-on: ubuntu-latest-8core
|
||||
defaults:
|
||||
run:
|
||||
working-directory: pyscriptjs
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
|
||||
- name: npm install
|
||||
run: npm install
|
||||
|
||||
- name: Eslint
|
||||
run: npx eslint src -c .eslintrc.js
|
||||
2
.github/workflows/test_report.yml
vendored
2
.github/workflows/test_report.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
- completed
|
||||
jobs:
|
||||
report:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-8core
|
||||
steps:
|
||||
- uses: dorny/test-reporter@v1.6.0
|
||||
with:
|
||||
|
||||
@@ -32,6 +32,7 @@ Features
|
||||
- Added a `stderr` attribute of `py-repl` tags to route `sys.stderr` to a DOM element with the given ID. ([#1106](https://github.com/pyscript/pyscript/pull/1106))
|
||||
- Resored the `output-mode` attribute of `py-repl` tags. If `output-mode` == 'append', the DOM element where output is printed is _not_ cleared before writing new results.
|
||||
- Load code from the attribute src of py-repl and preload it into the corresponding py-repl tag by use the attribute `str` in your `py-repl` tag([#1292](https://github.com/pyscript/pyscript/pull/1292))
|
||||
- <py-repl> elements now have a `getPySrc()` method, which returns the code inside the REPL as a string.([#1516](https://github.com/pyscript/pyscript/pull/1292))
|
||||
|
||||
### Plugins
|
||||
- Plugins may now implement the `beforePyReplExec()` and `afterPyReplExec()` hooks, which are called immediately before and after code in a `py-repl` tag is executed. ([#1106](https://github.com/pyscript/pyscript/pull/1106))
|
||||
@@ -57,7 +58,7 @@ Docs
|
||||
|
||||
- Add docs for event handlers
|
||||
|
||||
2023.01.1
|
||||
2023.03.1
|
||||
=========
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,14 @@ The ID of an element in the DOM that `stderr` will be written to. Defaults to No
|
||||
### `src`
|
||||
If a \<py-repl\> tag has the `src` attribute, during page initialization, resource in the `src` will be preloaded into the REPL. Please note that this will not run in advance. If there is content in the \<py-repl\> tag, it will be cleared and replaced with preloaded resource.
|
||||
|
||||
## Methods
|
||||
|
||||
The following are methods that can be called on the \<py-repl\> element, from within Python or JavaScript
|
||||
|
||||
### `getPySrc()`
|
||||
|
||||
Returns the current code contents of the REPL as a string.
|
||||
|
||||
## Examples
|
||||
|
||||
### `<py-repl>` element set to auto-generate
|
||||
|
||||
20
pyscriptjs/package-lock.json
generated
20
pyscriptjs/package-lock.json
generated
@@ -34,7 +34,7 @@
|
||||
"prettier": "2.7.1",
|
||||
"pyodide": "0.23.2",
|
||||
"synclink": "0.2.4",
|
||||
"ts-jest": "29.0.3",
|
||||
"ts-jest": "29.1.0",
|
||||
"typescript": "5.0.4",
|
||||
"xterm": "^5.1.0"
|
||||
}
|
||||
@@ -5674,15 +5674,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ts-jest": {
|
||||
"version": "29.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
|
||||
"integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==",
|
||||
"version": "29.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz",
|
||||
"integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"bs-logger": "0.x",
|
||||
"fast-json-stable-stringify": "2.x",
|
||||
"jest-util": "^29.0.0",
|
||||
"json5": "^2.2.1",
|
||||
"json5": "^2.2.3",
|
||||
"lodash.memoize": "4.x",
|
||||
"make-error": "1.x",
|
||||
"semver": "7.x",
|
||||
@@ -5699,7 +5699,7 @@
|
||||
"@jest/types": "^29.0.0",
|
||||
"babel-jest": "^29.0.0",
|
||||
"jest": "^29.0.0",
|
||||
"typescript": ">=4.3"
|
||||
"typescript": ">=4.3 <6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@babel/core": {
|
||||
@@ -10247,15 +10247,15 @@
|
||||
}
|
||||
},
|
||||
"ts-jest": {
|
||||
"version": "29.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
|
||||
"integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==",
|
||||
"version": "29.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz",
|
||||
"integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bs-logger": "0.x",
|
||||
"fast-json-stable-stringify": "2.x",
|
||||
"jest-util": "^29.0.0",
|
||||
"json5": "^2.2.1",
|
||||
"json5": "^2.2.3",
|
||||
"lodash.memoize": "4.x",
|
||||
"make-error": "1.x",
|
||||
"semver": "7.x",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"prettier": "2.7.1",
|
||||
"pyodide": "0.23.2",
|
||||
"synclink": "0.2.4",
|
||||
"ts-jest": "29.0.3",
|
||||
"ts-jest": "29.1.0",
|
||||
"typescript": "5.0.4",
|
||||
"xterm": "^5.1.0"
|
||||
},
|
||||
|
||||
@@ -191,7 +191,7 @@ export function make_PyRepl(interpreter: InterpreterClient, app: PyScriptApp) {
|
||||
pyReplTag: this,
|
||||
result,
|
||||
});
|
||||
|
||||
await interpreter._remote.destroyIfProxy(result);
|
||||
this.autogenerateMaybe();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ export function make_PyScript(interpreter: InterpreterClient, app: PyScriptApp)
|
||||
await app.plugins.beforePyScriptExec({ interpreter, src, pyScriptTag });
|
||||
const { result } = await pyExec(interpreter, src, pyScriptTag);
|
||||
await app.plugins.afterPyScriptExec({ interpreter, src, pyScriptTag, result });
|
||||
await interpreter._remote.destroyIfProxy(result);
|
||||
} finally {
|
||||
releaseLock();
|
||||
app.decrementPendingTags();
|
||||
|
||||
@@ -71,6 +71,7 @@ export let runtime;
|
||||
export class PyScriptApp {
|
||||
config: AppConfig;
|
||||
interpreter: InterpreterClient;
|
||||
unwrapped_remote: RemoteInterpreter;
|
||||
readyPromise: Promise<void>;
|
||||
PyScript: ReturnType<typeof make_PyScript>;
|
||||
plugins: PluginManager;
|
||||
@@ -139,10 +140,10 @@ export class PyScriptApp {
|
||||
await this.plugins.configure(this.config);
|
||||
this.plugins.beforeLaunch(this.config);
|
||||
await this.loadInterpreter();
|
||||
interpreter = this.interpreter;
|
||||
interpreter = this.unwrapped_remote;
|
||||
// TODO: This is for backwards compatibility, it should be removed
|
||||
// when we finish the deprecation cycle of `runtime`
|
||||
runtime = this.interpreter;
|
||||
runtime = this.unwrapped_remote;
|
||||
}
|
||||
|
||||
// lifecycle (2)
|
||||
@@ -193,6 +194,7 @@ export class PyScriptApp {
|
||||
logger.info('Starting the interpreter in the main thread');
|
||||
// this is basically equivalent to worker_initialize()
|
||||
const remote_interpreter = new RemoteInterpreter(interpreter_cfg.src);
|
||||
this.unwrapped_remote = remote_interpreter;
|
||||
const { port1, port2 } = new Synclink.FakeMessageChannel() as unknown as MessageChannel;
|
||||
port1.start();
|
||||
port2.start();
|
||||
|
||||
@@ -4,7 +4,7 @@ from contextlib import contextmanager
|
||||
|
||||
from js import Object
|
||||
from pyodide.code import eval_code
|
||||
from pyodide.ffi import JsProxy
|
||||
from pyodide.ffi import JsProxy, to_js
|
||||
|
||||
from ._event_loop import (
|
||||
defer_user_asyncio,
|
||||
@@ -103,7 +103,7 @@ def run_pyscript(code: str, id: str = None) -> JsProxy:
|
||||
with display_target(id), defer_user_asyncio():
|
||||
result = eval_code(code, globals=__main__.__dict__)
|
||||
|
||||
return Object.new(result=result)
|
||||
return to_js({"result": result}, depth=1, dict_converter=Object.fromEntries)
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
||||
@@ -274,6 +274,20 @@ export class RemoteInterpreter extends Object {
|
||||
this.FS.writeFile(path, data, { canOwn: true });
|
||||
}
|
||||
|
||||
destroyIfProxy(px: any): void {
|
||||
if (this.interface.ffi) {
|
||||
// Pyodide 0.23
|
||||
if (px instanceof this.interface.ffi.PyProxy) {
|
||||
px.destroy();
|
||||
}
|
||||
} else {
|
||||
// older Pyodide
|
||||
if (this.interface.isPyProxy(px)) {
|
||||
px.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates clearing importlib's module path
|
||||
* caches to the underlying interface
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
from .support import PyScriptTest
|
||||
from .support import PyScriptTest, skip_worker
|
||||
|
||||
|
||||
class TestInterpreterAccess(PyScriptTest):
|
||||
"""Test accessing Python objects from JS via pyscript.interpreter"""
|
||||
|
||||
@skip_worker("WONTFIX: used without synclink to avoid awaits")
|
||||
def test_interpreter_python_access(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
@@ -17,9 +18,9 @@ class TestInterpreterAccess(PyScriptTest):
|
||||
|
||||
self.run_js(
|
||||
"""
|
||||
const x = await pyscript.interpreter.globals.get('x');
|
||||
const py_func = await pyscript.interpreter.globals.get('py_func');
|
||||
const py_func_res = await py_func();
|
||||
const x = pyscript.interpreter.globals.get('x');
|
||||
const py_func = pyscript.interpreter.globals.get('py_func');
|
||||
const py_func_res = py_func();
|
||||
console.log(`x is ${x}`);
|
||||
console.log(`py_func() returns ${py_func_res}`);
|
||||
"""
|
||||
@@ -29,13 +30,14 @@ class TestInterpreterAccess(PyScriptTest):
|
||||
"py_func() returns 2",
|
||||
]
|
||||
|
||||
@skip_worker("WONTFIX: used without synclink")
|
||||
def test_interpreter_script_execution(self):
|
||||
"""Test running Python code from js via pyscript.interpreter"""
|
||||
self.pyscript_run("")
|
||||
|
||||
self.run_js(
|
||||
"""
|
||||
const interface = pyscript.interpreter._remote.interface;
|
||||
const interface = pyscript.interpreter.interface;
|
||||
await interface.runPython('print("Interpreter Ran This")');
|
||||
"""
|
||||
)
|
||||
@@ -46,13 +48,14 @@ class TestInterpreterAccess(PyScriptTest):
|
||||
py_terminal = self.page.wait_for_selector("py-terminal")
|
||||
assert py_terminal.text_content() == expected_message
|
||||
|
||||
@skip_worker("WONTFIX: used without synclink")
|
||||
def test_backward_compatibility_runtime_script_execution(self):
|
||||
"""Test running Python code from js via pyscript.runtime"""
|
||||
self.pyscript_run("")
|
||||
|
||||
self.run_js(
|
||||
"""
|
||||
const interface = pyscript.runtime._remote.interpreter;
|
||||
const interface = pyscript.runtime.interpreter;
|
||||
await interface.runPython('print("Interpreter Ran This")');
|
||||
"""
|
||||
)
|
||||
@@ -63,6 +66,7 @@ class TestInterpreterAccess(PyScriptTest):
|
||||
py_terminal = self.page.wait_for_selector("py-terminal")
|
||||
assert py_terminal.text_content() == expected_message
|
||||
|
||||
@skip_worker("WONTFIX: used without synclink to avoid awaits")
|
||||
def test_backward_compatibility_runtime_python_access(self):
|
||||
"""Test accessing Python objects from JS via pyscript.runtime"""
|
||||
self.pyscript_run(
|
||||
@@ -77,9 +81,9 @@ class TestInterpreterAccess(PyScriptTest):
|
||||
|
||||
self.run_js(
|
||||
"""
|
||||
const x = await pyscript.interpreter.globals.get('x');
|
||||
const py_func = await pyscript.interpreter.globals.get('py_func');
|
||||
const py_func_res = await py_func();
|
||||
const x = pyscript.runtime.globals.get('x');
|
||||
const py_func = pyscript.runtime.globals.get('py_func');
|
||||
const py_func_res = py_func();
|
||||
console.log(`x is ${x}`);
|
||||
console.log(`py_func() returns ${py_func_res}`);
|
||||
"""
|
||||
|
||||
@@ -595,6 +595,26 @@ class TestPyRepl(PyScriptTest):
|
||||
alert_banner = self.page.wait_for_selector(".alert-banner")
|
||||
assert expected_alert_banner_msg in alert_banner.inner_text()
|
||||
|
||||
def test_getPySrc_Contents(self):
|
||||
"""Test that an empty REPL returns an empty string as src, and that the typed contents
|
||||
are returned as the source
|
||||
"""
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-repl>
|
||||
</py-repl>
|
||||
"""
|
||||
)
|
||||
py_repl = self.page.locator("py-repl")
|
||||
src = py_repl.evaluate("node => node.getPySrc()")
|
||||
assert src == ""
|
||||
assert type(src) == str
|
||||
|
||||
py_repl.focus()
|
||||
py_repl.type("Hello, world!")
|
||||
src = py_repl.evaluate("node => node.getPySrc()")
|
||||
assert src == "Hello, world!"
|
||||
|
||||
def test_repl_load_content_from_src(self):
|
||||
self.writefile("loadReplSrc1.py", "print('1')")
|
||||
self.pyscript_run(
|
||||
@@ -654,3 +674,47 @@ class TestPyRepl(PyScriptTest):
|
||||
"Are your filename and path correct?"
|
||||
)
|
||||
assert self.console.error.lines[-1] == errorMsg
|
||||
|
||||
@skip_worker("dont-care")
|
||||
def test_repl_results(self):
|
||||
self.writefile("loadReplSrc2.py", "2")
|
||||
self.writefile("loadReplSrc3.py", "print('3')")
|
||||
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-repl id="py-repl1" output="out1">
|
||||
42
|
||||
</py-repl>
|
||||
<div id="out1"></div>
|
||||
|
||||
<py-repl id="py-repl2" output="out2">
|
||||
c = [1,2,3]
|
||||
from sys import getrefcount
|
||||
# should print 2: 1 from the reference c and 1 since getrefcount
|
||||
# holds a reference to its argument
|
||||
print(getrefcount(c))
|
||||
c
|
||||
</py-repl>
|
||||
<div id="out2"></div>
|
||||
|
||||
<py-repl id="py-repl3" output="out3">
|
||||
# should also print 2: if it prints 3 that would mean that c was not properly
|
||||
# released by py-repl
|
||||
getrefcount(c)
|
||||
</py-repl>
|
||||
<div id="out3"></div>
|
||||
"""
|
||||
)
|
||||
py_repl1 = self.page.locator("py-repl#py-repl1")
|
||||
py_repl1.locator("button").click()
|
||||
|
||||
py_repl2 = self.page.locator("py-repl#py-repl2")
|
||||
py_repl2.locator("button").click()
|
||||
|
||||
py_repl3 = self.page.locator("py-repl#py-repl3")
|
||||
py_repl3.locator("button").click()
|
||||
|
||||
assert self.page.wait_for_selector("#out1").inner_text() == "42"
|
||||
assert self.page.wait_for_selector("#out2").inner_text() == "2\n\n[1, 2, 3]"
|
||||
# Check that c was released
|
||||
assert self.page.wait_for_selector("#out3").inner_text() == "2"
|
||||
|
||||
Reference in New Issue
Block a user