Repository: pwr-Solaar/Solaar

Issue:
Ubuntu 22.10's upgrade to 1.1.5 broke stuff. ("'NoneType' object is not iterable") w/fix
Hey fwiw in Ubuntu 22.10 (beta), I just got an upgrade of solaar from 1.1.1 to 1.1.5 ([solaar_1.1.5+dfsg-1_all.deb](https://packages.ubuntu.com/kinetic/solaar)) and noticed that solaar was now broken.  Running it manually resulted in an error that ended like this:

```
....
  File "/usr/share/solaar/lib/logitech_receiver/device.py", line 352, in persister
    self._persister = _configuration.persister(self)
  File "/usr/share/solaar/lib/solaar/configuration.py", line 214, in persister
    _load()
  File "/usr/share/solaar/lib/solaar/configuration.py", line 71, in _load
    _config = _cleanup_load(loaded_config)
  File "/usr/share/solaar/lib/solaar/configuration.py", line 137, in _cleanup_load
    for element in c:
TypeError: 'NoneType' object is not iterable
```

This was running as the user (not rute) and seemed to be an issue parsing the `~/.config/solaar/config.yaml` file.  When I looked at that file, it was completely blank, though there was a file there `config.json` modified five months back that looked like this:

```
{
  "_version": "1.1.1"
}
```

On a hunch, I set the blank `config.yaml` to instead look like:

```
_version:1.1.5
```

and started solar and it came back!  It repopulated the config.yaml, so I'm guessing it just wanted any values in there so it wouldn't error out.

While this is probably a bug w/ubuntu's packaging and may even be due to me running as a normal user, the `configuration.yaml` file's `_cleanup_load(c)` function should probably gracefully behave if there are no yaml entries in there rather than silently crashing.

That is all!  This is probably going to have to also be addressed in the Ubuntu release, but I figured this was upstream so maybe it should be here as well.  Thanks!



Discussion:
This looks rather weird.  I don't see where the code could produce the empty yaml file.  I'll create a patch for the problem though.

One thing.  Solaar should always be run as you, not as root.  Solaar distributions should include a udev rule file that allows Solaar to read and write directly to Logitech devices even when run as you.  The code quality of Solaar isn't high enough to run as root and running as root ends up creating configuration files in roots home directory, which is not a good thing.

Resolving patch:
diff --git a/lib/solaar/configuration.py b/lib/solaar/configuration.py
--- a/lib/solaar/configuration.py
+++ b/lib/solaar/configuration.py
@@ -134,23 +134,26 @@ def _convert_json(json_dict):
 
 def _cleanup_load(c):
     _config = [__version__]
-    for element in c:
-        if isinstance(element, dict):
-            divert = element.get('divert-keys')
-            if divert:
-                sliding = element.get('dpi-sliding')
-                if sliding:  # convert old-style dpi-sliding setting to divert-keys entry
-                    divert[int(sliding)] = 3
-                element.pop('dpi-sliding', None)
-                gestures = element.get('mouse-gestures')
-                if gestures:  # convert old-style mouse-gestures setting to divert-keys entry
-                    divert[int(gestures)] = 2
-                element.pop('mouse-gestures', None)
-                # remove any string entries (from bad conversions)
-                element['divert-keys'] = {k: v for k, v in divert.items() if isinstance(k, int)}
-            # convert to device entries
-            element = _DeviceEntry(**element)
-            _config.append(element)
+    try:
+        for element in c:
+            if isinstance(element, dict):
+                divert = element.get('divert-keys')
+                if divert:
+                    sliding = element.get('dpi-sliding')
+                    if sliding:  # convert old-style dpi-sliding setting to divert-keys entry
+                        divert[int(sliding)] = 3
+                    element.pop('dpi-sliding', None)
+                    gestures = element.get('mouse-gestures')
+                    if gestures:  # convert old-style mouse-gestures setting to divert-keys entry
+                        divert[int(gestures)] = 2
+                    element.pop('mouse-gestures', None)
+                    # remove any string entries (from bad conversions)
+                    element['divert-keys'] = {k: v for k, v in divert.items() if isinstance(k, int)}
+                # convert to device entries
+                element = _DeviceEntry(**element)
+                _config.append(element)
+    except Exception as e:
+        _log.warn('Exception processing config.yaml file, ignoring contents: %s', e)
     return _config
 
 


Test patch: