Skip to content

Commit efa51b7

Browse files
Merge pull request #29 from webui-dev/send_raw_fix
send_raw function fix
2 parents a96d130 + 62afb76 commit efa51b7

File tree

7 files changed

+113
-23
lines changed

7 files changed

+113
-23
lines changed

PyPI/Package/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Python WebUI v2.5.1
1+
# Python WebUI v2.5.2
22

33
> Use any web browser as GUI, with Python in the backend and HTML5 in the frontend, all in a lightweight Python package.
44

PyPI/Package/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "webui2"
7-
version = "2.5.1"
7+
version = "2.5.2"
88
authors = [
99
{ name="Hassan Draga" },
1010
]

PyPI/Package/src/webui/webui.py

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Python WebUI v2.5.1
1+
# Python WebUI v2.5.2
22
#
33
# http://webui.me
44
# https://github.com/webui-dev/python-webui
@@ -11,6 +11,7 @@
1111
# webui.py
1212
from __future__ import annotations
1313

14+
import array
1415
import warnings
1516
from typing import Any, Callable, Optional, TypeAlias
1617
from ctypes import *
@@ -209,29 +210,45 @@ def close_client(self) -> None:
209210
_raw.webui_close_client(byref(self._c_event()))
210211

211212
# -- send_raw_client ----------------------------
212-
def send_raw_client(self, function: str, raw: Optional[int], size: int) -> None:
213+
def send_raw_client(self, function: str, data: Union[bytes, bytearray, memoryview, array.array]) -> None:
213214
"""Safely send raw data to the UI for a single client.
214215
215216
This function sends raw data to a JavaScript function in the UI. The JavaScript function must
216217
be defined to accept the raw data, such as: `function myFunc(myData) {}`.
217218
218219
Args:
219-
function (str): The name of the JavaScript function to receive the raw data, encoded in UTF-8.
220-
raw (Optional[int]): The pointer to the raw data buffer. Must not be `None`.
221-
size (int): The size of the raw data buffer in bytes.
220+
function (str): The name of the JavaScript function to receive the raw data.
221+
data (Union[bytes, bytearray, memoryview, array.array]): The raw data buffer.
222222
223223
Raises:
224-
ValueError: If `raw` is `None`.
224+
ValueError: If `data` is `None` or empty.
225225
226226
Example:
227-
e.send_raw_client("myJavaScriptFunc", my_buffer, 64)
227+
e.send_raw_client("myJavaScriptFunc", bytearray([0x01, 0x0A, 0xFF]))
228+
# Sends 3 bytes of raw data to the JavaScript function `myJavaScriptFunc`.
228229
"""
229-
if raw is None:
230-
raise ValueError("Invalid Pointer: Cannot send a null pointer.")
230+
if data is None or len(data) == 0:
231+
raise ValueError("Data must not be None or empty.")
232+
233+
# Ensure data is a memoryview for uniformity
234+
if not isinstance(data, memoryview):
235+
data = memoryview(data)
236+
237+
# Ensure that data is a writable copy to obtain void pointer,
238+
# from_buffer will throw error if the buffer passed in is not writable.
239+
if data.readonly:
240+
data = memoryview(bytearray(data))
241+
242+
# Obtain a c_void_p pointer to the data buffer
243+
ptr = c_void_p(addressof(c_char.from_buffer(data)))
244+
245+
# Determine the size of the data
246+
size = len(data)
247+
231248
_raw.webui_send_raw_client(
232249
byref(self._c_event()),
233250
c_char_p(function.encode("utf-8")),
234-
c_void_p(raw),
251+
ptr,
235252
c_size_t(size)
236253
)
237254

@@ -1024,33 +1041,50 @@ def set_icon(self, icon: str, icon_type: str) -> None:
10241041
_raw.webui_set_icon(c_size_t(self._window), icon.encode("utf-8"), icon_type.encode("utf-8"))
10251042

