gpiod 2.2.4__tar.gz → 2.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {gpiod-2.2.4 → gpiod-2.3.0}/MANIFEST.in +1 -1
  2. {gpiod-2.2.4/gpiod.egg-info → gpiod-2.3.0}/PKG-INFO +34 -14
  3. {gpiod-2.2.4 → gpiod-2.3.0}/README.md +17 -0
  4. {gpiod-2.2.4 → gpiod-2.3.0}/build_tests.py +11 -7
  5. gpiod-2.3.0/gpiod/__init__.py +124 -0
  6. gpiod-2.3.0/gpiod/_ext.pyi +93 -0
  7. gpiod-2.2.4/gpiod/internal.py → gpiod-2.3.0/gpiod/_internal.py +3 -2
  8. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/chip.py +57 -35
  9. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/chip_info.py +8 -5
  10. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/edge_event.py +14 -4
  11. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/exception.py +2 -2
  12. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/info_event.py +14 -7
  13. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/line.py +23 -2
  14. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/line_info.py +17 -5
  15. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/line_request.py +69 -48
  16. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/line_settings.py +16 -7
  17. gpiod-2.3.0/gpiod/py.typed +0 -0
  18. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/version.py +1 -1
  19. {gpiod-2.2.4 → gpiod-2.3.0/gpiod.egg-info}/PKG-INFO +34 -14
  20. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod.egg-info/SOURCES.txt +5 -3
  21. {gpiod-2.2.4 → gpiod-2.3.0}/include/gpiod.h +0 -36
  22. gpiod-2.3.0/libgpiod-version.txt +1 -0
  23. gpiod-2.3.0/pyproject.toml +82 -0
  24. {gpiod-2.2.4 → gpiod-2.3.0}/setup.py +1 -18
  25. gpiod-2.3.0/tests/__init__.py +12 -0
  26. {gpiod-2.2.4 → gpiod-2.3.0}/tests/__main__.py +3 -4
  27. {gpiod-2.2.4 → gpiod-2.3.0}/tests/gpiosim/__init__.py +3 -1
  28. {gpiod-2.2.4 → gpiod-2.3.0}/tests/gpiosim/chip.py +2 -1
  29. gpiod-2.3.0/tests/helpers.py +27 -0
  30. gpiod-2.3.0/tests/system/__init__.py +6 -0
  31. gpiod-2.3.0/tests/system/ext.c +79 -0
  32. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_chip.py +50 -49
  33. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_chip_info.py +16 -15
  34. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_edge_event.py +69 -28
  35. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_info_event.py +59 -40
  36. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_line.py +4 -3
  37. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_line_info.py +20 -20
  38. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_line_request.py +199 -99
  39. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_line_settings.py +10 -11
  40. {gpiod-2.2.4 → gpiod-2.3.0}/tests/tests_module.py +18 -19
  41. gpiod-2.2.4/gpiod/__init__.py +0 -54
  42. gpiod-2.2.4/libgpiod-version.txt +0 -1
  43. gpiod-2.2.4/pyproject.toml +0 -5
  44. gpiod-2.2.4/tests/__init__.py +0 -17
  45. gpiod-2.2.4/tests/helpers.py +0 -16
  46. gpiod-2.2.4/tests/procname/__init__.py +0 -4
  47. gpiod-2.2.4/tests/procname/ext.c +0 -42
  48. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/ext/chip.c +0 -0
  49. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/ext/common.c +0 -0
  50. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/ext/internal.h +0 -0
  51. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/ext/line-config.c +0 -0
  52. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/ext/line-settings.c +0 -0
  53. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/ext/module.c +0 -0
  54. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod/ext/request.c +0 -0
  55. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod.egg-info/dependency_links.txt +0 -0
  56. {gpiod-2.2.4 → gpiod-2.3.0}/gpiod.egg-info/top_level.txt +0 -0
  57. {gpiod-2.2.4 → gpiod-2.3.0}/lib/chip-info.c +0 -0
  58. {gpiod-2.2.4 → gpiod-2.3.0}/lib/chip.c +0 -0
  59. {gpiod-2.2.4 → gpiod-2.3.0}/lib/edge-event.c +0 -0
  60. {gpiod-2.2.4 → gpiod-2.3.0}/lib/info-event.c +0 -0
  61. {gpiod-2.2.4 → gpiod-2.3.0}/lib/internal.c +0 -0
  62. {gpiod-2.2.4 → gpiod-2.3.0}/lib/internal.h +0 -0
  63. {gpiod-2.2.4 → gpiod-2.3.0}/lib/line-config.c +0 -0
  64. {gpiod-2.2.4 → gpiod-2.3.0}/lib/line-info.c +0 -0
  65. {gpiod-2.2.4 → gpiod-2.3.0}/lib/line-request.c +0 -0
  66. {gpiod-2.2.4 → gpiod-2.3.0}/lib/line-settings.c +0 -0
  67. {gpiod-2.2.4 → gpiod-2.3.0}/lib/misc.c +0 -0
  68. {gpiod-2.2.4 → gpiod-2.3.0}/lib/request-config.c +0 -0
  69. {gpiod-2.2.4 → gpiod-2.3.0}/lib/uapi/gpio.h +0 -0
  70. {gpiod-2.2.4 → gpiod-2.3.0}/setup.cfg +0 -0
  71. {gpiod-2.2.4 → gpiod-2.3.0}/tests/gpiosim/ext.c +0 -0
