{"record":{"id":"c0b99bd30b550f8b","repo":"ruvnet/RuView","slug":"module-wifi-densepose-client-has-no-attribute-n","errorCode":null,"errorMessage":"module 'wifi_densepose.client' has no attribute {name!r}","messagePattern":"module 'wifi_densepose\\.client' has no attribute (.+?)","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"python/wifi_densepose/client/__init__.py","lineNumber":93,"sourceCode":"    `SensingClient` needs `websockets`; `RuViewMqttClient` needs\n    `paho-mqtt`. Importing those at package init would make\n    `wifi_densepose.client` unusable without the extras installed\n    — defeating the point of an *optional* extra. We defer the import\n    until the attribute is actually looked up.\n    \"\"\"\n    if name in {\n        \"SensingClient\",\n        \"SensingMessage\",\n        \"EdgeVitalsMessage\",\n        \"PoseDataMessage\",\n        \"ConnectionEstablishedMessage\",\n    }:\n        from wifi_densepose.client import ws as _ws\n        return getattr(_ws, name)\n    if name == \"RuViewMqttClient\":\n        from wifi_densepose.client.mqtt import RuViewMqttClient as _R\n        return _R\n    raise AttributeError(f\"module 'wifi_densepose.client' has no attribute {name!r}\")\n","sourceCodeStart":75,"sourceCodeEnd":94,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/python/wifi_densepose/client/__init__.py#L75-L94","documentation":"wifi_densepose.client implements PEP 562 lazy exports via a module-level __getattr__. Only a fixed allowlist resolves: SensingClient, SensingMessage, EdgeVitalsMessage, PoseDataMessage, ConnectionEstablishedMessage (from .ws) and RuViewMqttClient (from .mqtt). Any other attribute lookup falls through to `raise AttributeError` naming the missing symbol.","triggerScenarios":"`from wifi_densepose.client import RuviewMqttClient` (typo), `wifi_densepose.client.MQTTClient` (wrong name), or dynamic `getattr(wifi_densepose.client, name)` where name is not in the allowlist.","commonSituations":"Typos; code copied from older versions with different export names; IDE autocomplete drifting from the installed version; plugin systems doing getattr-by-string.","solutions":["Use exactly one of the re-exported names (the allowlist is listed in the __getattr__ source)","Import from the submodule directly: `from wifi_densepose.client.ws import SensingClient` or `from wifi_densepose.client.mqtt import RuViewMqttClient`","Run `python -c \"import wifi_densepose.client as c; print([n for n in dir(c)])\"` against the installed version to see current exports"],"exampleFix":"# before\nfrom wifi_densepose.client import MQTTClient  # AttributeError: no attribute 'MQTTClient'\n\n# after\nfrom wifi_densepose.client import RuViewMqttClient\n# or directly from the submodule:\nfrom wifi_densepose.client.mqtt import RuViewMqttClient","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"CLIENT_EXPORTS = frozenset({\n    \"SensingClient\", \"SensingMessage\", \"EdgeVitalsMessage\",\n    \"PoseDataMessage\", \"ConnectionEstablishedMessage\",\n    \"RuViewMqttClient\",\n})\n\ndef is_client_export(name: str) -> bool:\n    \"\"\"True if wifi_densepose.client re-exports `name`.\"\"\"\n    return name in CLIENT_EXPORTS","tryCatchPattern":"try:\n    obj = getattr(wifi_densepose.client, name)\nexcept AttributeError:\n    raise KeyError(\n        f\"{name!r} is not exported by wifi_densepose.client; \"\n        f\"known exports: {sorted(CLIENT_EXPORTS)}\"\n    ) from None","preventionTips":["Use static top-level imports so wrong names fail at import time, not at runtime","Keep a single export allowlist constant for any dynamic getattr code","Run a smoke import of integration modules in CI to catch renamed exports on upgrades"],"tags":["python","import","attribute","lazy-loading","pep562","typo"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}