diff --git a/tests/test_utils_ipy.py b/tests/test_utils_ipy.py new file mode 100644 index 00000000..1821ea69 --- /dev/null +++ b/tests/test_utils_ipy.py @@ -0,0 +1,90 @@ +from IPython import get_ipython +from slic.utils.ipy import devices +from slic.core.device.device import Device +from slic.core.adjustable import Adjustable +import types + +# Dummy Adjustable used only to simulate realistic Device attributes +class DummyAdjustable(Adjustable): + def __init__(self, name): + self.name = name + +def test_devices_repr_fallback_and_ignore(): + ipy = get_ipython() + assert ipy is not None, "This test must be run in IPython (Jupyter or ipython shell)" + + # Clean up previous test variables + for k in list(ipy.user_ns): + if k.startswith("test_") or k.startswith("_test_"): + del ipy.user_ns[k] + + # Valid BaseDevice subclasses + + class WithDescription(Device): + def __init__(self, ID): + super().__init__(ID) + self.description = "desc ok" + + class WithDoc(Device): + """doc ok""" + def __init__(self, ID): + super().__init__(ID) + + class WithName(Device): + def __init__(self, ID): + super().__init__(ID) + self.name = "name ok" + # remove description to force fallback + if hasattr(self, 'description'): + del self.description + + class WithOnlyID(Device): + def __init__(self, ID): + super().__init__(ID) + self.ID = ID + # remove name and description to force fallback to ID + if hasattr(self, 'description'): + del self.description + if hasattr(self, 'name'): + del self.name + + # Invalid or ignored objects + + ipy.user_ns["test_str"] = "i am a string" + ipy.user_ns["test_int"] = 42 + ipy.user_ns["test_list"] = [1, 2, 3] + ipy.user_ns["test_func"] = lambda x: x + ipy.user_ns["test_module"] = types + ipy.user_ns["test_fake_device"] = type("FakeDevice", (), {"ID": "123"})() + + ipy.user_ns["_test_hidden_device"] = WithDescription("HIDDEN") + + # Inject valid devices into the IPython user namespace === + + ipy.user_ns["test_desc"] = WithDescription("D1") # has description + ipy.user_ns["test_doc"] = WithDoc("D2") # has __doc__ + ipy.user_ns["test_name"] = WithName("D3") # has name + ipy.user_ns["test_id"] = WithOnlyID("D4") # fallback to ID + + # Execute devices() + out = repr(devices()) + + # Assert that valid devices appear and correct fallback values are present + assert "test_desc" in out + assert "desc ok" in out + + assert "test_doc" in out + assert "doc ok" in out + + assert "test_name" in out + assert "name ok" in out + + assert "test_id" in out + assert "D4" in out + + # ❌ Assert that all ignored values are NOT shown + for bad in [ + "test_str", "test_int", "test_list", "test_func", + "test_module", "test_fake_device", "_test_hidden_device" + ]: + assert bad not in out