@@ -13,7 +13,7 @@ recursive-include gpiod/ext *.c
13
13
  recursive-include gpiod/ext *.h
14
14
 
15
15
  recursive-include tests/gpiosim *.c
16
- recursive-include tests/procname *.c
16
+ recursive-include tests/system *.c
17
17
 
18
18
  recursive-include lib *.c
19
19
  recursive-include lib *.h
@@ -1,23 +1,26 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: gpiod
3
- Version: 2.2.4
3
+ Version: 2.3.0
4
4
  Summary: Python bindings for libgpiod
5
- Home-page: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
6
- Author: Bartosz Golaszewski
7
- Author-email: brgl@bgdev.pl
8
- License: LGPLv2.1
5
+ Author-email: Bartosz Golaszewski <brgl@bgdev.pl>
6
+ License: LGPL-2.1-or-later
7
+ Project-URL: Homepage, https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
8
+ Project-URL: Issues, https://github.com/brgl/libgpiod/issues/
9
9
  Platform: linux
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Typing :: Typed
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
10
22
  Requires-Python: >=3.9.0
11
23
  Description-Content-Type: text/markdown
12
- Dynamic: author
13
- Dynamic: author-email
14
- Dynamic: description
15
- Dynamic: description-content-type
16
- Dynamic: home-page
17
- Dynamic: license
18
- Dynamic: platform
19
- Dynamic: requires-python
20
- Dynamic: summary
21
24
 
22
25
  <!-- SPDX-License-Identifier: CC-BY-SA-4.0 -->
23
26
  <!-- SPDX-FileCopyrightText: 2023 Phil Howard <phil@gadgetoid.com> -->
@@ -133,3 +136,20 @@ make python-tests-run
133
136
 
134
137
  from the `libgpiod/bindings/python` directory as root (necessary to be able
135
138
  to create the **gpio-sims** used for testing).
139
+
140
+ ## Linting/Formatting
141
+
142
+ When making changes, ensure type checks and linting still pass:
143
+
144
+ ```
145
+ python3 -m venv venv
146
+ . venv/bin/activate
147
+ pip install mypy ruff
148
+ mypy; ruff format; ruff check
149
+ ```
150
+
151
+ Ideally the gpiod library will continue to pass strict checks:
152
+
153
+ ```
154
+ mypy --strict
155
+ ```
@@ -112,3 +112,20 @@ make python-tests-run
112
112
 
113
113
  from the `libgpiod/bindings/python` directory as root (necessary to be able
114
114
  to create the **gpio-sims** used for testing).
115
+
116
+ ## Linting/Formatting
117
+
118
+ When making changes, ensure type checks and linting still pass:
119
+
120
+ ```
121
+ python3 -m venv venv
122
+ . venv/bin/activate
123
+ pip install mypy ruff
124
+ mypy; ruff format; ruff check
125
+ ```
126
+
127
+ Ideally the gpiod library will continue to pass strict checks:
128
+
129
+ ```
130
+ mypy --strict
131
+ ```
@@ -11,7 +11,7 @@ polluted with artefacts in build/
11
11
  Builds:
12
12
 
13
13
  tests/gpiosim/_ext.<target>.so
14
- tests/procname/_ext.<target>.so
14
+ tests/system/_ext.<target>.so
15
15
 
16
16
  """
17
17
 
@@ -61,9 +61,9 @@ gpiosim_ext = Extension(
61
61
  ],
62
62
  )
63
63
 
64
- procname_ext = Extension(
65
- "tests.procname._ext",
66
- sources=["tests/procname/ext.c"],
64
+ system_ext = Extension(
65
+ "tests.system._ext",
66
+ sources=["tests/system/ext.c"],
67
67
  define_macros=[("_GNU_SOURCE", "1")],
68
68
  extra_compile_args=["-Wall", "-Wextra"],
69
69
  )
@@ -71,7 +71,7 @@ procname_ext = Extension(
71
71
  dist = Distribution(
72
72
  {
73
73
  "name": "gpiod",
74
- "ext_modules": [gpiosim_ext, procname_ext, gpiod_ext],
74
+ "ext_modules": [gpiosim_ext, system_ext, gpiod_ext],
75
75
  "version": __version__,
76
76
  "platforms": ["linux"],
77
77
  }
@@ -82,9 +82,13 @@ try:
82
82
 
83
83
  configure()
84
84
  except ImportError:
85
- from distutils.log import DEBUG, set_verbosity
85
+ try:
86
+ from distutils.log import DEBUG, set_verbosity
86
87
 
87
- set_verbosity(DEBUG)
88
+ set_verbosity(DEBUG)
89
+ except ImportError:
90
+ # We can still build the tests, it will just be very quiet.
91
+ pass
88
92
 
89
93
  with tempfile.TemporaryDirectory(prefix="libgpiod-") as temp_dir:
90
94
  command = build_ext(dist)
@@ -0,0 +1,124 @@
1
+ # SPDX-License-Identifier: LGPL-2.1-or-later
2
+ # SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
3
+
4
+ """
5
+ Python bindings for libgpiod.
6
+
7
+ This module wraps the native C API of libgpiod in a set of python classes.
8
+ """
9
+
10
+ from collections.abc import Iterable
11
+ from typing import Optional, Union
12
+
13
+ from . import (
14
+ _ext,
15
+ chip,
16
+ chip_info,
17
+ edge_event,
18
+ exception,
19
+ info_event,
20
+ line,
21
+ line_info,
22
+ line_request,
23
+ line_settings,
24
+ version,
25
+ )
26
+ from .chip import *
27
+ from .chip_info import *
28
+ from .edge_event import *
29
+ from .exception import *
30
+ from .info_event import *
31
+ from .line_info import *
32
+ from .line_request import *
33
+ from .line_settings import *
34
+ from .version import __version__
35
+
36
+ api_version = _ext.api_version
37
+
38
+ # public submodules
39
+ __all__ = [
40
+ "chip",
41
+ "chip_info",
42
+ "edge_event",
43
+ "exception",
44
+ "info_event",
45
+ "line",
46
+ "line_info",
47
+ "line_request",
48
+ "line_settings",
49
+ "version",
50
+ ]
51
+
52
+ # re-export public submodule exports
53
+ # do not re-export line objects, this is not an oversight
54
+ __all__ += (
55
+ chip.__all__
56
+ + chip_info.__all__
57
+ + edge_event.__all__
58
+ + exception.__all__
59
+ + info_event.__all__
60
+ + line_info.__all__
61
+ + line_request.__all__
62
+ + line_settings.__all__
63
+ )
64
+
65
+ # module methods/attributes
66
+ __all__ += [
67
+ "__version__",
68
+ "api_version",
69
+ "is_gpiochip_device",
70
+ "request_lines",
71
+ ]
72
+
73
+
74
+ def is_gpiochip_device(path: str) -> bool:
75
+ """
76
+ Check if the file pointed to by path is a GPIO chip character device.
77
+
78
+ Args:
79
+ path
80
+ Path to the file that should be checked.
81
+
82
+ Returns:
83
+ Returns true if so, False otherwise.
84
+ """
85
+ return _ext.is_gpiochip_device(path)
86
+
87
+
88
+ def request_lines(
89
+ path: str,
90
+ config: dict[Union[Iterable[Union[int, str]], int, str], Optional[LineSettings]],
91
+ consumer: Optional[str] = None,
92
+ event_buffer_size: Optional[int] = None,
93
+ output_values: Optional[dict[Union[int, str], line.Value]] = None,
94
+ ) -> LineRequest:
95
+ """
96
+ Open a GPIO chip pointed to by 'path', request lines according to the
97
+ configuration arguments, close the chip and return the request object.
98
+
99
+ Args:
100
+ path
101
+ Path to the GPIO character device file.
102
+ config:
103
+ Dictionary mapping offsets or names (or tuples thereof) to
104
+ LineSettings. If None is passed as the value of the mapping,
105
+ default settings are used.
106
+ consumer:
107
+ Consumer string to use for this request.
108
+ event_buffer_size:
109
+ Size of the kernel edge event buffer to configure for this request.
110
+ output_values:
111
+ Dictionary mapping offsets or names to line.Value. This can be used
112
+ to set the desired output values globally while reusing LineSettings
113
+ for more lines.
114
+
115
+ Returns:
116
+ Returns a new LineRequest object.
117
+ """
118
+ with Chip(path) as chip:
119
+ return chip.request_lines(
120
+ config=config,
121
+ consumer=consumer,
122
+ event_buffer_size=event_buffer_size,
123
+ output_values=output_values,
124
+ )
@@ -0,0 +1,93 @@
1
+ # SPDX-License-Identifier: LGPL-2.1-or-later
2
+ # SPDX-FileCopyrightText: 2024 Vincent Fazio <vfazio@gmail.com>
3
+
4
+ from typing import Optional
5
+
6
+ from .chip_info import ChipInfo
7
+ from .edge_event import EdgeEvent
8
+ from .info_event import InfoEvent
9
+ from .line import Value
10
+ from .line_info import LineInfo
11
+
12
+ class LineSettings:
13
+ def __init__(
14
+ self,
15
+ direction: int,
16
+ edge_detection: int,
17
+ bias: int,
18
+ drive: int,
19
+ active_low: bool,
20
+ debounce_period: int,
21
+ event_clock: int,
22
+ output_value: int,
23
+ ) -> None: ...
24
+
25
+ class LineConfig:
26
+ def __init__(self) -> None: ...
27
+ def add_line_settings(self, offsets: list[int], settings: LineSettings) -> None: ...
28
+ def set_output_values(self, global_output_values: list[Value]) -> None: ...
29
+
30
+ class Request:
31
+ def release(self) -> None: ...
32
+ def get_values(self, offsets: list[int], values: list[Value]) -> None: ...
33
+ def set_values(self, values: dict[int, Value]) -> None: ...
34
+ def reconfigure_lines(self, line_cfg: LineConfig) -> None: ...
35
+ def read_edge_events(self, max_events: Optional[int]) -> list[EdgeEvent]: ...
36
+ @property
37
+ def chip_name(self) -> str: ...
38
+ @property
39
+ def num_lines(self) -> int: ...
40
+ @property
41
+ def offsets(self) -> list[int]: ...
42
+ @property
43
+ def fd(self) -> int: ...
44
+
45
+ class Chip:
46
+ def __init__(self, path: str) -> None: ...
47
+ def get_info(self) -> ChipInfo: ...
48
+ def line_offset_from_id(self, id: str) -> int: ...
49
+ def get_line_info(self, offset: int, watch: bool) -> LineInfo: ...
50
+ def request_lines(
51
+ self,
52
+ line_cfg: LineConfig,
53
+ consumer: Optional[str],
54
+ event_buffer_size: Optional[int],
55
+ ) -> Request: ...
56
+ def read_info_event(self) -> InfoEvent: ...
57
+ def close(self) -> None: ...
58
+ def unwatch_line_info(self, line: int) -> None: ...
59
+ @property
60
+ def path(self) -> str: ...
61
+ @property
62
+ def fd(self) -> int: ...
63
+
64
+ def is_gpiochip_device(path: str) -> bool: ...
65
+
66
+ api_version: str
67
+
68
+ # enum constants
69
+ BIAS_AS_IS: int
70
+ BIAS_DISABLED: int
71
+ BIAS_PULL_DOWN: int
72
+ BIAS_PULL_UP: int
73
+ BIAS_UNKNOWN: int
74
+ CLOCK_HTE: int
75
+ CLOCK_MONOTONIC: int
76
+ CLOCK_REALTIME: int
77
+ DIRECTION_AS_IS: int
78
+ DIRECTION_INPUT: int
79
+ DIRECTION_OUTPUT: int
80
+ DRIVE_OPEN_DRAIN: int
81
+ DRIVE_OPEN_SOURCE: int
82
+ DRIVE_PUSH_PULL: int
83
+ EDGE_BOTH: int
84
+ EDGE_EVENT_TYPE_FALLING: int
85
+ EDGE_EVENT_TYPE_RISING: int
86
+ EDGE_FALLING: int
87
+ EDGE_NONE: int
88
+ EDGE_RISING: int
89
+ INFO_EVENT_TYPE_LINE_CONFIG_CHANGED: int
90
+ INFO_EVENT_TYPE_LINE_RELEASED: int
91
+ INFO_EVENT_TYPE_LINE_REQUESTED: int
92
+ VALUE_ACTIVE: int
93
+ VALUE_INACTIVE: int
@@ -1,14 +1,15 @@
1
- # SPDX-License-Identifier: GPL-2.0-or-later
1
+ # SPDX-License-Identifier: LGPL-2.1-or-later
2
2
  # SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
3
3
 
4
4
  from datetime import timedelta
5
5
  from select import select
6
6
  from typing import Optional, Union
7
7
 
8
- __all__ = []
8
+ __all__ = ["poll_fd"]
9
9
 
10
10
 
11
11
  def poll_fd(fd: int, timeout: Optional[Union[timedelta, float]] = None) -> bool:
12
+ sec: Union[float, None]
12
13
  if isinstance(timeout, timedelta):
13
14
  sec = timeout.total_seconds()
14
15
  else:
@@ -1,22 +1,29 @@
1
1
  # SPDX-License-Identifier: LGPL-2.1-or-later
2
2
  # SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
3
3
 
4
+ from __future__ import annotations
5
+
6
+ from collections import Counter
7
+ from errno import ENOENT
8
+ from typing import TYPE_CHECKING, Optional, Union, cast
9
+
4
10
  from . import _ext
5
- from .chip_info import ChipInfo
11
+ from ._internal import poll_fd
6
12
  from .exception import ChipClosedError
7
- from .info_event import InfoEvent
8
- from .internal import poll_fd
9
13
  from .line import Value
10
- from .line_info import LineInfo
11
- from .line_settings import LineSettings, _line_settings_to_ext
12
14
  from .line_request import LineRequest
13
- from collections import Counter
14
- from collections.abc import Iterable
15
- from datetime import timedelta
16
- from errno import ENOENT
17
- from typing import Union, Optional
15
+ from .line_settings import LineSettings, _line_settings_to_ext
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Iterable
19
+ from datetime import timedelta
20
+ from types import TracebackType
21
+
22
+ from .chip_info import ChipInfo
23
+ from .info_event import InfoEvent
24
+ from .line_info import LineInfo
18
25
 
19
- __all__ = "Chip"
26
+ __all__ = ["Chip"]
20
27
 
21
28
 
22
29
  class Chip:
@@ -32,7 +39,7 @@ class Chip:
32
39
  Callers must close the chip by calling the close() method when it's no longer
33
40
  used.
34
41
 
35
- Example:
42
+ Example::
36
43
 
37
44
  chip = gpiod.Chip(\"/dev/gpiochip0\")
38
45
  do_something(chip)
@@ -40,7 +47,7 @@ class Chip:
40
47
 
41
48
  The gpiod.Chip class also supports controlled execution ('with' statement).
42
49
 
43
- Example:
50
+ Example::
44
51
 
45
52
  with gpiod.Chip(path="/dev/gpiochip0") as chip:
46
53
  do_something(chip)
@@ -54,8 +61,8 @@ class Chip:
54
61
  path:
55
62
  Path to the GPIO character device file.
56
63
  """
