diff --git a/docs/developer/vision_pipeline_architecture.md b/docs/developer/vision_pipeline_architecture.md index a9700c7d..b69860ac 100644 --- a/docs/developer/vision_pipeline_architecture.md +++ b/docs/developer/vision_pipeline_architecture.md @@ -1,5 +1,3 @@ -(developer.vision_pipeline)= - # Vision pipeline architecture: `VisionInterface` and `SampleVisionMonitor` A generic, camera-agnostic machine-vision layer living under @@ -124,7 +122,7 @@ caller. `diagnostic_image` (and `DummyVisionCamera.image`) is a `PreviewSignal`, a `BECMessageSignal` subclass. Every `BECMessageSignal` hardcodes `rpc_access` to `False`, so — same gotcha documented in -{ref}`the LamNI smear architecture notes ` +[the LamNI smear architecture notes](lamni_smear_architecture.md) for `IDSCamera`'s preview channels — it does **not** appear as a client-side device attribute at all: @@ -158,28 +156,29 @@ guaranteed, so this can't be resolved at construction). `PSIDeviceBase` itself accepts a `device_manager` keyword and stores it — but that alone is **not** enough for it to ever be populated with a real value. -:::{important} -The device server's `DeviceManagerDS.construct_device_obj()` only injects -`device_manager` into a device's constructor when that device class's *own* -`__init__` **signature** names a `device_manager` parameter explicitly: +!!! important -```python -signature = inspect.signature(dev_cls) -if "device_manager" in signature.parameters: - init_kwargs["device_manager"] = device_manager -``` + The device server's `DeviceManagerDS.construct_device_obj()` only injects + `device_manager` into a device's constructor when that device class's *own* + `__init__` **signature** names a `device_manager` parameter explicitly: + + ```python + signature = inspect.signature(dev_cls) + if "device_manager" in signature.parameters: + init_kwargs["device_manager"] = device_manager + ``` + + `inspect.signature()` on a class reflects only that class's own `__init__` + — it does not look through `**kwargs` into a base class. A subclass whose + `__init__` accepts only `**kwargs` and forwards it to + `super().__init__(..., **kwargs)` will happily accept `device_manager` if + passed directly (e.g. unit tests instantiating the class themselves), but + the device server will never pass it, silently leaving + `self.device_manager` at its default of `None` for the lifetime of the + object — with no error at startup. Every call that resolves a sibling + device (`self.device_manager.devices.get(...)`) then fails at call time + instead, with `device manager is not available`. -`inspect.signature()` on a class reflects only that class's own `__init__` -— it does not look through `**kwargs` into a base class. A subclass whose -`__init__` accepts only `**kwargs` and forwards it to -`super().__init__(..., **kwargs)` will happily accept `device_manager` if -passed directly (e.g. unit tests instantiating the class themselves), but -the device server will never pass it, silently leaving -`self.device_manager` at its default of `None` for the lifetime of the -object — with no error at startup. Every call that resolves a sibling -device (`self.device_manager.devices.get(...)`) then fails at call time -instead, with `device manager is not available`. -::: The fix, and the required pattern for any new `PSIDeviceBase` subclass that needs to look up sibling devices (the same shape already used by diff --git a/zensical.toml b/zensical.toml index 37fe217e..82006121 100644 --- a/zensical.toml +++ b/zensical.toml @@ -46,6 +46,7 @@ nav = [ { "Overview" = "developer/developer.md" }, { "Editing the documentation" = "developer/editing_docs.md" }, { "LamNI smear aid architecture" = "developer/lamni_smear_architecture.md" }, + { "Vision pipeline architecture" = "developer/vision_pipeline_architecture.md" }, { "PandaBox free-running setup" = "developer/panda_box_free_running_setup.md" }, { "PandaBox data schema" = "developer/panda_box_free_running_data_schema.md" }, ] },