Skip to content

Commit 9610a21

Browse files
authored
Merge pull request #296 from P-R-O-C-H-Y/feat/wokwi-diagram-path-support
2 parents 30082f7 + 1383c2e commit 9610a21

File tree

5 files changed

+51
-20
lines changed

5 files changed

+51
-20
lines changed

pytest-embedded-wokwi/pytest_embedded_wokwi/__init__.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
"""Make pytest-embedded plugin work with the Wokwi CLI."""
22

3-
from .dut import WokwiDut
4-
from .wokwi_cli import WokwiCLI
3+
WOKWI_CLI_MINIMUM_VERSION = '0.10.1'
4+
5+
from .dut import WokwiDut # noqa
6+
from .wokwi_cli import WokwiCLI # noqa
57

68
__all__ = [
9+
'WOKWI_CLI_MINIMUM_VERSION',
710
'WokwiCLI',
811
'WokwiDut',
912
]

pytest-embedded-wokwi/pytest_embedded_wokwi/wokwi_cli.py

+28-18
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
import typing as t
66
from pathlib import Path
77

8+
import pexpect
89
import toml
10+
from packaging.version import Version
911
from pytest_embedded import __version__
1012
from pytest_embedded.log import DuplicateStdoutPopen
1113

14+
from pytest_embedded_wokwi import WOKWI_CLI_MINIMUM_VERSION
15+
1216
from .idf import IDFFirmwareResolver
1317