57
- self._chip = _ext.Chip(path)
58
- self._info = None
64
+ self._chip: Union[_ext.Chip, None] = _ext.Chip(path)
65
+ self._info: Union[ChipInfo, None] = None
59
66
 
60
67
  def __bool__(self) -> bool:
61
68
  """
@@ -66,14 +73,19 @@ class Chip:
66
73
  """
67
74
  return True if self._chip else False
68
75
 
69
- def __enter__(self):
76
+ def __enter__(self) -> Chip:
70
77
  """
71
78
  Controlled execution enter callback.
72
79
  """
73
80
  self._check_closed()
74
81
  return self
75
82
 
76
- def __exit__(self, exc_type, exc_value, traceback) -> None:
83
+ def __exit__(
84
+ self,
85
+ exc_type: Optional[type[BaseException]],
86
+ exc_value: Optional[BaseException],
87
+ traceback: Optional[TracebackType],
88
+ ) -> None:
77
89
  """
78
90
  Controlled execution exit callback.
79
91
  """
@@ -89,7 +101,7 @@ class Chip:
89
101
  longer be used after this method is called.
90
102
  """
91
103
  self._check_closed()
92
- self._chip.close()
104
+ cast(_ext.Chip, self._chip).close()
93
105
  self._chip = None
94
106
 
95
107
  def get_info(self) -> ChipInfo:
@@ -102,7 +114,7 @@ class Chip:
102
114
  self._check_closed()
103
115
 
104
116
  if not self._info:
105
- self._info = self._chip.get_info()
117
+ self._info = cast(_ext.Chip, self._chip).get_info()
106
118
 
107
119
  return self._info
108
120
 
@@ -127,7 +139,7 @@ class Chip:
127
139
 
128
140
  if not isinstance(id, int):
129
141
  try:
130
- return self._chip.line_offset_from_id(id)
142
+ return cast(_ext.Chip, self._chip).line_offset_from_id(id)
131
143
  except OSError as ex:
132
144
  if ex.errno == ENOENT:
133
145
  try:
@@ -146,7 +158,9 @@ class Chip:
146
158
 
147
159
  def _get_line_info(self, line: Union[int, str], watch: bool) -> LineInfo:
148
160
  self._check_closed()
149
- return self._chip.get_line_info(self.line_offset_from_id(line), watch)
161
+ return cast(_ext.Chip, self._chip).get_line_info(
162
+ self.line_offset_from_id(line), watch
163
+ )
150
164
 
151
165
  def get_line_info(self, line: Union[int, str]) -> LineInfo:
152
166
  """
@@ -184,7 +198,9 @@ class Chip:
184
198
  Offset or name of the line to stop watching.
185
199
  """
186
200
  self._check_closed()
187
- return self._chip.unwatch_line_info(self.line_offset_from_id(line))
201
+ return cast(_ext.Chip, self._chip).unwatch_line_info(
202
+ self.line_offset_from_id(line)
203
+ )
188
204
 
189
205
  def wait_info_event(
190
206
  self, timeout: Optional[Union[timedelta, float]] = None
@@ -218,11 +234,13 @@ class Chip:
218
234
  This function may block if there are no available events in the queue.
219
235
  """
220
236
  self._check_closed()
221
- return self._chip.read_info_event()
237
+ return cast(_ext.Chip, self._chip).read_info_event()
222
238
 
223
239
  def request_lines(
224
240
  self,
225
- config: dict[tuple[Union[int, str]], Optional[LineSettings]],
241
+ config: dict[
242
+ Union[Iterable[Union[int, str]], int, str], Optional[LineSettings]
243
+ ],
226
244
  consumer: Optional[str] = None,
227
245
  event_buffer_size: Optional[int] = None,
228
246
  output_values: Optional[dict[Union[int, str], Value]] = None,
@@ -251,7 +269,7 @@ class Chip:
251
269
 
252
270
  line_cfg = _ext.LineConfig()
253
271
 
254
- # Sanitize lines - don't allow offset repeatitions or offset-name conflicts.
272
+ # Sanitize lines - don't allow offset repetitions or offset-name conflicts.
255
273
  for offset, count in Counter(
256
274
  [
257
275
  self.line_offset_from_id(line)
@@ -264,9 +282,7 @@ class Chip:
264
282
  ).items():
265
283
  if count != 1:
266
284
  raise ValueError(
267
- "line must be configured exactly once - offset {} repeats".format(
268
- offset
269
- )
285
+ f"line must be configured exactly once - offset {offset} repeats"
270
286
  )
271
287
 
272
288
  # If we have global output values - map line names to offsets
@@ -312,7 +328,9 @@ class Chip:
312
328
  if len(global_output_values):
313
329
  line_cfg.set_output_values(global_output_values)
314
330
 
315
- req_internal = self._chip.request_lines(line_cfg, consumer, event_buffer_size)
331
+ req_internal = cast(_ext.Chip, self._chip).request_lines(
332
+ line_cfg, consumer, event_buffer_size
333
+ )
316
334
  request = LineRequest(req_internal)
317
335
 
318
336
  request._chip_name = req_internal.chip_name
@@ -326,6 +344,12 @@ class Chip:
326
344
 
327
345
  return request
328
346
 
347
+ def fileno(self) -> int:
348
+ """
349
+ Return the underlying file descriptor.
350
+ """
351
+ return self.fd
352
+
329
353
  def __repr__(self) -> str:
330
354
  """
331
355
  Return a string that can be used to re-create this chip object.
@@ -333,7 +357,7 @@ class Chip:
333
357
  if not self._chip:
334
358
  return "<Chip CLOSED>"
335
359
 
336
- return 'gpiod.Chip("{}")'.format(self.path)
360
+ return f'gpiod.Chip("{self.path}")'
337
361
 
338
362
  def __str__(self) -> str:
339
363
  """
@@ -342,9 +366,7 @@ class Chip:
342
366
  if not self._chip:
343
367
  return "<Chip CLOSED>"
344
368
 
345
- return '<Chip path="{}" fd={} info={}>'.format(
346
- self.path, self.fd, self.get_info()
347
- )
369
+ return f'<Chip path="{self.path}" fd={self.fd} info={self.get_info()}>'
348
370
 
349
371
  @property
350
372
  def path(self) -> str:
@@ -352,7 +374,7 @@ class Chip:
352
374
  Filesystem path used to open this chip.
353
375
  """
354
376
  self._check_closed()
355
- return self._chip.path
377
+ return cast(_ext.Chip, self._chip).path
356
378
 
357
379
  @property
358
380
  def fd(self) -> int:
@@ -360,4 +382,4 @@ class Chip:
360
382
  File descriptor associated with this chip.
361
383
  """
362
384
  self._check_closed()
363
- return self._chip.fd
385
+ return cast(_ext.Chip, self._chip).fd
@@ -4,7 +4,7 @@
4
4
 
5
5
  from dataclasses import dataclass
6
6
 
7
- __all__ = "ChipInfo"
7
+ __all__ = ["ChipInfo"]
8
8
 
9
9
 
10
10
  @dataclass(frozen=True, repr=False)
@@ -14,10 +14,13 @@ class ChipInfo:
14
14
  """
15
15
 
16
16
  name: str
17
+ """Name of the chip."""
18
+
17
19
  label: str
20
+ """Label of the chip."""
21
+
18
22
  num_lines: int
23
+ """Number of lines exposed by the chip."""
19
24
 
20
- def __str__(self):
21
- return '<ChipInfo name="{}" label="{}" num_lines={}>'.format(
22
- self.name, self.label, self.num_lines
23
- )
25
+ def __str__(self) -> str:
26
+ return f'<ChipInfo name="{self.name}" label="{self.label}" num_lines={self.num_lines}>'
@@ -1,11 +1,12 @@
1
1
  # SPDX-License-Identifier: LGPL-2.1-or-later
2
2
  # SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
3
3
 
4
- from . import _ext
5
4
  from dataclasses import dataclass
6
5
  from enum import Enum
7
6
 
8
- __all__ = "EdgeEvent"
7
+ from . import _ext
8
+
9
+ __all__ = ["EdgeEvent"]
9
10
 
10
11
 
11
12
  @dataclass(frozen=True, init=False, repr=False)
@@ -15,14 +16,23 @@ class EdgeEvent:
15
16
  """
16
17
 
17
18
  class Type(Enum):
19
+ """Possible edge event types."""
20
+
18
21
  RISING_EDGE = _ext.EDGE_EVENT_TYPE_RISING
22
+ """Rising edge event."""
19
23
  FALLING_EDGE = _ext.EDGE_EVENT_TYPE_FALLING
24
+ """Falling edge event."""
20
25
 
21
26
  event_type: Type
27
+ """Edge event type."""
22
28
  timestamp_ns: int
29
+ """Timestamp of the event in nanoseconds."""
23
30
  line_offset: int
31
+ """Offset of the line on which this event was registered."""
24
32
  global_seqno: int
33
+ """Global sequence number of this event."""
25
34
  line_seqno: int
35
+ """Event sequence number specific to the concerned line."""
26
36
 
27
37
  def __init__(
28
38
  self,
@@ -38,8 +48,8 @@ class EdgeEvent:
38
48
  object.__setattr__(self, "global_seqno", global_seqno)
39
49
  object.__setattr__(self, "line_seqno", line_seqno)
40
50
 
41
- def __str__(self):
42
- return "<EdgeEvent type={} timestamp_ns={} line_offset={} global_seqno={} line_seqno={}>".format(
51
+ def __str__(self) -> str:
52
+ return "<EdgeEvent type={} timestamp_ns={} line_offset={} global_seqno={} line_seqno={}>".format( # noqa: UP032
43
53
  self.event_type,
44
54
  self.timestamp_ns,
45
55
  self.line_offset,