Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
37345b5
Add test suite for opencv webcam
iliketocode2 Apr 6, 2026
e26a335
image now appears in new location
iliketocode2 Apr 6, 2026
3f336b9
add to main.py
iliketocode2 Apr 7, 2026
6346665
attempt at opencv integration again
iliketocode2 Apr 8, 2026
4a25d16
remove test
iliketocode2 Apr 8, 2026
5a736d2
main.py cleanup
iliketocode2 Apr 8, 2026
5b72646
isolate openCV python changes
iliketocode2 Apr 9, 2026
8d506cd
It finally works! OpenCV loading properly
iliketocode2 Apr 9, 2026
86c895a
Properly listening to codeeditor event to change opencv result
iliketocode2 Apr 9, 2026
9a251a8
simplify v1
iliketocode2 Apr 9, 2026
5df6b6d
more simplifications
iliketocode2 Apr 9, 2026
e2ea61b
Clean up comments
iliketocode2 Apr 9, 2026
9d3a32a
last changes before implementing donkey
iliketocode2 Apr 10, 2026
97b5094
Merge branch 'invent-framework:main' into webcam-opencv
iliketocode2 Apr 10, 2026
f787282
update gitignore to not commit temp files
iliketocode2 Apr 6, 2026
b8f684b
planning
iliketocode2 Apr 10, 2026
5362003
Huge reworking and pyscript wrapping to get donkey working
iliketocode2 Apr 13, 2026
e3a2b57
remove max-captures feature from webcam
iliketocode2 Apr 13, 2026
2a2ec88
It finally works!
iliketocode2 Apr 13, 2026
dfcd113
Lots of simplifications, add code editor
iliketocode2 Apr 13, 2026
0aa5442
fixed styling
iliketocode2 Apr 15, 2026
7540d5a
Code cleanup
iliketocode2 Apr 15, 2026
c5524d3
Remove extra spacing additions
iliketocode2 Apr 15, 2026
0b4fe2e
More comment cleanup
iliketocode2 Apr 15, 2026
1853529
fix import location in webcam.py
iliketocode2 Apr 22, 2026
44891cd
Diversifying the donkey plugin
iliketocode2 Apr 22, 2026
b7a9e2a
Approaching a plugin donkey, chart test
iliketocode2 Apr 22, 2026
2b1fc24
More modular donkey plugin, codeeditor test page
iliketocode2 Apr 22, 2026
9f41981
donkey plugin helper
iliketocode2 Apr 22, 2026
10cc2a4
make_plugin_runner simplification
iliketocode2 Apr 22, 2026
6001676
updated examples to post status to channels
iliketocode2 Apr 27, 2026
0e2f5cd
Integrate webcam donkey class
iliketocode2 Apr 30, 2026
b4424b9
Modularize the testing assertions/helpers
iliketocode2 Apr 30, 2026
d425275
cleanup comments
iliketocode2 Apr 30, 2026
6078778
Add assertion text to the webcam test page
iliketocode2 Apr 30, 2026
a6bd4ab
Refactor as per the discussed architecture
iliketocode2 May 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,8 @@ test_suite.tar.gz
invent.min.tar.gz
static/default.css
static/default.min.css
static/*.zip
static/*.zip

# All temp files
/temp
temp/
10 changes: 10 additions & 0 deletions examples/tests/chart/chart_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def run(chart_type, data, options, plugin_code):
namespace = {
"chart_type": chart_type,
"data": data,
"options": options,
}
exec(plugin_code, namespace, namespace)
if "result" not in namespace:
raise ValueError("Plugin code must assign to `result`.")
return namespace["result"]
6 changes: 6 additions & 0 deletions examples/tests/chart/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"files": {
"/static/invent.min.tar.gz": "./*",
"./chart_helper.py": ""
}
}
23 changes: 23 additions & 0 deletions examples/tests/chart/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Chart Donkey Interactive Test</title>

<!-- mini-coi must be first for donkey worker support. -->
<script src="/mini-coi.js"></script>

<link
rel="stylesheet"
href="https://pyscript.net/releases/2026.3.1/core.css"
>
<script
type="module"
src="https://pyscript.net/releases/2026.3.1/core.js"
></script>
</head>
<body>
<script type="mpy" src="./main.py" config="./config.json"></script>
</body>
</html>
159 changes: 159 additions & 0 deletions examples/tests/chart/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import invent
import sys
import os
from pathlib import Path
from invent.tools import make_helper
from invent.ui import *

from invent.tools.common_ui import (
back_link_widget,
fail_html,
make_status_setter,
pass_html,
publish_run,
wait_html,
)

await invent.setup()


chart = Chart(
chart_type="bar",
data={
"labels": ["A", "B", "C"],
"datasets": [
{
"label": "Values",
"data": [3, 5, 2],
"backgroundColor": "rgba(54, 162, 235, 0.5)",
}
],
},
options={"plugins": {"legend": {"display": True}}},
)

status_label = Label(text="Donkey starting...")
_set_chart_status = make_status_setter(invent, status_label, channel="chart")

default_code = (
"# Inputs: chart_type, data, options\n"
"# Assign a dict to result with optional data/options keys.\n"
"new_data = dict(data)\n"
"datasets = [dict(ds) for ds in data.get('datasets', [])]\n"
"if datasets:\n"
" first = dict(datasets[0])\n"
" values = list(first.get('data', []))\n"
" first['data'] = [value * 2 for value in values]\n"
" first['label'] = 'Values x2'\n"
" datasets[0] = first\n"
"new_data['datasets'] = datasets\n"
"result = {'data': new_data}\n"
)

code_editor = CodeEditor(
code=default_code,
language="python",
min_height="260px",
)

assert_worker = Html(html=wait_html("Worker not started."))
assert_run = Html(html=wait_html("Code not run."))

HELPER_CHANNEL = "chart-helper"

make_helper(src="chart_helper.py", channel=HELPER_CHANNEL)


def handle_helper_status(msg):
state = getattr(msg, "state", None)
detail = getattr(msg, "detail", None)
if state == "starting":
_set_chart_status("Starting donkey worker...")
elif state == "ready":
_set_chart_status("Donkey ready. Press Run Code.")
assert_worker.html = pass_html("Donkey worker ready.")
elif state == "busy":
_set_chart_status("Running code...")
elif state == "error":
_set_chart_status(f"Failed to start donkey: {detail}")
assert_worker.html = fail_html(f"Donkey worker failed: {detail}")


def handle_helper_result(msg):
if msg.function != "run":
return
if msg.error:
_set_chart_status(f"Worker error: {msg.error}")
assert_run.html = fail_html(f"Code run failed: {msg.error}")
return
payload = msg.result
if not isinstance(payload, dict):
assert_run.html = fail_html("Result must be a dict.")
_set_chart_status("Invalid chart result.")
return
if "data" in payload:
chart.data = payload["data"]
if "options" in payload:
chart.options = payload["options"]
assert_run.html = pass_html("Code run succeeded.")
_set_chart_status("Done. Chart updated from donkey result.")


invent.subscribe(handle_helper_status, HELPER_CHANNEL, "status")
invent.subscribe(handle_helper_result, HELPER_CHANNEL, "result")


async def handle_controls(message):
if getattr(message.source, "name", "") != "run_chart_code":
return
publish_run(
invent,
channel=HELPER_CHANNEL,
function="run",
args=[
chart.chart_type,
chart.data,
chart.options,
code_editor.code or "",
],
)


invent.subscribe(
handle_controls,
to_channel="chart-controls",
when_subject=["press"],
)

app = invent.App(
name="Chart Donkey Interactive Test",
pages=[
Page(
id="chart-donkey-test",
children=[
back_link_widget(),
Label(text="# Chart Donkey Interactive Test"),
Label(
text=(
"Run Python code in a donkey worker to transform "
"chart data and apply the result back to the "
"widget."
)
),
chart,
Button(
text="Run Code",
name="run_chart_code",
channel="chart-controls",
),
code_editor,
status_label,
Label(text="## Assertions"),
assert_worker,
assert_run,
],
),
],
)

invent.go()
6 changes: 6 additions & 0 deletions examples/tests/codeeditor/codeeditor_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def run(editor_code, plugin_code):
namespace = {"editor_code": editor_code}
exec(plugin_code, namespace, namespace)
if "result" not in namespace:
raise ValueError("Plugin code must assign to `result`.")
return namespace["result"]
6 changes: 6 additions & 0 deletions examples/tests/codeeditor/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"files": {
"/static/invent.min.tar.gz": "./*",
"./codeeditor_helper.py": ""
}
}
23 changes: 23 additions & 0 deletions examples/tests/codeeditor/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CodeEditor Donkey Interactive Test</title>

<!-- mini-coi must be first for donkey worker support. -->
<script src="/mini-coi.js"></script>

<link
rel="stylesheet"
href="https://pyscript.net/releases/2026.3.1/core.css"
>
<script
type="module"
src="https://pyscript.net/releases/2026.3.1/core.js"
></script>
</head>
<body>
<script type="mpy" src="./main.py" config="./config.json"></script>
</body>
</html>
Loading