mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-20 02:37:41 -05:00
Compare commits
5 Commits
fpliger/ex
...
fix-404-ge
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39725c1384 | ||
|
|
48c5158b46 | ||
|
|
4b89c84692 | ||
|
|
df68449b82 | ||
|
|
48e3383f66 |
36
README.md
36
README.md
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
|
|
||||||
PyScript is a framework that allows users to create rich Python applications in the browser using HTML's interface and the power of [Pyodide](https://pyodide.org/en/stable/), [WASM](https://webassembly.org/), and modern web technologies.
|
PyScript is a framework that allows users to create rich Python applications in the browser using HTML's interface and the power of [Pyodide](https://pyodide.org/en/stable/), [MicroPython](https://micropython.org/) and [WASM](https://webassembly.org/), and modern web technologies.
|
||||||
|
|
||||||
To get started see the [getting started tutorial](docs/tutorials/getting-started.md).
|
To get started see the [getting started tutorial](https://pyscript.github.io/docs/latest/beginning-pyscript/).
|
||||||
|
|
||||||
For examples see [here](examples).
|
For examples see [here](examples).
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ PyScript is a meta project that aims to combine multiple open technologies into
|
|||||||
|
|
||||||
## Try PyScript
|
## Try PyScript
|
||||||
|
|
||||||
To try PyScript, import the appropriate pyscript files into the `<head>` tag of your html page with:
|
To try PyScript, import the appropriate pyscript files into the `<head>` tag of your html page:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<head>
|
<head>
|
||||||
@@ -29,14 +29,25 @@ To try PyScript, import the appropriate pyscript files into the `<head>` tag of
|
|||||||
src="https://pyscript.net/releases/2023.11.1/core.js"
|
src="https://pyscript.net/releases/2023.11.1/core.js"
|
||||||
></script>
|
></script>
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="py" terminal>
|
||||||
|
from pyscript import display
|
||||||
|
display("Hello World!") # this goes to the DOM
|
||||||
|
print("Hello terminal") # this goes to the terminal
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
```
|
```
|
||||||
|
|
||||||
You can then use PyScript components in your html page. PyScript currently implements the following elements:
|
You can then use PyScript components in your html page. PyScript currently offers various ways of running Python code:
|
||||||
|
|
||||||
- `<py-script>`: can be used to define python code that is executable within the web page. The element itself is not rendered to the page and is only used to add logic
|
- `<script type="py">`: can be used to define python code that is executable within the web page.
|
||||||
- `<py-repl>`: creates a REPL component that is rendered to the page as a code editor and allows users to write executable code
|
- `<script type="py" src="hello.py">`: same as above, but the python source is fetched from the given URL.
|
||||||
|
- `<script type="py" terminal>`: same as above, but also creates a terminal where to display stdout and stderr (e.g., the output of `print()`); `input()` does not work.
|
||||||
|
- `<script type="py" terminal worker>`: run Python inside a web worker: the terminal if fully functional and `input()` works.
|
||||||
|
- `<py-script>`: same as `<script type="py">`, but it is not recommended because if the code contains HTML tags, they could be parsed wrongly.
|
||||||
|
- `<script type="mpy">`: same as above but use MicroPython instead of Python.
|
||||||
|
|
||||||
Check out the [the examples directory](examples) folder for more examples on how to use it, all you need to do is open them in Chrome.
|
Check out the [official docs](https://docs.pyscript.net) for more detailed documentation.
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
@@ -44,6 +55,17 @@ Read the [contributing guide](CONTRIBUTING.md) to learn about our development pr
|
|||||||
|
|
||||||
Check out the [developing process](https://docs.pyscript.net/latest/contributing) documentation for more information on how to setup your development environment.
|
Check out the [developing process](https://docs.pyscript.net/latest/contributing) documentation for more information on how to setup your development environment.
|
||||||
|
|
||||||
|
## Community calls and events
|
||||||
|
|
||||||
|
Every Tuesday at 15:30 UTC there is the _PyScript Community Call_ on zoom, where we can talk about PyScript development in the open. Most of the maintainers regularly participate in the call, and everybody is welcome to join.
|
||||||
|
|
||||||
|
Every other Thursday at 16:00 UTC there is the _PyScript FUN_ call: this is a call in which everybody is encouraged to show what they did with PyScript.
|
||||||
|
|
||||||
|
For more details on how to join the calls and up to date schedule, consult the official calendar:
|
||||||
|
|
||||||
|
- [Google calendar](https://calendar.google.com/calendar/u/0/embed?src=d3afdd81f9c132a8c8f3290f5cc5966adebdf61017fca784eef0f6be9fd519e0@group.calendar.google.com&ctz=UTC) in UTC time;
|
||||||
|
- [iCal format](https://calendar.google.com/calendar/ical/d3afdd81f9c132a8c8f3290f5cc5966adebdf61017fca784eef0f6be9fd519e0%40group.calendar.google.com/public/basic.ics).
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- [Official docs](https://docs.pyscript.net)
|
- [Official docs](https://docs.pyscript.net)
|
||||||
|
|||||||
@@ -45,6 +45,19 @@ export const createFunction = (self, name) => {
|
|||||||
const SetFunction = typedSet({ typeof: "function" });
|
const SetFunction = typedSet({ typeof: "function" });
|
||||||
const SetString = typedSet({ typeof: "string" });
|
const SetString = typedSet({ typeof: "string" });
|
||||||
|
|
||||||
|
const inputFailure = `
|
||||||
|
import builtins
|
||||||
|
def input(prompt=""):
|
||||||
|
raise Exception("\\n ".join([
|
||||||
|
"input() doesn't work when PyScript runs in the main thread.",
|
||||||
|
"Consider using the worker attribute: https://docs.pyscript.net/2023.11.1/user-guide/workers/"
|
||||||
|
]))
|
||||||
|
|
||||||
|
builtins.input = input
|
||||||
|
del builtins
|
||||||
|
del input
|
||||||
|
`;
|
||||||
|
|
||||||
export const hooks = {
|
export const hooks = {
|
||||||
main: {
|
main: {
|
||||||
/** @type {Set<function>} */
|
/** @type {Set<function>} */
|
||||||
@@ -60,7 +73,7 @@ export const hooks = {
|
|||||||
/** @type {Set<function>} */
|
/** @type {Set<function>} */
|
||||||
onAfterRunAsync: new SetFunction(),
|
onAfterRunAsync: new SetFunction(),
|
||||||
/** @type {Set<string>} */
|
/** @type {Set<string>} */
|
||||||
codeBeforeRun: new SetString(),
|
codeBeforeRun: new SetString([inputFailure]),
|
||||||
/** @type {Set<string>} */
|
/** @type {Set<string>} */
|
||||||
codeBeforeRunAsync: new SetString(),
|
codeBeforeRunAsync: new SetString(),
|
||||||
/** @type {Set<string>} */
|
/** @type {Set<string>} */
|
||||||
|
|||||||
21
pyscript.core/test/input.html
Normal file
21
pyscript.core/test/input.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>PyScript Next</title>
|
||||||
|
<script>
|
||||||
|
addEventListener("py:ready", console.log);
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" href="../dist/core.css">
|
||||||
|
<script type="module" src="../dist/core.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<py-script>
|
||||||
|
input("what's your name?")
|
||||||
|
</py-script>
|
||||||
|
<mpy-script>
|
||||||
|
input("what's your name?")
|
||||||
|
</mpy-script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
import js
|
|
||||||
import panel as pn
|
|
||||||
from js import JSON
|
|
||||||
from panel.io.pyodide import init_doc, write_doc
|
|
||||||
from polyscript import xworker
|
|
||||||
from pyodide.ffi import create_once_callable, create_proxy, to_js
|
|
||||||
from pyscript import document, window
|
|
||||||
|
|
||||||
js.document = document
|
|
||||||
init_doc()
|
|
||||||
|
|
||||||
print("Hello from panel.py")
|
|
||||||
|
|
||||||
slider = pn.widgets.FloatSlider(start=0, end=10, name="Amplitude")
|
|
||||||
|
|
||||||
|
|
||||||
def callback(new):
|
|
||||||
print(f"Amplitude is: {new}")
|
|
||||||
return f"Amplitude is: {new}"
|
|
||||||
|
|
||||||
|
|
||||||
print("made this far...")
|
|
||||||
pn.Row(slider, pn.bind(callback, slider)).servable(target="simple_app")
|
|
||||||
|
|
||||||
# ------ END OF PANEL CODE ------
|
|
||||||
|
|
||||||
docs_json_str, render_items_str, root_ids_str = await write_doc()
|
|
||||||
docs_json = JSON.parse(docs_json_str) # .as_object_map()
|
|
||||||
# render_items = to_js(JSON.parse(render_items_str), depth=-1, pyproxies=None, create_pyproxies=False, dict_converter=js.Object.fromEntries)#.as_object_map()
|
|
||||||
root_ids = JSON.parse(root_ids_str) # .as_object_map()
|
|
||||||
|
|
||||||
# docs_json = json.loads(docs_json_str)
|
|
||||||
render_items = json.loads(render_items_str)
|
|
||||||
# root_ids = json.loads(root_ids_str)
|
|
||||||
|
|
||||||
print(type(render_items))
|
|
||||||
root_elements = document.querySelectorAll("[data-root-id]")
|
|
||||||
data_roots = []
|
|
||||||
for el in root_elements:
|
|
||||||
el.innerHTML = ""
|
|
||||||
data_roots.append([el.getAttribute("data-root-id"), el.id])
|
|
||||||
|
|
||||||
roots = {root_ids[i]: root for i, root in enumerate(data_roots)}
|
|
||||||
|
|
||||||
print("Quick check")
|
|
||||||
print(roots)
|
|
||||||
print(root_ids)
|
|
||||||
print(render_items)
|
|
||||||
# render_items[0]['roots'] = roots
|
|
||||||
# render_items[0]['root_ids'] = root_ids
|
|
||||||
# render_items[0].roots = to_js(roots)
|
|
||||||
# render_items[0].root_ids = to_js(root_ids)
|
|
||||||
|
|
||||||
|
|
||||||
# print(roots)
|
|
||||||
# print(data_roots)
|
|
||||||
print(docs_json)
|
|
||||||
print(render_items)
|
|
||||||
print("here....")
|
|
||||||
|
|
||||||
# views = await window.Bokeh.embed.embed_items(to_js(docs_json), to_js(render_items))
|
|
||||||
views = await window.Bokeh.embed.embed_items(
|
|
||||||
docs_json, # to_js(docs_json, depth=-1, pyproxies=None, create_pyproxies=False, dict_converter=js.Object.fromEntries),
|
|
||||||
to_js(
|
|
||||||
render_items,
|
|
||||||
depth=-1,
|
|
||||||
pyproxies=None,
|
|
||||||
create_pyproxies=False,
|
|
||||||
dict_converter=js.Object.fromEntries,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Experiments back to main thread
|
|
||||||
# await xworker.sync.render_full(docs_json_str, render_items_str, root_ids_str)
|
|
||||||
print("made it to the end")
|
|
||||||
print(docs_json)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
packages = [
|
|
||||||
"https://cdn.holoviz.org/panel/0.14.3/dist/wheels/bokeh-2.4.3-py3-none-any.whl",
|
|
||||||
"numpy",
|
|
||||||
"panel==0.14.1"
|
|
||||||
]
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Panel Example</title>
|
|
||||||
<meta charset="iso-8859-1" />
|
|
||||||
<link rel="icon" type="image/x-icon" href="./favicon.png" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<section class="pyscript">
|
|
||||||
<div id="simple_app"></div>
|
|
||||||
|
|
||||||
<py-tutor>
|
|
||||||
<script defer src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"></script>
|
|
||||||
<script defer src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
|
|
||||||
<script defer src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"></script>
|
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.14.1/dist/panel.min.js"></script>
|
|
||||||
|
|
||||||
<script type="module" src="../../core.js"></script>
|
|
||||||
<!-- <script
|
|
||||||
type="module"
|
|
||||||
src="https://esm.sh/@pyscript/core@latest/core.js"
|
|
||||||
></script> -->
|
|
||||||
|
|
||||||
<script type="py" worker="./panel.py" config="./panel.toml" async></script>
|
|
||||||
|
|
||||||
<!-- Code below borrowed for reference from example working on polyscript directly -->
|
|
||||||
<!-- <script type="micropython">
|
|
||||||
from pyscript import PyWorker
|
|
||||||
import json
|
|
||||||
import js
|
|
||||||
|
|
||||||
w = PyWorker('./panel.py', **{'type': 'pyodide', 'async': True, 'config': './panel.toml'})
|
|
||||||
|
|
||||||
# xworker.window made the following completely unnecessary
|
|
||||||
document = js.document
|
|
||||||
|
|
||||||
async def render_full(docs_json_str, render_items_str, root_ids_str):
|
|
||||||
docs_json = json.loads(docs_json_str)
|
|
||||||
render_items = json.loads(render_items_str)
|
|
||||||
root_ids = json.loads(root_ids_str)
|
|
||||||
|
|
||||||
print(type(render_items))
|
|
||||||
root_elements = document.querySelectorAll('[data-root-id]')
|
|
||||||
data_roots = []
|
|
||||||
for el in root_elements:
|
|
||||||
el.innerHTML = ''
|
|
||||||
data_roots.append([el.getAttribute('data-root-id'), el.id])
|
|
||||||
|
|
||||||
roots = {root_ids[i]: root for i, root in enumerate(data_roots)}
|
|
||||||
|
|
||||||
print("Quick check")
|
|
||||||
render_items[0]['roots'] = roots
|
|
||||||
render_items[0]['root_ids'] = root_ids
|
|
||||||
print("here....")
|
|
||||||
views = await js.Bokeh.embed.embed_items(docs_json, render_items)
|
|
||||||
|
|
||||||
|
|
||||||
def render(docs_json, render_items):
|
|
||||||
print(f"GOT DATA: {docs_json}")
|
|
||||||
print(f"GOT ITEMS: {render_items}")
|
|
||||||
|
|
||||||
await js.Bokeh.embed.embed_items(json.loads(docs_json), json.loads(render_items))
|
|
||||||
# views = await xworker.window.Bokeh.embed.embed_items(create_proxy(docs_json), create_proxy(render_items))
|
|
||||||
|
|
||||||
w.sync.render = render
|
|
||||||
w.sync.render_full = render_full
|
|
||||||
|
|
||||||
</script> -->
|
|
||||||
</py-tutor>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -93,6 +93,19 @@ class TestBasic(PyScriptTest):
|
|||||||
)
|
)
|
||||||
assert self.console.log.lines[-1] == "hello pyscript"
|
assert self.console.log.lines[-1] == "hello pyscript"
|
||||||
|
|
||||||
|
@only_main
|
||||||
|
def test_input_exception(self):
|
||||||
|
self.pyscript_run(
|
||||||
|
"""
|
||||||
|
<script type="py">
|
||||||
|
input("what's your name?")
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
self.check_py_errors(
|
||||||
|
"Exception: input() doesn't work when PyScript runs in the main thread."
|
||||||
|
)
|
||||||
|
|
||||||
@skip_worker("NEXT: exceptions should be displayed in the DOM")
|
@skip_worker("NEXT: exceptions should be displayed in the DOM")
|
||||||
def test_python_exception(self):
|
def test_python_exception(self):
|
||||||
self.pyscript_run(
|
self.pyscript_run(
|
||||||
|
|||||||
Reference in New Issue
Block a user