diff mbox series

[libgpiod,1/9] bindings: python: make config iteration consistent

Message ID 20251009130516.3729433-2-vfazio@gmail.com
State New
Headers show
Series bindings: python: improve line requests and reconfiguration | expand

Commit Message

Vincent Fazio Oct. 9, 2025, 1:05 p.m. UTC
Previously, Chip.request_lines and LineRequest.reconfigure_lines
iterated over a config object but did so in subtly different ways.

Create a generator that iterates over a config object and returns line +
settings pairs. Update the aforementioned functions to use the generator
to consolidate and condense code.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
---
 bindings/python/gpiod/_internal.py    | 22 ++++++++++++++--
 bindings/python/gpiod/chip.py         | 38 ++++++++++++---------------
 bindings/python/gpiod/line_request.py | 12 +++------
 3 files changed, 41 insertions(+), 31 deletions(-)
diff mbox series

Patch

diff --git a/bindings/python/gpiod/_internal.py b/bindings/python/gpiod/_internal.py
index 37f6661..ee15796 100644
--- a/bindings/python/gpiod/_internal.py
+++ b/bindings/python/gpiod/_internal.py
@@ -1,11 +1,18 @@ 
 # SPDX-License-Identifier: LGPL-2.1-or-later
 # SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
 
+from __future__ import annotations
+
 from datetime import timedelta
 from select import select
-from typing import Optional, Union
+from typing import TYPE_CHECKING, Optional, Union
+
+if TYPE_CHECKING:
+    from collections.abc import Generator, Iterable
+
+    from .line_settings import LineSettings
 
-__all__ = ["poll_fd"]
+__all__ = ["poll_fd", "config_iter"]
 
 
 def poll_fd(fd: int, timeout: Optional[Union[timedelta, float]] = None) -> bool:
@@ -17,3 +24,14 @@  def poll_fd(fd: int, timeout: Optional[Union[timedelta, float]] = None) -> bool:
 
     readable, _, _ = select([fd], [], [], sec)
     return True if fd in readable else False
+
+
+def config_iter(
+    config: dict[Union[Iterable[Union[int, str]], int, str], Optional[LineSettings]],
+) -> Generator[tuple[Union[int, str], Optional[LineSettings]]]:
+    for key, settings in config.items():
+        if isinstance(key, int) or isinstance(key, str):
+            yield key, settings
+        else:
+            for subkey in key:
+                yield subkey, settings
diff --git a/bindings/python/gpiod/chip.py b/bindings/python/gpiod/chip.py
index 169488a..9f38ab7 100644
--- a/bindings/python/gpiod/chip.py
+++ b/bindings/python/gpiod/chip.py
@@ -8,7 +8,7 @@  from errno import ENOENT
 from typing import TYPE_CHECKING, Optional, Union, cast
 
 from . import _ext
-from ._internal import poll_fd
+from ._internal import config_iter, poll_fd
 from .exception import ChipClosedError
 from .line import Value
 from .line_request import LineRequest
@@ -305,28 +305,24 @@  class Chip:
         offset_map = dict()
         global_output_values = list()
 
-        for lines, settings in config.items():
+        for line, settings in config_iter(config):
             offsets = list()
 
-            if isinstance(lines, int) or isinstance(lines, str):
-                lines = (lines,)
-
-            for line in lines:
-                offset = self.line_offset_from_id(line)
-                offsets.append(offset)
-
-                # If there's a global output value for this offset, store it in the
-                # list for later.
-                if mapped_output_values:
-                    global_output_values.append(
-                        mapped_output_values[offset]
-                        if offset in mapped_output_values
-                        else Value.INACTIVE
-                    )
-
-                if isinstance(line, str):
-                    name_map[line] = offset
-                    offset_map[offset] = line
+            offset = self.line_offset_from_id(line)
+            offsets.append(offset)
+
+            # If there's a global output value for this offset, store it in the
+            # list for later.
+            if mapped_output_values:
+                global_output_values.append(
+                    mapped_output_values[offset]
+                    if offset in mapped_output_values
+                    else Value.INACTIVE
+                )
+
+            if isinstance(line, str):
+                name_map[line] = offset
+                offset_map[offset] = line
 
             line_cfg.add_line_settings(
                 offsets, _line_settings_to_ext(settings or LineSettings())
diff --git a/bindings/python/gpiod/line_request.py b/bindings/python/gpiod/line_request.py
index 69f86f6..7956e54 100644
--- a/bindings/python/gpiod/line_request.py
+++ b/bindings/python/gpiod/line_request.py
@@ -6,7 +6,7 @@  from __future__ import annotations
 from typing import TYPE_CHECKING, Optional, Union, cast
 
 from . import _ext
-from ._internal import poll_fd
+from ._internal import config_iter, poll_fd
 from .exception import RequestReleasedError
 from .line_settings import LineSettings, _line_settings_to_ext
 
@@ -174,13 +174,9 @@  class LineRequest:
         line_cfg = _ext.LineConfig()
         line_settings = {}
 
-        for lines, settings in config.items():
-            if isinstance(lines, int) or isinstance(lines, str):
-                lines = [lines]
-
-            for line in lines:
-                offset = self._line_to_offset(line)
-                line_settings[offset] = settings
+        for line, settings in config_iter(config):
+            offset = self._line_to_offset(line)
+            line_settings[offset] = settings
 
         for offset in self.offsets:
             settings = line_settings.get(offset) or LineSettings()