linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Vincent Fazio <vfazio@gmail.com>
To: linux-gpio@vger.kernel.org
Cc: vfazio@xes-inc.com, Vincent Fazio <vfazio@gmail.com>
Subject: [libgpiod][PATCH 1/9] bindings: python: make config iteration consistent
Date: Thu,  9 Oct 2025 08:05:07 -0500	[thread overview]
Message-ID: <20251009130516.3729433-2-vfazio@gmail.com> (raw)
In-Reply-To: <20251009130516.3729433-1-vfazio@gmail.com>

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 --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()
-- 
2.43.0


  reply	other threads:[~2025-10-09 13:05 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-09 13:05 [libgpiod][PATCH 0/9] bindings: python: improve line requests and reconfiguration Vincent Fazio
2025-10-09 13:05 ` Vincent Fazio [this message]
2025-10-09 13:05 ` [libgpiod][PATCH 2/9] bindings: python: remove unused attribute from LineRequest Vincent Fazio
2025-10-09 13:05 ` [libgpiod][PATCH 3/9] bindings: python: chip: track requested lines when enumerating Vincent Fazio
2025-10-09 13:05 ` [libgpiod][PATCH 4/9] bindings: python: chip: simplify duplicate checking Vincent Fazio
2025-10-09 13:05 ` [libgpiod][PATCH 5/9] bindings: python: chip: check mapped_output_values membership once Vincent Fazio
2025-10-09 13:05 ` [libgpiod][PATCH 6/9] bindings: python: line_request: ignore invalid line names in reconfigure_lines Vincent Fazio
2025-10-09 13:05 ` [libgpiod][PATCH 7/9] bindings: python: ext: add ability to query line name Vincent Fazio
2025-10-09 13:05 ` [libgpiod][PATCH 8/9] bindings: python: chip: map names for lines requested by offset Vincent Fazio
2025-10-09 13:05 ` [libgpiod][PATCH 9/9] bindings: python: line_request: warn on unknown lines when reconfiguring Vincent Fazio
2025-10-13 15:31 ` [libgpiod][PATCH 0/9] bindings: python: improve line requests and reconfiguration Bartosz Golaszewski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251009130516.3729433-2-vfazio@gmail.com \
    --to=vfazio@gmail.com \
    --cc=linux-gpio@vger.kernel.org \
    --cc=vfazio@xes-inc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).