`solaar show` (and any exit path) printed a cascade of "I/O operation on closed file" / "sys.meta_path is None" logging errors at the bottom. Two compounding causes: - Device.close() was not idempotent. The CLI closes devices explicitly, then __del__ calls close() again during interpreter shutdown, re-running every device cleanup a second time. Guard with a _closed flag (not self.handle, which is legitimately None for receiver-paired devices). - rgb_power.cleanup() read device.settings — the lazy property — which forces a first-time settings build. Running that build during shutdown fails because gettext can no longer import (sys.meta_path is None), raising inside a __del__ handler. Read the already-built settings (or the persister) via a new _rgb_control_off() helper that never triggers the build. Either guard alone stops the crash; both are correct hardening for a __del__-invoked path. |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| advanced_para_eq.py | ||
| base.py | ||
| base_usb.py | ||
| centurion.py | ||
| centurion_constants.py | ||
| common.py | ||
| descriptors.py | ||
| desktop_notifications.py | ||
| device.py | ||
| device_quirks.py | ||
| diversion.py | ||
| exceptions.py | ||
| headset_rgb.py | ||
| hidpp10.py | ||
| hidpp10_constants.py | ||
| hidpp20.py | ||
| hidpp20_constants.py | ||
| i18n.py | ||
| listener.py | ||
| logivoice.py | ||
| notifications.py | ||
| onboard_eq.py | ||
| receiver.py | ||
| rgb_effects_probe.py | ||
| rgb_power.py | ||
| settings.py | ||
| settings_new.py | ||
| settings_templates.py | ||
| settings_validator.py | ||
| special_keys.py | ||