10261043
# -- send_raw -----------------------------------
1027-
def send_raw(self, function: str, raw: Optional[c_void_p], size: int) -> None:
1028-
"""Safely send raw data to the UI for all clients.
1044+
def send_raw(self, function: str, data: Union[bytes, bytearray, memoryview, array.array]) -> None:
1045+
"""
1046+
Safely send raw data to the UI for all clients.
10291047
10301048
This function sends a raw data buffer to a JavaScript function in the UI.
10311049
The JavaScript function should be capable of handling raw binary data.
10321050
10331051
Args:
10341052
function (str): The JavaScript function that will receive the raw data.
1035-
raw (Optional[c_void_p]): A pointer to the raw data buffer. Must not be `None`.
1036-
size (int): The size of the raw data in bytes.
1053+
data (Union[bytes, bytearray, memoryview, array.array]): The raw data buffer.
10371054
10381055
Raises:
1039-
ValueError: If `raw` is `None`.
1056+
ValueError: If `data` is `None` or empty.
10401057
10411058
Returns:
10421059
None
10431060
10441061
Example:
1045-
my_window.send_raw("myJavaScriptFunc", my_buffer, 64)
1046-
# Sends 64 bytes of raw data to the JavaScript function `myJavaScriptFunc`.
1062+
my_window.send_raw("myJavaScriptFunc", bytearray([0x01, 0x0A, 0xFF]))
1063+
# Sends 3 bytes of raw data to the JavaScript function `myJavaScriptFunc`.
10471064
"""
1048-
if raw is None:
1049-
raise ValueError("Invalid pointer: Cannot send a null pointer.")
1065+
if data is None or len(data) == 0:
1066+
raise ValueError("Data must not be None or empty.")
1067+
1068+
# Ensure data is a memoryview for uniformity
1069+
if not isinstance(data, memoryview):
1070+
data = memoryview(data)
1071+
1072+
# Ensure that data is a writable copy to obtain void pointer,
1073+
# from_buffer will throw error if the buffer passed in is not writable.
1074+
if data.readonly:
1075+
data = memoryview(bytearray(data))
1076+
1077+
# Obtain a c_void_p pointer to the data buffer
1078+
ptr = c_void_p(addressof(c_char.from_buffer(data)))
1079+
1080+
# Determine the size of the data
1081+
size = len(data)
1082+
1083+
# Call the underlying function to send the data
10501084
_raw.webui_send_raw(
10511085
c_size_t(self._window),
10521086
c_char_p(function.encode("utf-8")),
1053-
c_void_p(raw), # type: ignore
1087+
ptr,
10541088
c_size_t(size)
10551089
)
10561090

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![Logo](https://raw.githubusercontent.com/webui-dev/webui-logo/main/webui_python.png)
44

5-
# Python-WebUI v2.5.1
5+
# Python-WebUI v2.5.2
66

77
[last-commit]: https://img.shields.io/github/last-commit/webui-dev/webui?style=for-the-badge&logo=github&logoColor=C0CAF5&labelColor=414868
88
[release-version]: https://img.shields.io/github/v/tag/webui-dev/webui?style=for-the-badge&logo=webtrees&logoColor=C0CAF5&labelColor=414868&color=7664C6

examples/sending-raw/index.html

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Title</title>
6+
</head>
7+
<body>
8+
<h1>Hello there!</h1>
9+
10+
<script src="/webui.js"></script>
11+
<script type="application/javascript">
12+
function myJavaScriptFunc(rawData) {
13+
// `rawData` should be a Uint8Array variable
14+
console.log("rawData: ", rawData)
15+
16+
// Create a Blob from the raw data, specifying the MIME type as 'image/png'
17+
const blob = new Blob([rawData], { type: 'image/png' });
18+
19+
// Generate a URL for the Blob
20+
const imageUrl = URL.createObjectURL(blob);
21+
22+
// Create an <img> element and set its src attribute to the Blob URL
23+
const img = document.createElement('img');
24+
img.src = imageUrl;
25+
26+
// Add the img element to the body of the html
27+
document.body.appendChild(img);
28+
console.log("Image has been added to the page.");
29+
}
30+
</script>
31+
</body>
32+
</html>

examples/sending-raw/main.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from webui import webui
2+
3+
def main():
4+
# Create an instance of a Window object
5+
my_window = webui.Window()
6+
7+
# Open an image file and read it in as byte data.
8+
with open("./webui_python.png", 'rb') as file:
9+
raw_bytes: bytes = file.read()
10+
11+
# Open the window using the html file in the project while getting the appropriate browser for the user.
12+
my_window.show_browser("index.html", my_window.get_best_browser())
13+
14+
#print(raw_bytes)
15+
# Send over the byte data from the picture to the javascript function we have in the html.
16+
my_window.send_raw("myJavaScriptFunc", raw_bytes)
17+
18+
# waits for all windows to close before terminating the program.
19+
webui.wait()
20+
21+
if __name__ == "__main__":
22+
main()
23+
24+
6.57 KB
Loading

0 commit comments

Comments
 (0)