mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d0ea96435 | ||
|
|
fafdf74007 | ||
|
|
999897df12 | ||
|
|
d47fb58ede | ||
|
|
f316341e73 | ||
|
|
8c46fcabf7 | ||
|
|
e4ff4d8fab | ||
|
|
f20a0003ed | ||
|
|
6c938dfe3b | ||
|
|
d884586a82 |
892
pyscript.core/package-lock.json
generated
892
pyscript.core/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pyscript/core",
|
||||
"version": "0.4.55",
|
||||
"version": "0.5.3",
|
||||
"type": "module",
|
||||
"description": "PyScript",
|
||||
"module": "./index.js",
|
||||
@@ -44,7 +44,7 @@
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"polyscript": "^0.13.8",
|
||||
"polyscript": "^0.15.0",
|
||||
"sticky-module": "^0.1.1",
|
||||
"to-json-callback": "^0.1.1",
|
||||
"type-checked-collections": "^0.1.7"
|
||||
@@ -54,24 +54,24 @@
|
||||
"@codemirror/lang-python": "^6.1.6",
|
||||
"@codemirror/language": "^6.10.2",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
"@codemirror/view": "^6.28.3",
|
||||
"@playwright/test": "^1.45.1",
|
||||
"@codemirror/view": "^6.30.0",
|
||||
"@playwright/test": "^1.45.3",
|
||||
"@rollup/plugin-commonjs": "^26.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@webreflection/toml-j0.4": "^1.1.3",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/addon-web-links": "^0.11.0",
|
||||
"bun": "^1.1.17",
|
||||
"bun": "^1.1.21",
|
||||
"chokidar": "^3.6.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"eslint": "^9.6.0",
|
||||
"eslint": "^9.8.0",
|
||||
"flatted": "^3.3.1",
|
||||
"rollup": "^4.18.0",
|
||||
"rollup": "^4.20.0",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-string": "^3.0.0",
|
||||
"static-handler": "^0.4.3",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript": "^5.5.4",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-readline": "^1.1.1"
|
||||
},
|
||||
|
||||
BIN
pyscript.core/pyscript-core-0.5.3-rc1.tgz
Normal file
BIN
pyscript.core/pyscript-core-0.5.3-rc1.tgz
Normal file
Binary file not shown.
@@ -12,6 +12,7 @@ import {
|
||||
define,
|
||||
defineProperty,
|
||||
dispatch,
|
||||
isSync,
|
||||
queryTarget,
|
||||
unescape,
|
||||
whenDefined,
|
||||
@@ -202,15 +203,13 @@ for (const [TYPE, interpreter] of TYPES) {
|
||||
}
|
||||
|
||||
if (isScript(element)) {
|
||||
const {
|
||||
attributes: { async: isAsync, target },
|
||||
} = element;
|
||||
const hasTarget = !!target?.value;
|
||||
const show = hasTarget
|
||||
? queryTarget(element, target.value)
|
||||
const isAsync = !isSync(element);
|
||||
const target = element.getAttribute("target");
|
||||
const show = target
|
||||
? queryTarget(element, target)
|
||||
: document.createElement("script-py");
|
||||
|
||||
if (!hasTarget) {
|
||||
if (!target) {
|
||||
const { head, body } = document;
|
||||
if (head.contains(element)) body.append(show);
|
||||
else element.after(show);
|
||||
@@ -331,7 +330,7 @@ for (const [TYPE, interpreter] of TYPES) {
|
||||
async connectedCallback() {
|
||||
if (!this.executed) {
|
||||
this.executed = true;
|
||||
const isAsync = this.hasAttribute("async");
|
||||
const isAsync = !isSync(this);
|
||||
const { io, run, runAsync } = await this._wrap
|
||||
.promise;
|
||||
this.srcCode = await fetchSource(
|
||||
|
||||
@@ -34,7 +34,10 @@ async function execute({ currentTarget }) {
|
||||
|
||||
if (!envs.has(env)) {
|
||||
const srcLink = URL.createObjectURL(new Blob([""]));
|
||||
const details = { type: this.interpreter };
|
||||
const details = {
|
||||
type: this.interpreter,
|
||||
serviceWorker: this.serviceWorker,
|
||||
};
|
||||
const { config } = this;
|
||||
if (config) {
|
||||
details.configURL = relative_url(config);
|
||||
@@ -163,8 +166,17 @@ const init = async (script, type, interpreter) => {
|
||||
|
||||
let isSetup = script.hasAttribute("setup");
|
||||
const hasConfig = script.hasAttribute("config");
|
||||
const serviceWorker = script.getAttribute("service-worker");
|
||||
const env = `${interpreter}-${script.getAttribute("env") || getID(type)}`;
|
||||
|
||||
// helps preventing too lazy ServiceWorker initialization on button run
|
||||
if (serviceWorker) {
|
||||
new XWorker("data:application/javascript,postMessage(0)", {
|
||||
type: "dummy",
|
||||
serviceWorker,
|
||||
}).onmessage = ({ target }) => target.terminate();
|
||||
}
|
||||
|
||||
if (hasConfig && configs.has(env)) {
|
||||
throw new SyntaxError(
|
||||
configs.get(env)
|
||||
@@ -181,6 +193,7 @@ const init = async (script, type, interpreter) => {
|
||||
const context = {
|
||||
// allow the listener to be overridden at distance
|
||||
handleEvent: execute,
|
||||
serviceWorker,
|
||||
interpreter,
|
||||
env,
|
||||
config: hasConfig && script.getAttribute("config"),
|
||||
|
||||
@@ -20,7 +20,7 @@ def when(event_type=None, selector=None):
|
||||
|
||||
def decorator(func):
|
||||
|
||||
from pyscript.web.elements import Element, ElementCollection
|
||||
from pyscript.web import Element, ElementCollection
|
||||
|
||||
if isinstance(selector, str):
|
||||
elements = document.querySelectorAll(selector)
|
||||
|
||||
@@ -36,7 +36,6 @@ if RUNNING_IN_WORKER:
|
||||
)
|
||||
|
||||
try:
|
||||
globalThis.SharedArrayBuffer.new(4)
|
||||
import js
|
||||
|
||||
window = polyscript.xworker.window
|
||||
@@ -47,17 +46,11 @@ if RUNNING_IN_WORKER:
|
||||
"return (...urls) => Promise.all(urls.map((url) => import(url)))"
|
||||
)()
|
||||
except:
|
||||
globalThis.console.debug("SharedArrayBuffer is not available")
|
||||
# in this scenario none of the utilities would work
|
||||
# as expected so we better export these as NotSupported
|
||||
window = NotSupported(
|
||||
"pyscript.window",
|
||||
"pyscript.window in workers works only via SharedArrayBuffer",
|
||||
)
|
||||
document = NotSupported(
|
||||
"pyscript.document",
|
||||
"pyscript.document in workers works only via SharedArrayBuffer",
|
||||
)
|
||||
message = "Unable to use `window` or `document` -> https://docs.pyscript.net/latest/faq/#sharedarraybuffer"
|
||||
globalThis.console.warn(message)
|
||||
window = NotSupported("pyscript.window", message)
|
||||
document = NotSupported("pyscript.document", message)
|
||||
js_import = None
|
||||
|
||||
sync = polyscript.xworker.sync
|
||||
|
||||
|
||||
1176
pyscript.core/src/stdlib/pyscript/web.py
Normal file
1176
pyscript.core/src/stdlib/pyscript/web.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
from pyscript import document
|
||||
from pyscript.web.elements import ElementCollection, element_from_dom
|
||||
|
||||
|
||||
class DOM:
|
||||
def __init__(self):
|
||||
self.body = element_from_dom(document.body)
|
||||
self.head = element_from_dom(document.head)
|
||||
|
||||
def __getitem__(self, selector):
|
||||
return self.find(selector)
|
||||
|
||||
def find(self, selector):
|
||||
return ElementCollection(
|
||||
[element_from_dom(el) for el in document.querySelectorAll(selector)]
|
||||
)
|
||||
|
||||
|
||||
dom = DOM()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,11 +5,17 @@
|
||||
<script type="module" src="../dist/core.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<py-script async>
|
||||
<py-script>
|
||||
import asyncio
|
||||
print('foo')
|
||||
print('py-script sleep')
|
||||
await asyncio.sleep(1)
|
||||
print('bar')
|
||||
print('py-script done')
|
||||
</py-script>
|
||||
<script type="py">
|
||||
import asyncio
|
||||
print('script-py sleep')
|
||||
await asyncio.sleep(1)
|
||||
print('script-py done')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -48,12 +48,12 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="mpy" worker>
|
||||
<script type="mpy" async="false" worker>
|
||||
from pyscript import document
|
||||
print("actual code in worker")
|
||||
document.documentElement.classList.add('worker')
|
||||
</script>
|
||||
<script type="mpy">
|
||||
<script type="mpy" async="false">
|
||||
print("actual code in main")
|
||||
</script>
|
||||
</body>
|
||||
|
||||
4
pyscript.core/test/issue-7015/config.toml
Normal file
4
pyscript.core/test/issue-7015/config.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
packages = [
|
||||
"https://cdn.holoviz.org/panel/wheels/bokeh-3.5.0-py3-none-any.whl",
|
||||
"https://cdn.holoviz.org/panel/1.5.0-b.2/dist/wheels/panel-1.5.0b2-py3-none-any.whl"
|
||||
]
|
||||
17
pyscript.core/test/issue-7015/index.html
Normal file
17
pyscript.core/test/issue-7015/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="../../dist/core.css">
|
||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-3.5.0.js"></script>
|
||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.5.0.min.js"></script>
|
||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.5.0.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@holoviz/panel@1.5.0-b.2/dist/panel.min.js"></script>
|
||||
<script type="module" src="../../dist/core.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="py" src="main.py" config="config.toml" worker></script>
|
||||
<div id="simple_app"></div>
|
||||
</body>
|
||||
</html>
|
||||
12
pyscript.core/test/issue-7015/main.py
Normal file
12
pyscript.core/test/issue-7015/main.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import panel as pn
|
||||
|
||||
pn.extension(sizing_mode="stretch_width")
|
||||
|
||||
slider = pn.widgets.FloatSlider(start=0, end=10, name="amplitude")
|
||||
|
||||
|
||||
def callback(new):
|
||||
return f"Amplitude is: {new}"
|
||||
|
||||
|
||||
pn.Row(slider, pn.bind(callback, slider)).servable(target="simple_app")
|
||||
16
pyscript.core/test/py-editor/service-worker.html
Normal file
16
pyscript.core/test/py-editor/service-worker.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../../dist/core.css">
|
||||
<script type="module" src="../../dist/core.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="mpy-editor" service-worker="./sw.js">
|
||||
from pyscript import document
|
||||
|
||||
document.body.append("OK")
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1
pyscript.core/test/py-editor/sw.js
Normal file
1
pyscript.core/test/py-editor/sw.js
Normal file
@@ -0,0 +1 @@
|
||||
const{isArray:e}=Array,t=new Map,s=e=>{e.stopImmediatePropagation(),e.preventDefault()};var n=Object.freeze({__proto__:null,activate:e=>e.waitUntil(clients.claim()),fetch:e=>{const{request:n}=e;"POST"===n.method&&n.url===`${location.href}?sabayon`&&(s(e),e.respondWith(n.json().then((async e=>{const{promise:s,resolve:o}=Promise.withResolvers(),a=e.join(",");t.set(a,o);for(const t of await clients.matchAll())t.postMessage(e);return s.then((e=>new Response(`[${e.join(",")}]`,n.headers)))}))))},install:()=>skipWaiting(),message:n=>{const{data:o}=n;if(e(o)&&4===o.length){const[e,a,i,r]=o,l=[e,a,i].join(",");t.has(l)&&(s(n),t.get(l)(r),t.delete(l))}}});for(const e in n)addEventListener(e,n[e]);
|
||||
@@ -32,7 +32,7 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script type="py" src="./run_tests.py" config="./tests.toml"></script>
|
||||
<script type="py" src="/test/pyscript_dom/run_tests.py" config="/test/pyscript_dom/tests.toml"></script>
|
||||
|
||||
<h1>pyscript.dom Tests</h1>
|
||||
<p>You can pass test parameters to this test suite by passing them as query params on the url.
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
from pyscript import document, when
|
||||
from pyscript.web import dom
|
||||
from pyscript.web import elements as el
|
||||
from pyscript.web.elements import ElementCollection
|
||||
from pyscript.web import Element, ElementCollection, div, p, page
|
||||
|
||||
|
||||
class TestDocument:
|
||||
def test__element(self):
|
||||
assert dom.body._dom_element == document.body
|
||||
assert dom.head._dom_element == document.head
|
||||
assert page.body._dom_element == document.body
|
||||
assert page.head._dom_element == document.head
|
||||
|
||||
|
||||
def test_getitem_by_id():
|
||||
@@ -16,13 +14,13 @@ def test_getitem_by_id():
|
||||
txt = "You found test_id_selector"
|
||||
selector = f"#{id_}"
|
||||
# EXPECT the element to be found by id
|
||||
result = dom.find(selector)
|
||||
result = page.find(selector)
|
||||
div = result[0]
|
||||
# EXPECT the element text value to match what we expect and what
|
||||
# the JS document.querySelector API would return
|
||||
assert document.querySelector(selector).innerHTML == div.innerHTML == txt
|
||||
# EXPECT the results to be of the right types
|
||||
assert isinstance(div, el.Element)
|
||||
assert isinstance(div, Element)
|
||||
assert isinstance(result, ElementCollection)
|
||||
|
||||
|
||||
@@ -33,8 +31,7 @@ def test_getitem_by_class():
|
||||
"test_selector_w_children_child_1",
|
||||
]
|
||||
expected_class = "a-test-class"
|
||||
result = dom.find(f".{expected_class}")
|
||||
div = result[0]
|
||||
result = page.find(f".{expected_class}")
|
||||
|
||||
# EXPECT to find exact number of elements with the class in the page (== 3)
|
||||
assert len(result) == 3
|
||||
@@ -44,7 +41,7 @@ def test_getitem_by_class():
|
||||
|
||||
|
||||
def test_read_n_write_collection_elements():
|
||||
elements = dom.find(".multi-elems")
|
||||
elements = page.find(".multi-elems")
|
||||
|
||||
for element in elements:
|
||||
assert element.innerHTML == f"Content {element.id.replace('#', '')}"
|
||||
@@ -59,15 +56,15 @@ class TestElement:
|
||||
def test_query(self):
|
||||
# GIVEN an existing element on the page, with at least 1 child element
|
||||
id_ = "test_selector_w_children"
|
||||
parent_div = dom.find(f"#{id_}")[0]
|
||||
parent_div = page.find(f"#{id_}")[0]
|
||||
|
||||
# EXPECT it to be able to query for the first child element
|
||||
div = parent_div.find("div")[0]
|
||||
|
||||
# EXPECT the new element to be associated with the parent
|
||||
assert div.parent == parent_div
|
||||
# EXPECT the new element to be a el.Element
|
||||
assert isinstance(div, el.Element)
|
||||
# EXPECT the new element to be an Element
|
||||
assert isinstance(div, Element)
|
||||
# EXPECT the div attributes to be == to how they are configured in the page
|
||||
assert div.innerHTML == "Child 1"
|
||||
assert div.id == "test_selector_w_children_child_1"
|
||||
@@ -76,8 +73,8 @@ class TestElement:
|
||||
# GIVEN 2 different Elements pointing to the same underlying element
|
||||
id_ = "test_id_selector"
|
||||
selector = f"#{id_}"
|
||||
div = dom.find(selector)[0]
|
||||
div2 = dom.find(selector)[0]
|
||||
div = page.find(selector)[0]
|
||||
div2 = page.find(selector)[0]
|
||||
|
||||
# EXPECT them to be equal
|
||||
assert div == div2
|
||||
@@ -92,27 +89,27 @@ class TestElement:
|
||||
|
||||
def test_append_element(self):
|
||||
id_ = "element-append-tests"
|
||||
div = dom.find(f"#{id_}")[0]
|
||||
div = page.find(f"#{id_}")[0]
|
||||
len_children_before = len(div.children)
|
||||
new_el = el.p("new element")
|
||||
new_el = p("new element")
|
||||
div.append(new_el)
|
||||
assert len(div.children) == len_children_before + 1
|
||||
assert div.children[-1] == new_el
|
||||
|
||||
def test_append_dom_element_element(self):
|
||||
id_ = "element-append-tests"
|
||||
div = dom.find(f"#{id_}")[0]
|
||||
div = page.find(f"#{id_}")[0]
|
||||
len_children_before = len(div.children)
|
||||
new_el = el.p("new element")
|
||||
new_el = p("new element")
|
||||
div.append(new_el._dom_element)
|
||||
assert len(div.children) == len_children_before + 1
|
||||
assert div.children[-1] == new_el
|
||||
|
||||
def test_append_collection(self):
|
||||
id_ = "element-append-tests"
|
||||
div = dom.find(f"#{id_}")[0]
|
||||
div = page.find(f"#{id_}")[0]
|
||||
len_children_before = len(div.children)
|
||||
collection = dom.find(".collection")
|
||||
collection = page.find(".collection")
|
||||
div.append(collection)
|
||||
assert len(div.children) == len_children_before + len(collection)
|
||||
|
||||
@@ -122,16 +119,16 @@ class TestElement:
|
||||
def test_read_classes(self):
|
||||
id_ = "test_class_selector"
|
||||
expected_class = "a-test-class"
|
||||
div = dom.find(f"#{id_}")[0]
|
||||
div = page.find(f"#{id_}")[0]
|
||||
assert div.classes == [expected_class]
|
||||
|
||||
def test_add_remove_class(self):
|
||||
id_ = "div-no-classes"
|
||||
classname = "tester-class"
|
||||
div = dom.find(f"#{id_}")[0]
|
||||
div = page.find(f"#{id_}")[0]
|
||||
assert not div.classes
|
||||
div.classes.add(classname)
|
||||
same_div = dom.find(f"#{id_}")[0]
|
||||
same_div = page.find(f"#{id_}")[0]
|
||||
assert div.classes == [classname] == same_div.classes
|
||||
div.classes.remove(classname)
|
||||
assert div.classes == [] == same_div.classes
|
||||
@@ -139,7 +136,7 @@ class TestElement:
|
||||
def test_when_decorator(self):
|
||||
called = False
|
||||
|
||||
just_a_button = dom.find("#a-test-button")[0]
|
||||
just_a_button = page.find("#a-test-button")[0]
|
||||
|
||||
@when("click", just_a_button)
|
||||
def on_click(event):
|
||||
@@ -153,9 +150,9 @@ class TestElement:
|
||||
|
||||
assert called
|
||||
|
||||
def test_html_attribute(self):
|
||||
def test_inner_html_attribute(self):
|
||||
# GIVEN an existing element on the page with a known empty text content
|
||||
div = dom.find("#element_attribute_tests")[0]
|
||||
div = page.find("#element_attribute_tests")[0]
|
||||
|
||||
# WHEN we set the html attribute
|
||||
div.innerHTML = "<b>New Content</b>"
|
||||
@@ -163,14 +160,14 @@ class TestElement:
|
||||
# EXPECT the element html and underlying JS Element innerHTML property
|
||||
# to match what we expect and what
|
||||
assert div.innerHTML == div._dom_element.innerHTML == "<b>New Content</b>"
|
||||
assert div.text == div._dom_element.textContent == "New Content"
|
||||
assert div.textContent == div._dom_element.textContent == "New Content"
|
||||
|
||||
def test_text_attribute(self):
|
||||
# GIVEN an existing element on the page with a known empty text content
|
||||
div = dom.find("#element_attribute_tests")[0]
|
||||
div = page.find("#element_attribute_tests")[0]
|
||||
|
||||
# WHEN we set the html attribute
|
||||
div.text = "<b>New Content</b>"
|
||||
div.textContent = "<b>New Content</b>"
|
||||
|
||||
# EXPECT the element html and underlying JS Element innerHTML property
|
||||
# to match what we expect and what
|
||||
@@ -179,17 +176,17 @@ class TestElement:
|
||||
== div._dom_element.innerHTML
|
||||
== "<b>New Content</b>"
|
||||
)
|
||||
assert div.text == div._dom_element.textContent == "<b>New Content</b>"
|
||||
assert div.textContent == div._dom_element.textContent == "<b>New Content</b>"
|
||||
|
||||
|
||||
class TestCollection:
|
||||
def test_iter_eq_children(self):
|
||||
elements = dom.find(".multi-elems")
|
||||
assert [el for el in elements] == [el for el in elements.children]
|
||||
elements = page.find(".multi-elems")
|
||||
assert [el for el in elements] == [el for el in elements.elements]
|
||||
assert len(elements) == 3
|
||||
|
||||
def test_slices(self):
|
||||
elements = dom.find(".multi-elems")
|
||||
elements = page.find(".multi-elems")
|
||||
assert elements[0]
|
||||
_slice = elements[:2]
|
||||
assert len(_slice) == 2
|
||||
@@ -199,26 +196,26 @@ class TestCollection:
|
||||
|
||||
def test_style_rule(self):
|
||||
selector = ".multi-elems"
|
||||
elements = dom.find(selector)
|
||||
elements = page.find(selector)
|
||||
for el in elements:
|
||||
assert el.style["background-color"] != "red"
|
||||
|
||||
elements.style["background-color"] = "red"
|
||||
|
||||
for i, el in enumerate(dom.find(selector)):
|
||||
for i, el in enumerate(page.find(selector)):
|
||||
assert elements[i].style["background-color"] == "red"
|
||||
assert el.style["background-color"] == "red"
|
||||
|
||||
elements.style.remove("background-color")
|
||||
|
||||
for i, el in enumerate(dom.find(selector)):
|
||||
for i, el in enumerate(page.find(selector)):
|
||||
assert el.style["background-color"] != "red"
|
||||
assert elements[i].style["background-color"] != "red"
|
||||
|
||||
def test_when_decorator(self):
|
||||
called = False
|
||||
|
||||
buttons_collection = dom.find("button")
|
||||
buttons_collection = page.find("button")
|
||||
|
||||
@when("click", buttons_collection)
|
||||
def on_click(event):
|
||||
@@ -236,34 +233,33 @@ class TestCollection:
|
||||
|
||||
class TestCreation:
|
||||
def test_create_document_element(self):
|
||||
# TODO: This test should probably be removed since it's testing the elements module
|
||||
new_el = el.div("new element")
|
||||
# TODO: This test should probably be removed since it's testing the elements
|
||||
# module.
|
||||
new_el = div("new element")
|
||||
new_el.id = "new_el_id"
|
||||
assert isinstance(new_el, el.Element)
|
||||
assert isinstance(new_el, Element)
|
||||
assert new_el._dom_element.tagName == "DIV"
|
||||
# EXPECT the new element to be associated with the document
|
||||
assert new_el.parent == None
|
||||
dom.body.append(new_el)
|
||||
assert new_el.parent is None
|
||||
page.body.append(new_el)
|
||||
|
||||
assert dom.find("#new_el_id")[0].parent == dom.body
|
||||
assert page.find("#new_el_id")[0].parent == page.body
|
||||
|
||||
def test_create_element_child(self):
|
||||
selector = "#element-creation-test"
|
||||
parent_div = dom.find(selector)[0]
|
||||
parent_div = page.find(selector)[0]
|
||||
|
||||
# Creating an element from another element automatically creates that element
|
||||
# as a child of the original element
|
||||
new_el = el.p(
|
||||
"a div", classes=["code-description"], innerHTML="Ciao PyScripters!"
|
||||
)
|
||||
new_el = p("a div", classes=["code-description"], innerHTML="Ciao PyScripters!")
|
||||
parent_div.append(new_el)
|
||||
|
||||
assert isinstance(new_el, el.Element)
|
||||
assert isinstance(new_el, Element)
|
||||
assert new_el._dom_element.tagName == "P"
|
||||
|
||||
# EXPECT the new element to be associated with the document
|
||||
assert new_el.parent == parent_div
|
||||
assert dom.find(selector)[0].children[0] == new_el
|
||||
assert page.find(selector)[0].children[0] == new_el
|
||||
|
||||
|
||||
class TestInput:
|
||||
@@ -277,7 +273,7 @@ class TestInput:
|
||||
def test_value(self):
|
||||
for id_ in self.input_ids:
|
||||
expected_type = id_.split("_")[-1]
|
||||
result = dom.find(f"#{id_}")
|
||||
result = page.find(f"#{id_}")
|
||||
input_el = result[0]
|
||||
assert input_el._dom_element.type == expected_type
|
||||
assert input_el.value == f"Content {id_}" == input_el._dom_element.value
|
||||
@@ -295,7 +291,7 @@ class TestInput:
|
||||
|
||||
def test_set_value_collection(self):
|
||||
for id_ in self.input_ids:
|
||||
input_el = dom.find(f"#{id_}")
|
||||
input_el = page.find(f"#{id_}")
|
||||
|
||||
assert input_el.value[0] == f"Content {id_}" == input_el[0].value
|
||||
|
||||
@@ -308,30 +304,30 @@ class TestInput:
|
||||
# actually on the class. Maybe a job for __setattr__?
|
||||
#
|
||||
# def test_element_without_value(self):
|
||||
# result = dom.find(f"#tests-terminal"][0]
|
||||
# result = page.find(f"#tests-terminal"][0]
|
||||
# with pytest.raises(AttributeError):
|
||||
# result.value = "some value"
|
||||
#
|
||||
# def test_element_without_value_via_collection(self):
|
||||
# result = dom.find(f"#tests-terminal"]
|
||||
# result = page.find(f"#tests-terminal"]
|
||||
# with pytest.raises(AttributeError):
|
||||
# result.value = "some value"
|
||||
|
||||
|
||||
class TestSelect:
|
||||
def test_select_options_iter(self):
|
||||
select = dom.find(f"#test_select_element_w_options")[0]
|
||||
select = page.find(f"#test_select_element_w_options")[0]
|
||||
|
||||
for i, option in enumerate(select.options, 1):
|
||||
assert option.value == f"{i}"
|
||||
assert option.innerHTML == f"Option {i}"
|
||||
|
||||
def test_select_options_len(self):
|
||||
select = dom.find(f"#test_select_element_w_options")[0]
|
||||
select = page.find(f"#test_select_element_w_options")[0]
|
||||
assert len(select.options) == 2
|
||||
|
||||
def test_select_options_clear(self):
|
||||
select = dom.find(f"#test_select_element_to_clear")[0]
|
||||
select = page.find(f"#test_select_element_to_clear")[0]
|
||||
assert len(select.options) == 3
|
||||
|
||||
select.options.clear()
|
||||
@@ -340,7 +336,7 @@ class TestSelect:
|
||||
|
||||
def test_select_element_add(self):
|
||||
# GIVEN the existing select element with no options
|
||||
select = dom.find(f"#test_select_element")[0]
|
||||
select = page.find(f"#test_select_element")[0]
|
||||
|
||||
# EXPECT the select element to have no options
|
||||
assert len(select.options) == 0
|
||||
@@ -431,7 +427,7 @@ class TestSelect:
|
||||
|
||||
def test_select_options_remove(self):
|
||||
# GIVEN the existing select element with 3 options
|
||||
select = dom.find(f"#test_select_element_to_remove")[0]
|
||||
select = page.find(f"#test_select_element_to_remove")[0]
|
||||
|
||||
# EXPECT the select element to have 3 options
|
||||
assert len(select.options) == 4
|
||||
@@ -453,7 +449,7 @@ class TestSelect:
|
||||
|
||||
def test_select_get_selected_option(self):
|
||||
# GIVEN the existing select element with one selected option
|
||||
select = dom.find(f"#test_select_element_w_options")[0]
|
||||
select = page.find(f"#test_select_element_w_options")[0]
|
||||
|
||||
# WHEN we get the selected option
|
||||
selected_option = select.options.selected
|
||||
|
||||
16
pyscript.core/test/service-worker/index.html
Normal file
16
pyscript.core/test/service-worker/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Service Worker</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link rel="stylesheet" href="../../dist/core.css">
|
||||
<script type="module" src="../../dist/core.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="mpy" service-worker="./sabayon.js" worker>
|
||||
from pyscript import document
|
||||
document.body.append('OK')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
28
pyscript.core/test/service-worker/mini-coi.js
Normal file
28
pyscript.core/test/service-worker/mini-coi.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
|
||||
/*! mini-coi - Andrea Giammarchi and contributors, licensed under MIT */
|
||||
(({ document: d, navigator: { serviceWorker: s } }) => {
|
||||
if (d) {
|
||||
const { currentScript: c } = d;
|
||||
s.register(c.src, { scope: c.getAttribute('scope') || '.' }).then(r => {
|
||||
r.addEventListener('updatefound', () => location.reload());
|
||||
if (r.active && !s.controller) location.reload();
|
||||
});
|
||||
}
|
||||
else {
|
||||
addEventListener('install', () => skipWaiting());
|
||||
addEventListener('activate', e => e.waitUntil(clients.claim()));
|
||||
addEventListener('fetch', e => {
|
||||
const { request: r } = e;
|
||||
if (r.cache === 'only-if-cached' && r.mode !== 'same-origin') return;
|
||||
e.respondWith(fetch(r).then(r => {
|
||||
const { body, status, statusText } = r;
|
||||
if (!status || status > 399) return r;
|
||||
const h = new Headers(r.headers);
|
||||
h.set('Cross-Origin-Opener-Policy', 'same-origin');
|
||||
h.set('Cross-Origin-Embedder-Policy', 'require-corp');
|
||||
h.set('Cross-Origin-Resource-Policy', 'cross-origin');
|
||||
return new Response(body, { status, statusText, headers: h });
|
||||
}));
|
||||
});
|
||||
}
|
||||
})(self);
|
||||
1
pyscript.core/test/service-worker/sabayon.js
Normal file
1
pyscript.core/test/service-worker/sabayon.js
Normal file
@@ -0,0 +1 @@
|
||||
const{isArray:e}=Array,t=new Map,s=e=>{e.stopImmediatePropagation(),e.preventDefault()};var n=Object.freeze({__proto__:null,activate:e=>e.waitUntil(clients.claim()),fetch:e=>{const{request:n}=e;"POST"===n.method&&n.url===`${location.href}?sabayon`&&(s(e),e.respondWith(n.json().then((async e=>{const{promise:s,resolve:o}=Promise.withResolvers(),a=e.join(",");t.set(a,o);for(const t of await clients.matchAll())t.postMessage(e);return s.then((e=>new Response(`[${e.join(",")}]`,n.headers)))}))))},install:()=>skipWaiting(),message:n=>{const{data:o}=n;if(e(o)&&4===o.length){const[e,a,i,r]=o,l=[e,a,i].join(",");t.has(l)&&(s(n),t.get(l)(r),t.delete(l))}}});for(const e in n)addEventListener(e,n[e]);
|
||||
29
pyscript.core/test/workers/named.html
Normal file
29
pyscript.core/test/workers/named.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<title>named workers</title>
|
||||
<script type="module" src="../../dist/core.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="mpy" async>
|
||||
from pyscript import workers
|
||||
|
||||
await (await workers["mpy"]).greetings()
|
||||
await (await workers["py"]).greetings()
|
||||
</script>
|
||||
<script type="mpy" worker name="mpy">
|
||||
def greetings():
|
||||
print("micropython")
|
||||
|
||||
__export__ = ['greetings']
|
||||
</script>
|
||||
<script type="py" worker name="py">
|
||||
def greetings():
|
||||
print("pyodide")
|
||||
|
||||
__export__ = ['greetings']
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -97,7 +97,7 @@ class TestBasic(PyScriptTest):
|
||||
def test_input_exception(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<script type="py">
|
||||
<script type="py" async="false">
|
||||
input("what's your name?")
|
||||
</script>
|
||||
"""
|
||||
|
||||
@@ -43,12 +43,12 @@ class TestDisplay(PyScriptTest):
|
||||
def test_consecutive_display(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<script type="py">
|
||||
<script type="py" async="false">
|
||||
from pyscript import display
|
||||
display('hello 1')
|
||||
</script>
|
||||
<p>hello 2</p>
|
||||
<script type="py">
|
||||
<script type="py" async="false">
|
||||
from pyscript import display
|
||||
display('hello 3')
|
||||
</script>
|
||||
@@ -177,16 +177,16 @@ class TestDisplay(PyScriptTest):
|
||||
def test_consecutive_display_target(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<script type="py" id="first">
|
||||
<script type="py" id="first" async="false">
|
||||
from pyscript import display
|
||||
display('hello 1')
|
||||
</script>
|
||||
<p>hello in between 1 and 2</p>
|
||||
<script type="py" id="second">
|
||||
<script type="py" id="second" async="false">
|
||||
from pyscript import display
|
||||
display('hello 2', target="second")
|
||||
</script>
|
||||
<script type="py" id="third">
|
||||
<script type="py" id="third" async="false">
|
||||
from pyscript import display
|
||||
display('hello 3')
|
||||
</script>
|
||||
|
||||
@@ -101,11 +101,9 @@ class TestElements(PyScriptTest):
|
||||
code_ = f"""
|
||||
from pyscript import when
|
||||
<script type="{interpreter}">
|
||||
from pyscript.web import dom
|
||||
from pyscript.web.elements import {el_type}
|
||||
|
||||
from pyscript.web import page, {el_type}
|
||||
el = {el_type}({attributes})
|
||||
dom.body.append(el)
|
||||
page.body.append(el)
|
||||
</script>
|
||||
"""
|
||||
self.pyscript_run(code_)
|
||||
@@ -620,13 +618,12 @@ class TestElements(PyScriptTest):
|
||||
code_ = f"""
|
||||
from pyscript import when
|
||||
<script type="{interpreter}">
|
||||
from pyscript.web import dom
|
||||
from pyscript.web.elements import div, p
|
||||
from pyscript.web import page, div, p
|
||||
|
||||
el = div("{div_text_content}")
|
||||
child = p('{p_text_content}')
|
||||
el.append(child)
|
||||
dom.body.append(el)
|
||||
page.body.append(el)
|
||||
</script>
|
||||
"""
|
||||
self.pyscript_run(code_)
|
||||
@@ -664,14 +661,13 @@ class TestElements(PyScriptTest):
|
||||
from pyscript import when
|
||||
<script type="{interpreter}">
|
||||
from pyscript import document
|
||||
from pyscript.web import dom
|
||||
from pyscript.web.elements import div, p
|
||||
from pyscript.web import page, div, p
|
||||
|
||||
el = div("{div_text_content}")
|
||||
child = document.createElement('P')
|
||||
child.textContent = '{p_text_content}'
|
||||
el.append(child)
|
||||
dom.body.append(el)
|
||||
page.body.append(el)
|
||||
</script>
|
||||
"""
|
||||
self.pyscript_run(code_)
|
||||
@@ -709,15 +705,14 @@ class TestElements(PyScriptTest):
|
||||
code_ = f"""
|
||||
from pyscript import when
|
||||
<script type="{interpreter}">
|
||||
from pyscript.web import dom
|
||||
from pyscript.web.elements import div, p, ElementCollection
|
||||
from pyscript.web import page, div, p, ElementCollection
|
||||
|
||||
el = div("{div_text_content}")
|
||||
child1 = p('{p_text_content}')
|
||||
child2 = p('{p2_text_content}', id='child2')
|
||||
collection = ElementCollection([child1, child2])
|
||||
el.append(collection)
|
||||
dom.body.append(el)
|
||||
page.body.append(el)
|
||||
</script>
|
||||
"""
|
||||
self.pyscript_run(code_)
|
||||
@@ -765,20 +760,19 @@ class TestElements(PyScriptTest):
|
||||
from pyscript import when
|
||||
<script type="{interpreter}">
|
||||
from pyscript import document
|
||||
from pyscript.web import dom
|
||||
from pyscript.web.elements import div, p, ElementCollection
|
||||
from pyscript.web import page, div, p, ElementCollection
|
||||
|
||||
el = div("{div_text_content}")
|
||||
child1 = p('{p_text_content}')
|
||||
child2 = p('{p2_text_content}', id='child2')
|
||||
|
||||
dom.body.append(child1)
|
||||
dom.body.append(child2)
|
||||
page.body.append(child1)
|
||||
page.body.append(child2)
|
||||
|
||||
nodes = document.querySelectorAll('p')
|
||||
el.append(nodes)
|
||||
|
||||
dom.body.append(el)
|
||||
page.body.append(el)
|
||||
</script>
|
||||
"""
|
||||
self.pyscript_run(code_)
|
||||
|
||||
2
pyscript.core/types/core.d.ts
vendored
2
pyscript.core/types/core.d.ts
vendored
@@ -54,5 +54,5 @@ declare const exportedHooks: {
|
||||
};
|
||||
};
|
||||
declare const exportedConfig: {};
|
||||
declare const exportedWhenDefined: (type: string) => Promise<any>;
|
||||
declare const exportedWhenDefined: (type: string) => Promise<object>;
|
||||
export { stdlib, optional, inputFailure, TYPES, relative_url, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined };
|
||||
|
||||
5
pyscript.core/types/stdlib/pyscript.d.ts
vendored
5
pyscript.core/types/stdlib/pyscript.d.ts
vendored
@@ -9,10 +9,7 @@ declare namespace _default {
|
||||
"magic_js.py": string;
|
||||
"storage.py": string;
|
||||
"util.py": string;
|
||||
web: {
|
||||
"__init__.py": string;
|
||||
"elements.py": string;
|
||||
};
|
||||
"web.py": string;
|
||||
"websocket.py": string;
|
||||
"workers.py": string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user