From af18e2c42ecd11cdad403700cd13a8509e9a8cbe Mon Sep 17 00:00:00 2001 From: Vinicius Zein Date: Wed, 22 Apr 2026 12:51:47 -0400 Subject: [PATCH 1/2] fix(someip): fail fast when opensomeip native extension is unavailable Closes #628 --- .../jumpstarter_driver_someip/conftest.py | 9 ++++++++- .../jumpstarter_driver_someip/driver.py | 11 +++++++++++ .../jumpstarter_driver_someip/driver_test.py | 6 ++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py index 54d457a31..86e3d14df 100644 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/conftest.py @@ -15,7 +15,7 @@ import socket import struct import threading -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch import pytest @@ -388,6 +388,13 @@ def unregister_service(self, service_id: int, instance_id: int): ] +@pytest.fixture(autouse=True) +def _mock_get_ext(): + """Ensure the native-extension guard passes in all tests by default.""" + with patch("jumpstarter_driver_someip.driver.get_ext", return_value=object()): + yield + + @pytest.fixture def stateful_osip(): """Provide a fresh StatefulOsipClient instance.""" diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py index 53f48f623..46d7d265f 100755 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py @@ -7,6 +7,7 @@ from opensomeip import ClientConfig, TransportMode from opensomeip import SomeIpClient as OsipClient +from opensomeip._bridge import get_ext from opensomeip.message import Message from opensomeip.sd import SdConfig, ServiceInstance from opensomeip.transport import Endpoint @@ -91,6 +92,16 @@ def __post_init__(self): raise ValueError( f"Invalid transport_mode: {self.transport_mode!r}. Must be 'TCP' or 'UDP'." ) + + if get_ext() is None: + raise RuntimeError( + "opensomeip C++ extension (_opensomeip) is not available. " + "The SOME/IP driver requires the native extension for network I/O. " + "On macOS, rebuild with the system compiler: " + "CC=/usr/bin/clang CXX=/usr/bin/clang++ " + "pip install --no-cache-dir --force-reinstall --no-binary=opensomeip opensomeip" + ) + mode = TransportMode.TCP if transport_upper == "TCP" else TransportMode.UDP local_ep = Endpoint(self.host, self.port) diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py index 755fcf1a5..18ceed92c 100644 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py @@ -345,6 +345,12 @@ def test_someip_invalid_port_type(): SomeIp(host="127.0.0.1", port="not_a_port") # ty: ignore[invalid-argument-type] +@patch("jumpstarter_driver_someip.driver.get_ext", return_value=None) +def test_someip_raises_when_native_extension_unavailable(_mock_get_ext): + with pytest.raises(RuntimeError, match="C\\+\\+ extension"): + SomeIp(host="127.0.0.1", port=30490) + + @patch("jumpstarter_driver_someip.driver.OsipClient") def test_someip_invalid_transport_mode(mock_osip_cls): mock_osip_cls.return_value = _make_mock_osip_client() From daa42fd2d749d14598f60cf833752478977f0f36 Mon Sep 17 00:00:00 2001 From: Vinicius Zein Date: Wed, 22 Apr 2026 12:58:12 -0400 Subject: [PATCH 2/2] fix(someip): address CodeRabbit review nitpicks - Wrap private opensomeip._bridge import in try/except ImportError - Add cross-platform guidance to the RuntimeError message - Tighten test assertion regex to match _opensomeip symbol name Made-with: Cursor --- .../jumpstarter_driver_someip/driver.py | 9 +++++++-- .../jumpstarter_driver_someip/driver_test.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py index 46d7d265f..b78b79ad7 100755 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver.py @@ -7,7 +7,10 @@ from opensomeip import ClientConfig, TransportMode from opensomeip import SomeIpClient as OsipClient -from opensomeip._bridge import get_ext +try: + from opensomeip._bridge import get_ext +except ImportError: + get_ext = lambda: None # noqa: E731 from opensomeip.message import Message from opensomeip.sd import SdConfig, ServiceInstance from opensomeip.transport import Endpoint @@ -99,7 +102,9 @@ def __post_init__(self): "The SOME/IP driver requires the native extension for network I/O. " "On macOS, rebuild with the system compiler: " "CC=/usr/bin/clang CXX=/usr/bin/clang++ " - "pip install --no-cache-dir --force-reinstall --no-binary=opensomeip opensomeip" + "pip install --no-cache-dir --force-reinstall --no-binary=opensomeip opensomeip. " + "On other platforms, reinstall opensomeip and ensure the C++ " + "build toolchain is available." ) mode = TransportMode.TCP if transport_upper == "TCP" else TransportMode.UDP diff --git a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py index 18ceed92c..8e36a3416 100644 --- a/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py +++ b/python/packages/jumpstarter-driver-someip/jumpstarter_driver_someip/driver_test.py @@ -347,7 +347,7 @@ def test_someip_invalid_port_type(): @patch("jumpstarter_driver_someip.driver.get_ext", return_value=None) def test_someip_raises_when_native_extension_unavailable(_mock_get_ext): - with pytest.raises(RuntimeError, match="C\\+\\+ extension"): + with pytest.raises(RuntimeError, match=r"_opensomeip.*not available"): SomeIp(host="127.0.0.1", port=30490)