Skip to content

Commit fa368e6

Browse files
committed
Merge remote-tracking branch 'origin/main' into refactor-tests
2 parents d2348c7 + 22ef062 commit fa368e6

File tree

4 files changed

+29
-60
lines changed

4 files changed

+29
-60
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 0.0.8 - 2025-08-20
4+
5+
- feat: add `download()` and `download_file()` methods (#5)
6+
7+
## 0.0.7 - 2025-08-20
8+
9+
- feat: add `read_framebuffer_png_bytes()` and `save_framebuffer_png()` methods (#4)
10+
311
## 0.0.6 - 2025-08-17
412

513
- feat: add `set_control()`, `read_pin()`, `listen_pin()`, `serial_write()` methods (#1)

src/wokwi_client/client.py

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22
#
33
# SPDX-License-Identifier: MIT
44

5+
import base64
56
from pathlib import Path
67
from typing import Any, Optional, Union
78

89
from wokwi_client.framebuffer import (
9-
compare_framebuffer_png,
10-
framebuffer_png_bytes,
11-
framebuffer_read,
10+
read_framebuffer_png_bytes,
1211
save_framebuffer_png,
1312
)
1413

1514
from .__version__ import get_version
1615
from .constants import DEFAULT_WS_URL
1716
from .control import set_control
1817
from .event_queue import EventQueue
19-
from .file_ops import download, download_file, upload, upload_file
18+
from .file_ops import download, upload, upload_file
2019
from .pins import gpio_list, pin_listen, pin_read
2120
from .protocol_types import EventMessage, ResponseMessage
2221
from .serial import monitor_lines, write_serial
@@ -93,17 +92,18 @@ async def upload_file(
9392
"""
9493
return await upload_file(self._transport, filename, local_path)
9594

96-
async def download(self, name: str) -> ResponseMessage:
95+
async def download(self, name: str) -> bytes:
9796
"""
9897
Download a file from the simulator.
9998
10099
Args:
101100
name: The name of the file to download.
102101
103102
Returns:
104-
The response message from the server.
103+
The downloaded file content as bytes.
105104
"""
106-
return await download(self._transport, name)
105+
result = await download(self._transport, name)
106+
return base64.b64decode(result["result"]["binary"])
107107

108108
async def download_file(self, name: str, local_path: Optional[Path] = None) -> None:
109109
"""
@@ -113,7 +113,12 @@ async def download_file(self, name: str, local_path: Optional[Path] = None) -> N
113113
name: The name of the file to download.
114114
local_path: The local path to save the downloaded file. If not provided, uses the name as the path.
115115
"""
116-
await download_file(self._transport, name, local_path)
116+
if local_path is None:
117+
local_path = Path(name)
118+
119+
result = await self.download(name)
120+
with open(local_path, "wb") as f:
121+
f.write(result)
117122

118123
async def start_simulation(
119124
self,
@@ -267,22 +272,10 @@ async def set_control(
267272
"""
268273
return await set_control(self._transport, part=part, control=control, value=value)
269274

270-
async def framebuffer_read(self, id: str) -> ResponseMessage:
271-
"""Read the current framebuffer for the given device id."""
272-
return await framebuffer_read(self._transport, id=id)
273-
274-
async def framebuffer_png_bytes(self, id: str) -> bytes:
275+
async def read_framebuffer_png_bytes(self, id: str) -> bytes:
275276
"""Return the current framebuffer as PNG bytes."""
276-
return await framebuffer_png_bytes(self._transport, id=id)
277+
return await read_framebuffer_png_bytes(self._transport, id=id)
277278

278279
async def save_framebuffer_png(self, id: str, path: Path, overwrite: bool = True) -> Path:
279280
"""Save the current framebuffer as a PNG file."""
280281
return await save_framebuffer_png(self._transport, id=id, path=path, overwrite=overwrite)
281-
282-
async def compare_framebuffer_png(
283-
self, id: str, reference: Path, save_mismatch: Optional[Path] = None
284-
) -> bool:
285-
"""Compare the current framebuffer with a reference PNG file."""
286-
return await compare_framebuffer_png(
287-
self._transport, id=id, reference=reference, save_mismatch=save_mismatch
288-
)

src/wokwi_client/file_ops.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,3 @@ async def upload(transport: Transport, name: str, content: bytes) -> ResponseMes
2626

2727
async def download(transport: Transport, name: str) -> ResponseMessage:
2828
return await transport.request("file:download", {"name": name})
29-
30-
31-
async def download_file(transport: Transport, name: str, local_path: Optional[Path] = None) -> None:
32-
if local_path is None:
33-
local_path = Path(name)
34-
35-
result = await download(transport, name)
36-
with open(local_path, "wb") as f:
37-
f.write(base64.b64decode(result["result"]["binary"]))

src/wokwi_client/framebuffer.py

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,13 @@
2424
from .transport import Transport
2525

2626
__all__ = [
27-
"framebuffer_read",
28-
"framebuffer_png_bytes",
27+
"read_framebuffer",
28+
"read_framebuffer_png_bytes",
2929
"save_framebuffer_png",
30-
"compare_framebuffer_png",
3130
]
3231

3332

34-
async def framebuffer_read(transport: Transport, *, id: str) -> ResponseMessage:
33+
async def read_framebuffer(transport: Transport, *, id: str) -> ResponseMessage:
3534
"""Issue `framebuffer:read` for the given device id and return raw response."""
3635
return await transport.request("framebuffer:read", {"id": id})
3736

@@ -44,9 +43,9 @@ def _extract_png_b64(resp: ResponseMessage) -> str:
4443
return png_b64
4544

4645

47-
async def framebuffer_png_bytes(transport: Transport, *, id: str) -> bytes:
46+
async def read_framebuffer_png_bytes(transport: Transport, *, id: str) -> bytes:
4847
"""Return decoded PNG bytes for the framebuffer of device `id`."""
49-
resp = await framebuffer_read(transport, id=id)
48+
resp = await read_framebuffer(transport, id=id)
5049
return base64.b64decode(_extract_png_b64(resp))
5150

5251

@@ -64,30 +63,8 @@ async def save_framebuffer_png(
6463
"""
6564
if path.exists() and not overwrite:
6665
raise WokwiError(f"File already exists and overwrite=False: {path}")
67-
data = await framebuffer_png_bytes(transport, id=id)
66+
data = await read_framebuffer_png_bytes(transport, id=id)
6867
path.parent.mkdir(parents=True, exist_ok=True)
6968
with open(path, "wb") as f:
7069
f.write(data)
7170
return path
72-
73-
74-
async def compare_framebuffer_png(
75-
transport: Transport, *, id: str, reference: Path, save_mismatch: Path | None = None
76-
) -> bool:
77-
"""Compare the current framebuffer PNG with a reference file.
78-
79-
Performs a byte-for-byte comparison. If different and `save_mismatch` is
80-
provided, writes the current framebuffer PNG there.
81-
82-
Returns True if identical, False otherwise.
83-
"""
84-
if not reference.exists():
85-
raise WokwiError(f"Reference image does not exist: {reference}")
86-
current = await framebuffer_png_bytes(transport, id=id)
87-
ref_bytes = reference.read_bytes()
88-
if current == ref_bytes:
89-
return True
90-
if save_mismatch:
91-
save_mismatch.parent.mkdir(parents=True, exist_ok=True)
92-
save_mismatch.write_bytes(current)
93-
return False

0 commit comments

Comments
 (0)