fix: work around asyncssh/fido2 AttributeError on Python 3.14 non-Windows#23
Conversation
…n 3.14 Agent-Logs-Url: https://github.com/gensyn/ssh_command/sessions/40be7829-f1be-4b60-83c3-b24fe786b4a8 Co-authored-by: gensyn <36128035+gensyn@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gensyn/ssh_command/sessions/40be7829-f1be-4b60-83c3-b24fe786b4a8 Co-authored-by: gensyn <36128035+gensyn@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Works around a Python 3.14 import-time crash involving asyncssh and fido2 on non-Windows platforms by pre-handling the problematic fido2.client.windows import before asyncssh is imported.
Changes:
- Adds an early, non-Windows-only pre-import of
fido2.client.windowsand on failure seedssys.modules["fido2.client.windows"] = Noneso later imports raiseImportErrorinstead ofAttributeError. - Moves
_LOGGERinitialization earlier to support debug logging during the pre-import step.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try: | ||
| import fido2.client.windows # noqa: F401 | ||
| except (ImportError, OSError, AttributeError) as _fido2_err: |
There was a problem hiding this comment.
# noqa: F401 won’t silence pylint’s unused-import check (and the workflow doesn’t disable unused-import), so this line is likely to fail CI. Prefer a pylint suppression (# pylint: disable=unused-import) or avoid binding an unused name by using importlib.import_module("fido2.client.windows") instead of a plain import.
| if sys.platform != "win32": | ||
| try: | ||
| import fido2.client.windows # noqa: F401 | ||
| except (ImportError, OSError, AttributeError) as _fido2_err: | ||
| _LOGGER.debug( | ||
| "fido2.client.windows unavailable (%s); asyncssh Windows WebAuthn support disabled", | ||
| _fido2_err, | ||
| ) | ||
| sys.modules["fido2.client.windows"] = None # type: ignore[assignment] |
There was a problem hiding this comment.
This workaround changes module import-time behavior on non-Windows by mutating sys.modules. There’s currently no unit test covering the failure path (e.g., simulating fido2.client.windows raising AttributeError) to ensure coordinator.py still imports and the negative-cache entry is installed; adding one would help prevent regressions on Python 3.14+.
On Python 3.14,
ctypes.HRESULTwas removed for non-Windows platforms. Whenfido2is installed in the HA environment,asyncssh'ssk.pyattemptsfrom fido2.client.windows import WindowsClientinside atry/except ImportErrorblock — butfido2/client/win_api.pyraisesAttributeErrorat module level (HRESULT = ctypes.HRESULT), which goes uncaught and blows up the entireasyncsshimport.Fix
Pre-attempt the problematic import in
coordinator.pybeforeasyncsshis loaded. On failure, writeNoneintosys.modules["fido2.client.windows"]— Python's negative-cache mechanism — so that asyncssh's subsequent import attempt raisesImportErrorinstead, which it already handles gracefully (disabling Windows WebAuthn support).This is a targeted workaround for a bug in asyncssh's exception handling (
except ImportErrorshould beexcept (ImportError, AttributeError)). No functional behaviour changes on Windows or in environments wherefido2is absent or fully compatible.