1418
if t.TYPE_CHECKING:
@@ -32,7 +36,6 @@ class WokwiCLI(DuplicateStdoutPopen):
3236
"""
3337

3438
SOURCE = 'Wokwi'
35-
3639
WOKWI_CLI_PATH = 'wokwi-cli'
3740

3841
def __init__(
@@ -41,6 +44,7 @@ def __init__(
4144
wokwi_cli_path: t.Optional[str] = None,
4245
wokwi_timeout: t.Optional[int] = None,
4346
wokwi_scenario: t.Optional[str] = None,
47+
wokwi_diagram: t.Optional[str] = None,
4448
app: t.Optional['IdfApp'] = None,
4549
**kwargs,
4650
):
@@ -51,15 +55,37 @@ def __init__(
5155
self.app = app
5256
self.firmware_resolver = firmware_resolver
5357

58+
# first need to check if wokwi-cli exists in PATH
59+
if shutil.which('wokwi-cli') is None:
60+
raise RuntimeError('Please install wokwi-cli, by running: curl -L https://wokwi.com/ci/install.sh | sh')
61+
62+
child = pexpect.spawn('wokwi-cli --help')
63+
try:
64+
child.expect(r'Wokwi CLI v(\d+\.\d+\.\d+)', timeout=1)
65+
wokwi_cli_version = child.match.group(1).decode('utf-8')
66+
except pexpect.TIMEOUT:
67+
logging.warning('Failed to get wokwi-cli version, assume version requirements satisfied')
68+
else:
69+
if Version(wokwi_cli_version) < Version(WOKWI_CLI_MINIMUM_VERSION):
70+
raise ValueError(
71+
f'Wokwi CLI version {wokwi_cli_version} is not supported. '
72+
f'Minimum version required: {WOKWI_CLI_MINIMUM_VERSION}. '
73+
f'To update Wokwi CLI run: curl -L https://wokwi.com/ci/install.sh | sh'
74+
)
75+
5476
self.create_wokwi_toml()
55-
self.create_diagram_json()
77+
78+
if wokwi_diagram is None:
79+
self.create_diagram_json()
5680

5781
wokwi_cli = wokwi_cli_path or self.wokwi_cli_executable
5882
cmd = [wokwi_cli, '--interactive', app.app_path]
5983
if (wokwi_timeout is not None) and (wokwi_timeout > 0):
6084
cmd.extend(['--timeout', str(wokwi_timeout)])
6185
if (wokwi_scenario is not None) and os.path.exists(wokwi_scenario):
6286
cmd.extend(['--scenario', wokwi_scenario])
87+
if (wokwi_diagram is not None) and os.path.exists(wokwi_diagram):
88+
cmd.extend(['--diagram-file', wokwi_diagram])
6389

6490
super().__init__(
6591
cmd=cmd,
@@ -107,22 +133,6 @@ def create_diagram_json(self):
107133
app = self.app
108134
target_board = target_to_board[app.target]
109135

110-
# Check for specific target.diagram.json file first
111-
diagram_json_path = os.path.join(app.app_path, (app.target + '.diagram.json'))
112-
if os.path.exists(diagram_json_path):
113-
# If there is also common diagram.json file, backup it first to diagram.json.old
114-
if os.path.exists(os.path.join(app.app_path, 'diagram.json')):
115-
logging.warning(
116-
'using %s instead. backup the original diagram.json to diagram.json.old', diagram_json_path
117-
)
118-
shutil.copyfile(
119-
os.path.join(app.app_path, 'diagram.json'),
120-
os.path.join(app.app_path, 'diagram.json.old'),
121-
)
122-
# Copy target.diagram.json to diagram.json
123-
shutil.copyfile(diagram_json_path, os.path.join(app.app_path, 'diagram.json'))
124-
return
125-
126136
# Check for common diagram.json file
127137
diagram_json_path = os.path.join(app.app_path, 'diagram.json')
128138
if os.path.exists(diagram_json_path):

pytest-embedded-wokwi/tests/test_wokwi.py

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def test_pexpect_by_wokwi(dut):
5454
'-s',
5555
'--embedded-services', 'arduino,wokwi',
5656
'--app-path', os.path.join(testdir.tmpdir, 'hello_world_arduino'),
57+
'--wokwi-diagram', os.path.join(testdir.tmpdir, 'hello_world_arduino/esp32.diagram.json'),
5758
)
5859

5960
result.assert_outcomes(passed=1)

pytest-embedded/pytest_embedded/dut_factory.py

+5
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ def _fixture_classes_and_options_fn(
149149
wokwi_cli_path,
150150
wokwi_timeout,
151151
wokwi_scenario,
152+
wokwi_diagram,
152153
skip_regenerate_image,
153154
encrypt,
154155
keyfile,
@@ -302,6 +303,7 @@ def _fixture_classes_and_options_fn(
302303
'wokwi_cli_path': wokwi_cli_path,
303304
'wokwi_timeout': wokwi_timeout,
304305
'wokwi_scenario': wokwi_scenario,
306+
'wokwi_diagram': wokwi_diagram,
305307
'msg_queue': msg_queue,
306308
'app': None,
307309
'meta': _meta,
@@ -608,6 +610,7 @@ def create(
608610
wokwi_cli_path: t.Optional[str] = None,
609611
wokwi_timeout: t.Optional[int] = 0,
610612
wokwi_scenario: t.Optional[str] = None,
613+
wokwi_diagram: t.Optional[str] = None,
611614
skip_regenerate_image: t.Optional[bool] = None,
612615
encrypt: t.Optional[bool] = None,
613616
keyfile: t.Optional[str] = None,
@@ -655,6 +658,7 @@ def create(
655658
wokwi_cli_path: Wokwi CLI path.
656659
wokwi_timeout: Wokwi timeout.
657660
wokwi_scenario: Wokwi scenario path.
661+
wokwi_diagram: Wokwi diagram path.
658662
skip_regenerate_image: Skip image regeneration flag.
659663
encrypt: Encryption flag.
660664
keyfile: Keyfile for encryption.
@@ -718,6 +722,7 @@ def create(
718722
'wokwi_cli_path': wokwi_cli_path,
719723
'wokwi_timeout': wokwi_timeout,
720724
'wokwi_scenario': wokwi_scenario,
725+
'wokwi_diagram': wokwi_diagram,
721726
'skip_regenerate_image': skip_regenerate_image,
722727
'encrypt': encrypt,
723728
'keyfile': keyfile,

pytest-embedded/pytest_embedded/plugin.py

+12
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ def pytest_addoption(parser):
283283
'--wokwi-scenario',
284284
help='Path to the wokwi scenario file (Default: None)',
285285
)
286+
wokwi_group.addoption(
287+
'--wokwi-diagram',
288+
help='Path to the wokwi diagram file (Default: None)',
289+
)
286290

287291

288292
###########
@@ -973,6 +977,13 @@ def wokwi_scenario(request: FixtureRequest) -> t.Optional[str]:
973977
return _request_param_or_config_option_or_default(request, 'wokwi_scenario', None)
974978

975979

980+
@pytest.fixture
981+
@multi_dut_argument
982+
def wokwi_diagram(request: FixtureRequest) -> t.Optional[str]:
983+
"""Enable parametrization for the same cli option"""
984+
return _request_param_or_config_option_or_default(request, 'wokwi_diagram', None)
985+
986+
976987
####################
977988
# Private Fixtures #
978989
####################
@@ -1031,6 +1042,7 @@ def parametrize_fixtures(
10311042
wokwi_cli_path,
10321043
wokwi_timeout,
10331044
wokwi_scenario,
1045+
wokwi_diagram,
10341046
skip_regenerate_image,
10351047
encrypt,
10361048
keyfile,

0 commit comments

Comments
 (0)