bindings: python: more flexible reconfigure_lines()
authorKent Gibson <warthog618@gmail.com>
Wed, 26 Jun 2024 05:38:07 +0000 (13:38 +0800)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Mon, 8 Jul 2024 09:50:20 +0000 (11:50 +0200)
The C API requires the configuration passed to reconfigure_lines()
to contain the lines in the same order as they were requested.  This is
problematic for the Python bindings which accepts the configuration in
the form of a dict.  For versions prior to Python 3.6, dicts do not
maintain insertion order, so iterating over the dict emits lines in
unreliable order.

Even with later Python versions, the ordering requirement makes
reconfigure_lines() awkward to use as subsequent configurations may
group line settings quite differently to the request, yet the user must
go out of their way to reproduce the original ordering.
This is a task better performed by the bindings.

Further, while the documentation for reconfigure_lines() states that
None settings values are treated as default values, the current
implementation raises an error when it tries to dereference the None,
thinking it is an actual object.

Similarly, providing default values for lines for which no settings
are provided would allow support for reconfiguring a subset of
requested lines.

Rework reconfigure_lines() to remove the ordering requirement and
construct the configuration provided to the C API in request order.
Populate missing or None line settings with default values to satisfy
the requirements of the C API that all requested lines must be
reconfigured.

Closes: https://github.com/brgl/libgpiod/issues/54
Signed-off-by: Kent Gibson <warthog618@gmail.com>
Link: https://lore.kernel.org/r/20240626053808.179457-3-warthog618@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
bindings/python/gpiod/line_request.py

index cde298f5c7a153676e52c193aa5a6cab6b3e4dc5..51e600a2ee5854f11f12d41ef561ec7bcdeb5908 100644 (file)
@@ -151,23 +151,26 @@ class LineRequest:
         Args:
           config
             Dictionary mapping offsets or names (or tuples thereof) to
-            LineSettings. If None is passed as the value of the mapping,
-            default settings are used.
+            LineSettings. If no entry exists, or a None is passed as the
+            settings, then the configuration for that line is not changed.
+            Any settings for non-requested lines are ignored.
         """
         self._check_released()
 
         line_cfg = _ext.LineConfig()
+        line_settings = {}
 
         for lines, settings in config.items():
             if isinstance(lines, int) or isinstance(lines, str):
                 lines = [lines]
 
-            offsets = [
-                self._name_map[line] if self._check_line_name(line) else line
-                for line in lines
-            ]
+            for line in lines:
+                offset = self._name_map[line] if self._check_line_name(line) else line
+                line_settings[offset] = settings
 
-            line_cfg.add_line_settings(offsets, _line_settings_to_ext(settings))
+        for offset in self.offsets:
+            settings = line_settings.get(offset) or LineSettings()
+            line_cfg.add_line_settings([offset], _line_settings_to_ext(settings))
 
         self._req.reconfigure_lines(line_cfg)