plesty.lib.sim.demo_device ========================== .. py:module:: plesty.lib.sim.demo_device .. autoapi-nested-parse:: A complete, hardware-free device module — the standard, made executable. Every test that needs a device used to hand-write one. plesty-lib's pipeline tests had ``_MockDevice``, plesty-sdk's scaffold tests had ``_DocDevice``, and each hub module has its own. Four fakes, each a partial reading of the standard, each drifting: a duck-typed stand-in passes whatever it was written against, so a gate can be green here and the real thing fail on a device that merely registers its parameters differently. :class:`DemoDevice` replaces them. It is a real :class:`~plesty.lib.device.base_device_sync.BaseDeviceSyncModel` subclass exercising the parts of the standard that are actually easy to get wrong: - a **grouped** parameter, so ``get_config_list()`` answers ``MOTOR.position`` while the group is named ``motor`` — the command-prefix against group-name mismatch three modules hit independently - every declarable type, so a mock generator that mishandles one is caught - read-only, write-only and read-write access modes - a parameter constrained by ``options``, and one by ``min_value``/``max_value`` - an operation with inputs and outputs, and one with neither It is hardware-free the way the standard says a device should be: ``address="mock"`` selects an in-memory store, and any other address refuses to connect, exactly as a real module does when the instrument is absent. That convention is what ``plesty init mock-test`` probes for, so a module author reading this file is reading the thing the tooling expects. Because it is a real device, the mock pipeline can be run against it — and is, in this package's own test suite. The gates then have a subject that must keep passing, which is what makes a change to them detectable. Usage:: from plesty.lib.sim.demo_device import DemoDevice from plesty.lib.test.device_pipeline import DevicePipeline DevicePipeline(DemoDevice, address="mock").run_mock_pipeline() Attributes ---------- .. autoapisummary:: plesty.lib.sim.demo_device.MOCK_ADDRESS plesty.lib.sim.demo_device.DocDevice Classes ------- .. autoapisummary:: plesty.lib.sim.demo_device.DemoDevice Module Contents --------------- .. py:data:: MOCK_ADDRESS :value: 'mock' .. py:class:: DemoDevice(address: str = MOCK_ADDRESS, device_id: str | None = None, **kwargs: Any) Bases: :py:obj:`plesty.lib.device.base_device_sync.BaseDeviceSyncModel` A device that declares one of everything and needs no instrument. :param address: ``"mock"`` for the in-memory store. Any other value is taken to be a real instrument and refuses to connect, which is what a module does when the hardware is not there. :param device_id: Identifier, generated when omitted so repeated construction does not collide on the resource registry — the gates construct the device several times over. :param \*\*kwargs: Forwarded to the base device. Register the parameters and operations, and prepare the store. .. py:attribute:: address :value: 'mock' .. py:attribute:: _connected :value: False .. py:attribute:: _store :type: dict[str, Any] .. py:method:: _register_parameters() -> None Register one parameter of each kind the standard allows. .. py:method:: _register_operations() -> None Register an operation with parameters, and one without. .. py:method:: _solve_operation(request: dict[str, Any]) -> dict[str, Any] Execute one operation against the in-memory store. Every value returned here is a JSON primitive. That is the point, not a simplification: the 2026-08-04 round lost a server to an ndarray return value that could not be serialized, so a demo device returning anything the protocol cannot carry would teach the defect. :param request: ``{"op": name, "params": {...}, "func_meta": ...}``, the shape :class:`~plesty.lib.device.funcs.FunctionSystem` sends. :returns: The operation's declared outputs. :raises KeyError: If the operation is not registered. .. py:method:: init(main: Any = None) -> None Prepare the device. Nothing to open for the in-memory store. :param main: Unused; accepted for interface compatibility. .. py:method:: connect() -> bool Connect, or refuse when pointed at an instrument that is not there. :returns: ``True`` once connected. :raises ConnectionError: If *address* is not :data:`MOCK_ADDRESS`. .. py:method:: disconnect() -> None Disconnect and drop the stored state. .. py:method:: check_operatability() -> bool Return whether the device is connected. :returns: ``True`` when connected. .. py:method:: check_errors() -> list[str] Return the device's error queue. :returns: An empty list; the demo device has no fault to report. .. py:method:: identity() -> str Return the identification string. :returns: A vendor, model, serial and firmware string, as ``*IDN?`` answers. .. py:method:: _write_(key: str, value: Any, **kwargs: Any) -> bool Store a value. :param key: Runtime parameter key. :param value: Value to store. :param \*\*kwargs: Unused. :returns: ``True``. .. py:method:: _query_(key: str, **kwargs: Any) -> Any Return a stored value, or the parameter's default. :param key: Runtime parameter key. :param \*\*kwargs: Unused. :returns: The stored value, or the declared default. .. py:data:: DocDevice