BDPotentiometer 0.2.0__tar.gz → 0.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 (33) hide show
  1. {bdpotentiometer-0.2.0/src/BDPotentiometer.egg-info → bdpotentiometer-0.3.0}/PKG-INFO +2 -3
  2. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/pyproject.toml +3 -4
  3. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/__gpiozero_helpers.py +2 -2
  4. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/__helpers.py +6 -7
  5. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/__init__.py +1 -1
  6. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/__logger.py +2 -3
  7. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/digital_potentiometer.py +38 -39
  8. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/digital_wiper.py +8 -8
  9. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/mcp4xxx/mcp4xx1.py +7 -7
  10. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/mcp4xxx/mcp4xx2.py +7 -7
  11. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/mcp4xxx/mcp4xxx.py +9 -9
  12. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/transport/fake.py +2 -3
  13. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/transport/selection.py +7 -7
  14. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0/src/BDPotentiometer.egg-info}/PKG-INFO +2 -3
  15. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/LICENSE +0 -0
  16. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/README.md +0 -0
  17. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/setup.cfg +0 -0
  18. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/mcp4xxx/__init__.py +0 -0
  19. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/potentiometer.py +0 -0
  20. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/py.typed +0 -0
  21. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/transport/__init__.py +0 -0
  22. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/transport/base.py +0 -0
  23. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/transport/gpiozero_spi.py +0 -0
  24. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer/transport/spidev_spi.py +0 -0
  25. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer.egg-info/SOURCES.txt +0 -0
  26. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer.egg-info/dependency_links.txt +0 -0
  27. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer.egg-info/requires.txt +0 -0
  28. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/src/BDPotentiometer.egg-info/top_level.txt +0 -0
  29. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/tests/test_backward_compatibility.py +0 -0
  30. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/tests/test_gpiozero_helpers.py +0 -0
  31. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/tests/test_logger.py +0 -0
  32. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/tests/test_optional_backends.py +0 -0
  33. {bdpotentiometer-0.2.0 → bdpotentiometer-0.3.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BDPotentiometer
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: BD Digital Potentiometer
5
5
  Author-email: Anton Bondarenko <bond.anton@gmail.com>
6
6
  License: MIT License
@@ -28,13 +28,12 @@ Project-URL: Homepage, https://github.com/bond-anton/BDPotentiometer
28
28
  Project-URL: Bug Tracker, https://github.com/bond-anton/BDPotentiometer/issues
29
29
  Project-URL: Documentation, https://bdpotentiometer.readthedocs.io
30
30
  Classifier: Programming Language :: Python :: 3
31
- Classifier: Programming Language :: Python :: 3.9
32
31
  Classifier: Programming Language :: Python :: 3.10
33
32
  Classifier: Programming Language :: Python :: 3.11
34
33
  Classifier: Programming Language :: Python :: 3.12
35
34
  Classifier: License :: OSI Approved :: MIT License
36
35
  Classifier: Operating System :: OS Independent
37
- Requires-Python: >=3.9
36
+ Requires-Python: >=3.10
38
37
  Description-Content-Type: text/markdown
39
38
  License-File: LICENSE
40
39
  Provides-Extra: gpiozero
@@ -13,14 +13,13 @@ license = { file = "LICENSE" }
13
13
  readme = "README.md"
14
14
  classifiers = [
15
15
  "Programming Language :: Python :: 3",
16
- "Programming Language :: Python :: 3.9",
17
16
  "Programming Language :: Python :: 3.10",
18
17
  "Programming Language :: Python :: 3.11",
19
18
  "Programming Language :: Python :: 3.12",
20
19
  "License :: OSI Approved :: MIT License",
21
20
  "Operating System :: OS Independent",
22
21
  ]
23
- requires-python = ">=3.9"
22
+ requires-python = ">=3.10"
24
23
  dependencies = []
25
24
 
26
25
  [project.urls]
@@ -49,7 +48,7 @@ pythonpath = [
49
48
 
50
49
  [tool.ruff]
51
50
  line-length = 88
52
- target-version = "py39"
51
+ target-version = "py310"
53
52
  extend-exclude = ["docs"]
54
53
 
55
54
  [tool.ruff.lint]
@@ -66,7 +65,7 @@ line-ending = "auto"
66
65
  docstring-code-format = false
67
66
 
68
67
  [tool.ty.environment]
69
- python-version = "3.9"
68
+ python-version = "3.10"
70
69
 
71
70
  [tool.ty.analysis]
72
71
  replace-imports-with-any = ["gpiozero.**", "spidev.**"]
@@ -10,14 +10,14 @@ function is a no-op.
10
10
 
11
11
  import logging
12
12
  import os
13
- from typing import Any, Optional
13
+ from typing import Any
14
14
 
15
15
  _LOGGER = logging.getLogger(__name__)
16
16
 
17
17
  # The factory class installed by the last successful call. It lives at module
18
18
  # scope so a later call can recognize its own factory instead of stacking
19
19
  # another subclass on top of it.
20
- _PATCHED_FACTORY_CLS: Optional[type] = None
20
+ _PATCHED_FACTORY_CLS: type | None = None
21
21
 
22
22
 
23
23
  def _fixed_factory_for(base_factory_cls: type) -> type:
@@ -8,10 +8,9 @@ the requested range.
8
8
 
9
9
  from math import isnan
10
10
  from numbers import Integral, Real
11
- from typing import Union
12
11
 
13
12
 
14
- def check_number(num: Union[float, int, Real]) -> Union[float, int]:
13
+ def check_number(num: float | int | Real) -> float | int:
15
14
  """
16
15
  Check that `num` is a finite real number.
17
16
 
@@ -43,7 +42,7 @@ def check_number(num: Union[float, int, Real]) -> Union[float, int]:
43
42
  return float(num)
44
43
 
45
44
 
46
- def check_integer(num: Union[float, int, Real]) -> int:
45
+ def check_integer(num: float | int | Real) -> int:
47
46
  """
48
47
  Check that `num` is an integer and convert it to int.
49
48
 
@@ -102,7 +101,7 @@ def check_label(value: str) -> str:
102
101
  return text
103
102
 
104
103
 
105
- def check_not_negative(num: Union[float, int]) -> Union[float, int]:
104
+ def check_not_negative(num: float | int) -> float | int:
106
105
  """
107
106
  Check that `num` is a not negative number.
108
107
 
@@ -120,7 +119,7 @@ def check_not_negative(num: Union[float, int]) -> Union[float, int]:
120
119
  return num
121
120
 
122
121
 
123
- def check_positive(num: Union[float, int]) -> Union[float, int]:
122
+ def check_positive(num: float | int) -> float | int:
124
123
  """
125
124
  Check that `num` is a positive number.
126
125
 
@@ -139,8 +138,8 @@ def check_positive(num: Union[float, int]) -> Union[float, int]:
139
138
 
140
139
 
141
140
  def clamp(
142
- value: Union[float, int], min_value: Union[float, int], max_value: Union[float, int]
143
- ) -> Union[float, int]:
141
+ value: float | int, min_value: float | int, max_value: float | int
142
+ ) -> float | int:
144
143
  """
145
144
  Clamp `value` to the range between `min_value` and `max_value`.
146
145
 
@@ -1,6 +1,6 @@
1
1
  """Digital potentiometer and wiper models with pluggable bus transports."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.0"
4
4
 
5
5
 
6
6
  from typing import TYPE_CHECKING, Any
@@ -11,7 +11,6 @@ propagation on the returned logger if that is not wanted.
11
11
 
12
12
  import logging
13
13
  import threading
14
- from typing import Union
15
14
 
16
15
  # Guards handler installation so that two threads calling `get_logger` for the
17
16
  # same label cannot attach two handlers.
@@ -25,7 +24,7 @@ _FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
25
24
  _PACKAGE_HANDLER_ATTR = "_bdpot_package_handler"
26
25
 
27
26
 
28
- def _package_handler(logger: logging.Logger) -> Union[logging.Handler, None]:
27
+ def _package_handler(logger: logging.Logger) -> logging.Handler | None:
29
28
  """Return the handler installed by this module, if it is still attached."""
30
29
  for handler in logger.handlers:
31
30
  if getattr(handler, _PACKAGE_HANDLER_ATTR, False):
@@ -33,7 +32,7 @@ def _package_handler(logger: logging.Logger) -> Union[logging.Handler, None]:
33
32
  return None
34
33
 
35
34
 
36
- def get_logger(label: str, log_level: Union[int, None] = None) -> logging.Logger:
35
+ def get_logger(label: str, log_level: int | None = None) -> logging.Logger:
37
36
  """
38
37
  Return the named logger `label`, configured once.
39
38
 
@@ -1,7 +1,8 @@
1
1
  """Digital potentiometer base class"""
2
2
 
3
3
  import copy
4
- from typing import Any, Callable, Union
4
+ from collections.abc import Callable
5
+ from typing import Any
5
6
 
6
7
  from .__helpers import (
7
8
  check_bool,
@@ -16,7 +17,7 @@ from .digital_wiper import DigitalWiper
16
17
 
17
18
 
18
19
  def _require_sequence(
19
- values: Union[list[Any], tuple[Any, ...]],
20
+ values: list[Any] | tuple[Any, ...],
20
21
  length: int,
21
22
  check: Callable[[Any], Any],
22
23
  ) -> tuple[Any, ...]:
@@ -109,9 +110,7 @@ class DigitalPotentiometerDevice:
109
110
  kwargs.get("label", "DigiPot"), kwargs.get("log_level")
110
111
  )
111
112
 
112
- def _get_channel_number_by_label_or_id(
113
- self, channel: Union[int, str]
114
- ) -> Union[int, None]:
113
+ def _get_channel_number_by_label_or_id(self, channel: int | str) -> int | None:
115
114
  """
116
115
  Look for channel number by label or number provided.
117
116
 
@@ -149,7 +148,7 @@ class DigitalPotentiometerDevice:
149
148
  return None
150
149
 
151
150
  def set_channel_label(
152
- self, channel: Union[int, str] = 0, label: Union[str, None] = None
151
+ self, channel: int | str = 0, label: str | None = None
153
152
  ) -> None:
154
153
  """
155
154
  Assign a string label to a channel.
@@ -201,7 +200,7 @@ class DigitalPotentiometerDevice:
201
200
  """
202
201
  return len(self.__channels)
203
202
 
204
- def set_value(self, channel: Union[int, str] = 0, value: int = 0) -> int:
203
+ def set_value(self, channel: int | str = 0, value: int = 0) -> int:
205
204
  """
206
205
  Method to set the value for a given channel.
207
206
 
@@ -216,7 +215,7 @@ class DigitalPotentiometerDevice:
216
215
  self.logger.debug("Channel %s value is set to %d", channel_id, value)
217
216
  return self.__channels[channel_id].value
218
217
 
219
- def get_value(self, channel: Union[int, str] = 0) -> int:
218
+ def get_value(self, channel: int | str = 0) -> int:
220
219
  """
221
220
  Read value of a given channel.
222
221
 
@@ -238,7 +237,7 @@ class DigitalPotentiometerDevice:
238
237
  return tuple(wiper.value for _, wiper in self.__channels.items())
239
238
 
240
239
  @value.setter
241
- def value(self, value: Union[list[int], tuple[int, ...]]) -> None:
240
+ def value(self, value: list[int] | tuple[int, ...]) -> None:
242
241
  """
243
242
  Set the wiper value for all channels.
244
243
 
@@ -253,7 +252,7 @@ class DigitalPotentiometerDevice:
253
252
  self.__channels[channel_id].value = value[idx]
254
253
  self.logger.debug("Channel %s value is set to %d", channel_id, value[idx])
255
254
 
256
- def set_invert(self, channel: Union[int, str] = 0, invert: bool = False) -> int:
255
+ def set_invert(self, channel: int | str = 0, invert: bool = False) -> int:
257
256
  """
258
257
  Set the invert property for a given channel.
259
258
 
@@ -270,7 +269,7 @@ class DigitalPotentiometerDevice:
270
269
  self.logger.debug("Channel %s invert is set to %s", channel_id, invert)
271
270
  return self.__channels[channel_id].value
272
271
 
273
- def get_invert(self, channel: Union[int, str] = 0) -> bool:
272
+ def get_invert(self, channel: int | str = 0) -> bool:
274
273
  """
275
274
  Get the invert property value for a given channel.
276
275
 
@@ -292,7 +291,7 @@ class DigitalPotentiometerDevice:
292
291
  return tuple(wiper.invert for _, wiper in self.__channels.items())
293
292
 
294
293
  @invert.setter
295
- def invert(self, invert: Union[list[bool], tuple[bool, ...]]) -> None:
294
+ def invert(self, invert: list[bool] | tuple[bool, ...]) -> None:
296
295
  """
297
296
  Set the invert property for all channels.
298
297
 
@@ -306,7 +305,7 @@ class DigitalPotentiometerDevice:
306
305
  self.__channels[channel_id].invert = invert[idx]
307
306
  self.logger.debug("Channel %s invert is set to %s", channel_id, invert[idx])
308
307
 
309
- def set_r_wb(self, channel: Union[int, str] = 0, resistance: float = 0) -> int:
308
+ def set_r_wb(self, channel: int | str = 0, resistance: float = 0) -> int:
310
309
  """
311
310
  Set the resistance for given channel between B and W terminals
312
311
  as close as possible to requested value.
@@ -322,7 +321,7 @@ class DigitalPotentiometerDevice:
322
321
  self.logger.debug("Channel %s r_wb is set to %s", channel_id, resistance)
323
322
  return self.__channels[channel_id].value
324
323
 
325
- def get_r_wb(self, channel: Union[int, str] = 0) -> float:
324
+ def get_r_wb(self, channel: int | str = 0) -> float:
326
325
  """
327
326
  Get the resistance for given channel between B and W terminals.
328
327
 
@@ -344,7 +343,7 @@ class DigitalPotentiometerDevice:
344
343
  return tuple(wiper.r_wb for _, wiper in self.__channels.items())
345
344
 
346
345
  @r_wb.setter
347
- def r_wb(self, resistance_wb: Union[list[float], tuple[float, ...]]) -> None:
346
+ def r_wb(self, resistance_wb: list[float] | tuple[float, ...]) -> None:
348
347
  """
349
348
  Set the B-W resistance for all channels.
350
349
 
@@ -363,7 +362,7 @@ class DigitalPotentiometerDevice:
363
362
  "Channel %s r_wb is set to %s", channel_id, resistance_wb[idx]
364
363
  )
365
364
 
366
- def set_r_wa(self, channel: Union[int, str] = 0, resistance: float = 0) -> int:
365
+ def set_r_wa(self, channel: int | str = 0, resistance: float = 0) -> int:
367
366
  """
368
367
  Set the resistance for given channel between A and W terminals
369
368
  as close as possible to requested value.
@@ -379,7 +378,7 @@ class DigitalPotentiometerDevice:
379
378
  self.logger.debug("Channel %s r_wa is set to %s", channel_id, resistance)
380
379
  return self.__channels[channel_id].value
381
380
 
382
- def get_r_wa(self, channel: Union[int, str] = 0) -> float:
381
+ def get_r_wa(self, channel: int | str = 0) -> float:
383
382
  """
384
383
  Get the resistance for given channel between A and W terminals.
385
384
 
@@ -401,7 +400,7 @@ class DigitalPotentiometerDevice:
401
400
  return tuple(wiper.r_wa for _, wiper in self.__channels.items())
402
401
 
403
402
  @r_wa.setter
404
- def r_wa(self, resistance_wa: Union[list[float], tuple[float, ...]]) -> None:
403
+ def r_wa(self, resistance_wa: list[float] | tuple[float, ...]) -> None:
405
404
  """
406
405
  Set the A-W resistance for all channels.
407
406
 
@@ -420,7 +419,7 @@ class DigitalPotentiometerDevice:
420
419
  "Channel %s r_wa is set to %s", channel_id, resistance_wa[idx]
421
420
  )
422
421
 
423
- def set_r_a(self, channel: Union[int, str] = 0, resistance: float = 0) -> int:
422
+ def set_r_a(self, channel: int | str = 0, resistance: float = 0) -> int:
424
423
  """
425
424
  Set the resistance of the A terminal (this can be current limiting resistor).
426
425
 
@@ -435,7 +434,7 @@ class DigitalPotentiometerDevice:
435
434
  self.logger.debug("Channel %s r_a is set to %s", channel_id, resistance)
436
435
  return self.__channels[channel_id].value
437
436
 
438
- def get_r_a(self, channel: Union[int, str] = 0) -> float:
437
+ def get_r_a(self, channel: int | str = 0) -> float:
439
438
  """
440
439
  Get the resistance of the A terminal for a given channel.
441
440
 
@@ -453,7 +452,7 @@ class DigitalPotentiometerDevice:
453
452
  return tuple(wiper.potentiometer.r_a for _, wiper in self.__channels.items())
454
453
 
455
454
  @r_a.setter
456
- def r_a(self, resistance_a: Union[list[float], tuple[float, ...]]) -> None:
455
+ def r_a(self, resistance_a: list[float] | tuple[float, ...]) -> None:
457
456
  """
458
457
  Set the A-terminal resistance for all channels.
459
458
 
@@ -472,7 +471,7 @@ class DigitalPotentiometerDevice:
472
471
  "Channel %s r_a is set to %s", channel_id, resistance_a[idx]
473
472
  )
474
473
 
475
- def set_r_b(self, channel: Union[int, str] = 0, resistance: float = 0) -> int:
474
+ def set_r_b(self, channel: int | str = 0, resistance: float = 0) -> int:
476
475
  """
477
476
  Set the resistance of the B terminal (this can be current limiting resistor).
478
477
 
@@ -487,7 +486,7 @@ class DigitalPotentiometerDevice:
487
486
  self.logger.debug("Channel %s r_b is set to %s", channel_id, resistance)
488
487
  return self.__channels[channel_id].value
489
488
 
490
- def get_r_b(self, channel: Union[int, str] = 0) -> float:
489
+ def get_r_b(self, channel: int | str = 0) -> float:
491
490
  """
492
491
  Get the resistance of the B terminal for a given channel.
493
492
 
@@ -505,7 +504,7 @@ class DigitalPotentiometerDevice:
505
504
  return tuple(wiper.potentiometer.r_b for _, wiper in self.__channels.items())
506
505
 
507
506
  @r_b.setter
508
- def r_b(self, resistance_b: Union[list[float], tuple[float, ...]]) -> None:
507
+ def r_b(self, resistance_b: list[float] | tuple[float, ...]) -> None:
509
508
  """
510
509
  Set the B-terminal resistance for all channels.
511
510
 
@@ -524,7 +523,7 @@ class DigitalPotentiometerDevice:
524
523
  "Channel %s r_b is set to %s", channel_id, resistance_b[idx]
525
524
  )
526
525
 
527
- def set_r_load(self, channel: Union[int, str] = 0, resistance: float = 0) -> int:
526
+ def set_r_load(self, channel: int | str = 0, resistance: float = 0) -> int:
528
527
  """
529
528
  Set the load resistance for a given channel.
530
529
 
@@ -539,7 +538,7 @@ class DigitalPotentiometerDevice:
539
538
  self.logger.debug("Channel %s r_load is set to %s", channel_id, resistance)
540
539
  return self.__channels[channel_id].value
541
540
 
542
- def get_r_load(self, channel: Union[int, str] = 0) -> float:
541
+ def get_r_load(self, channel: int | str = 0) -> float:
543
542
  """
544
543
  Get the load resistance for a given channel.
545
544
 
@@ -557,7 +556,7 @@ class DigitalPotentiometerDevice:
557
556
  return tuple(wiper.potentiometer.r_load for _, wiper in self.__channels.items())
558
557
 
559
558
  @r_load.setter
560
- def r_load(self, resistance_l: Union[list[float], tuple[float, ...]]) -> None:
559
+ def r_load(self, resistance_l: list[float] | tuple[float, ...]) -> None:
561
560
  """
562
561
  Set the load resistance for all channels.
563
562
 
@@ -576,7 +575,7 @@ class DigitalPotentiometerDevice:
576
575
  "Channel %s r_load is set to %s", channel_id, resistance_l[idx]
577
576
  )
578
577
 
579
- def set_v_a(self, channel: Union[int, str] = 0, voltage: float = 0) -> float:
578
+ def set_v_a(self, channel: int | str = 0, voltage: float = 0) -> float:
580
579
  """
581
580
  Set the terminal A voltage for a given channel.
582
581
 
@@ -591,7 +590,7 @@ class DigitalPotentiometerDevice:
591
590
  self.logger.debug("Channel %s v_a is set to %s", channel_id, voltage)
592
591
  return self.__channels[channel_id].potentiometer.v_a
593
592
 
594
- def get_v_a(self, channel: Union[int, str] = 0) -> float:
593
+ def get_v_a(self, channel: int | str = 0) -> float:
595
594
  """
596
595
  Get the terminal A voltage for a given channel.
597
596
 
@@ -609,7 +608,7 @@ class DigitalPotentiometerDevice:
609
608
  return tuple(wiper.potentiometer.v_a for _, wiper in self.__channels.items())
610
609
 
611
610
  @v_a.setter
612
- def v_a(self, voltage_a: Union[list[float], tuple[float, ...]]) -> None:
611
+ def v_a(self, voltage_a: list[float] | tuple[float, ...]) -> None:
613
612
  """
614
613
  Set the A-terminal voltage for all channels.
615
614
 
@@ -624,7 +623,7 @@ class DigitalPotentiometerDevice:
624
623
  self.__channels[channel_id].potentiometer.v_a = voltage_a[idx]
625
624
  self.logger.debug("Channel %s v_a is set to %s", channel_id, voltage_a[idx])
626
625
 
627
- def set_v_b(self, channel: Union[int, str] = 0, voltage: float = 0) -> float:
626
+ def set_v_b(self, channel: int | str = 0, voltage: float = 0) -> float:
628
627
  """
629
628
  Set the terminal B voltage for a given channel.
630
629
 
@@ -639,7 +638,7 @@ class DigitalPotentiometerDevice:
639
638
  self.logger.debug("Channel %s v_b is set to %s", channel_id, voltage)
640
639
  return self.__channels[channel_id].potentiometer.v_b
641
640
 
642
- def get_v_b(self, channel: Union[int, str] = 0) -> float:
641
+ def get_v_b(self, channel: int | str = 0) -> float:
643
642
  """
644
643
  Get the terminal B voltage for a given channel.
645
644
 
@@ -657,7 +656,7 @@ class DigitalPotentiometerDevice:
657
656
  return tuple(wiper.potentiometer.v_b for _, wiper in self.__channels.items())
658
657
 
659
658
  @v_b.setter
660
- def v_b(self, voltage_b: Union[list[float], tuple[float, ...]]) -> None:
659
+ def v_b(self, voltage_b: list[float] | tuple[float, ...]) -> None:
661
660
  """
662
661
  Set the B-terminal voltage for all channels.
663
662
 
@@ -672,7 +671,7 @@ class DigitalPotentiometerDevice:
672
671
  self.__channels[channel_id].potentiometer.v_b = voltage_b[idx]
673
672
  self.logger.debug("Channel %s v_b is set to %s", channel_id, voltage_b[idx])
674
673
 
675
- def set_v_load(self, channel: Union[int, str] = 0, voltage: float = 0) -> float:
674
+ def set_v_load(self, channel: int | str = 0, voltage: float = 0) -> float:
676
675
  """
677
676
  Set the voltage at the load for a given channel.
678
677
 
@@ -687,7 +686,7 @@ class DigitalPotentiometerDevice:
687
686
  self.logger.debug("Channel %s v_load is set to %s", channel_id, voltage)
688
687
  return self.__channels[channel_id].potentiometer.v_load
689
688
 
690
- def get_v_load(self, channel: Union[int, str] = 0) -> float:
689
+ def get_v_load(self, channel: int | str = 0) -> float:
691
690
  """
692
691
  Get the voltage at the load for a given channel.
693
692
 
@@ -705,7 +704,7 @@ class DigitalPotentiometerDevice:
705
704
  return tuple(wiper.potentiometer.v_load for _, wiper in self.__channels.items())
706
705
 
707
706
  @v_load.setter
708
- def v_load(self, voltage_l: Union[list[float], tuple[float, ...]]) -> None:
707
+ def v_load(self, voltage_l: list[float] | tuple[float, ...]) -> None:
709
708
  """
710
709
  Set the load voltage for all channels.
711
710
 
@@ -722,7 +721,7 @@ class DigitalPotentiometerDevice:
722
721
  "Channel %s v_load is set to %s", channel_id, voltage_l[idx]
723
722
  )
724
723
 
725
- def set_v_w(self, channel: Union[int, str] = 0, voltage: float = 0) -> float:
724
+ def set_v_w(self, channel: int | str = 0, voltage: float = 0) -> float:
726
725
  """
727
726
  Set the terminal W voltage for a given channel.
728
727
 
@@ -737,7 +736,7 @@ class DigitalPotentiometerDevice:
737
736
  self.logger.debug("Channel %s v_w is set to %s", channel_id, voltage)
738
737
  return self.__channels[channel_id].potentiometer.v_w
739
738
 
740
- def get_v_w(self, channel: Union[int, str] = 0) -> float:
739
+ def get_v_w(self, channel: int | str = 0) -> float:
741
740
  """
742
741
  Get the terminal W voltage for a given channel.
743
742
 
@@ -755,7 +754,7 @@ class DigitalPotentiometerDevice:
755
754
  return tuple(wiper.potentiometer.v_w for _, wiper in self.__channels.items())
756
755
 
757
756
  @v_w.setter
758
- def v_w(self, voltage_w: Union[list[float], tuple[float, ...]]) -> None:
757
+ def v_w(self, voltage_w: list[float] | tuple[float, ...]) -> None:
759
758
  """
760
759
  Set the W-terminal voltage for all channels.
761
760
 
@@ -1,7 +1,7 @@
1
1
  """Module contains basic digital wiper class implementation"""
2
2
 
3
3
  from copy import deepcopy
4
- from typing import Union, cast
4
+ from typing import cast
5
5
 
6
6
  from .__helpers import (
7
7
  check_bool,
@@ -349,10 +349,10 @@ class SpiDigitalWiper(DigitalWiper):
349
349
  def __init__(
350
350
  self,
351
351
  potentiometer: Potentiometer,
352
- spi: Union[SpiTransport, None] = None,
352
+ spi: SpiTransport | None = None,
353
353
  max_value: int = 128,
354
354
  invert: bool = False,
355
- transport: Union[SpiTransport, None] = None,
355
+ transport: SpiTransport | None = None,
356
356
  **kwargs,
357
357
  ):
358
358
  """
@@ -380,7 +380,7 @@ class SpiDigitalWiper(DigitalWiper):
380
380
  )
381
381
 
382
382
  @staticmethod
383
- def _resolve_transport(value: object) -> Union[SpiTransport, None]:
383
+ def _resolve_transport(value: object) -> SpiTransport | None:
384
384
  if value is None:
385
385
  return None
386
386
  if is_spi_transport(value):
@@ -393,18 +393,18 @@ class SpiDigitalWiper(DigitalWiper):
393
393
  return self._transport
394
394
 
395
395
  @property
396
- def transport(self) -> Union[SpiTransport, None]:
396
+ def transport(self) -> SpiTransport | None:
397
397
  """Canonical SPI transport; `spi` is a compatibility accessor."""
398
398
  return self._transport
399
399
 
400
400
  @transport.setter
401
- def transport(self, value: Union[SpiTransport, None]) -> None:
401
+ def transport(self, value: SpiTransport | None) -> None:
402
402
  """Set the SPI transport, replacing the current one."""
403
403
  self._transport = self._resolve_transport(value)
404
404
  self.logger.debug("Transport set to %s", self._transport)
405
405
 
406
406
  @property
407
- def spi(self) -> Union[SpiTransport, None]:
407
+ def spi(self) -> SpiTransport | None:
408
408
  """
409
409
  Compatibility accessor for the SPI interface; `transport` is canonical.
410
410
 
@@ -418,7 +418,7 @@ class SpiDigitalWiper(DigitalWiper):
418
418
  return self._transport if raw is None else raw
419
419
 
420
420
  @spi.setter
421
- def spi(self, spi: Union[SpiTransport, None]) -> None:
421
+ def spi(self, spi: SpiTransport | None) -> None:
422
422
  """
423
423
  Compatibility setter for the SPI interface.
424
424
 
@@ -1,6 +1,6 @@
1
1
  """MCP4XX1 series potentiometers"""
2
2
 
3
- from typing import Any, Union
3
+ from typing import Any
4
4
 
5
5
  from .. import DigitalPotentiometerDevice
6
6
  from ..__helpers import check_integer
@@ -90,11 +90,11 @@ class MCP4xx1(DigitalPotentiometerDevice, MCP4xxx):
90
90
  def __init__( # noqa: PLR0913
91
91
  self,
92
92
  r_ab: float = 10e3,
93
- max_value: Union[int, None] = None,
94
- channels: Union[int, None] = None,
93
+ max_value: int | None = None,
94
+ channels: int | None = None,
95
95
  *,
96
- transport: Union[SpiTransport, None] = None,
97
- spi: Union[SpiTransport, None] = None,
96
+ transport: SpiTransport | None = None,
97
+ spi: SpiTransport | None = None,
98
98
  port: Any = None,
99
99
  device: Any = None,
100
100
  clock_pin: Any = None,
@@ -102,8 +102,8 @@ class MCP4xx1(DigitalPotentiometerDevice, MCP4xxx):
102
102
  miso_pin: Any = None,
103
103
  select_pin: Any = None,
104
104
  invert: bool = False,
105
- label: Union[str, None] = None,
106
- log_level: Union[int, str, None] = None,
105
+ label: str | None = None,
106
+ log_level: int | str | None = None,
107
107
  ) -> None:
108
108
  """
109
109
  Build an MCP4XX1 potentiometer device.
@@ -1,6 +1,6 @@
1
1
  """MCP4XX2 series rheostats"""
2
2
 
3
- from typing import Any, Union
3
+ from typing import Any
4
4
 
5
5
  from .. import DigitalPotentiometerDevice
6
6
  from ..__helpers import check_integer
@@ -90,11 +90,11 @@ class MCP4xx2(DigitalPotentiometerDevice, MCP4xxx):
90
90
  def __init__( # noqa: PLR0913
91
91
  self,
92
92
  r_ab: float = 10e3,
93
- max_value: Union[int, None] = None,
94
- channels: Union[int, None] = None,
93
+ max_value: int | None = None,
94
+ channels: int | None = None,
95
95
  *,
96
- transport: Union[SpiTransport, None] = None,
97
- spi: Union[SpiTransport, None] = None,
96
+ transport: SpiTransport | None = None,
97
+ spi: SpiTransport | None = None,
98
98
  port: Any = None,
99
99
  device: Any = None,
100
100
  clock_pin: Any = None,
@@ -102,8 +102,8 @@ class MCP4xx2(DigitalPotentiometerDevice, MCP4xxx):
102
102
  miso_pin: Any = None,
103
103
  select_pin: Any = None,
104
104
  invert: bool = False,
105
- label: Union[str, None] = None,
106
- log_level: Union[int, str, None] = None,
105
+ label: str | None = None,
106
+ log_level: int | str | None = None,
107
107
  ) -> None:
108
108
  """
109
109
  Build an MCP4XX2 rheostat device.
@@ -1,7 +1,7 @@
1
1
  """MCP4XXX series SPI device base class"""
2
2
 
3
3
  from contextlib import suppress
4
- from typing import Any, Union
4
+ from typing import Any
5
5
 
6
6
  from .. import Potentiometer, SpiDigitalWiper
7
7
  from ..__helpers import check_bool, check_integer, clamp
@@ -273,10 +273,10 @@ class MCP4xxxWiper(SpiDigitalWiper):
273
273
  def __init__(
274
274
  self,
275
275
  potentiometer: MCP4xxxPotentiometer,
276
- spi: Union[SpiTransport, None] = None,
276
+ spi: SpiTransport | None = None,
277
277
  max_value: int = 128,
278
278
  invert: bool = False,
279
- transport: Union[SpiTransport, None] = None,
279
+ transport: SpiTransport | None = None,
280
280
  **kwargs,
281
281
  ):
282
282
  """
@@ -356,8 +356,8 @@ class MCP4xxx:
356
356
 
357
357
  def __init__( # noqa: PLR0913
358
358
  self,
359
- transport: Union[SpiTransport, None] = None,
360
- spi: Union[SpiTransport, None] = None,
359
+ transport: SpiTransport | None = None,
360
+ spi: SpiTransport | None = None,
361
361
  *,
362
362
  port: Any = None,
363
363
  device: Any = None,
@@ -420,7 +420,7 @@ class MCP4xxx:
420
420
  "Expected an SPI transport with transfer() and close(), "
421
421
  f"got {type(transport)}"
422
422
  )
423
- self._transport: Union[SpiTransport, None] = transport
423
+ self._transport: SpiTransport | None = transport
424
424
  self._closed = False
425
425
  except Exception:
426
426
  # Only a transport built here is ours to release; a caller-supplied
@@ -431,7 +431,7 @@ class MCP4xxx:
431
431
  raise
432
432
 
433
433
  @property
434
- def transport(self) -> Union[SpiTransport, None]:
434
+ def transport(self) -> SpiTransport | None:
435
435
  """SPI transport used by the device."""
436
436
  return self._transport
437
437
 
@@ -525,8 +525,8 @@ class MCP4xxx:
525
525
 
526
526
  def write_tcon(
527
527
  self,
528
- ch0: Union[dict[str, bool], None] = None,
529
- ch1: Union[dict[str, bool], None] = None,
528
+ ch0: dict[str, bool] | None = None,
529
+ ch1: dict[str, bool] | None = None,
530
530
  ) -> bool:
531
531
  """
532
532
  Write the terminal connection (TCON) state of both channels.
@@ -1,7 +1,6 @@
1
1
  """Scripted SPI transport for tests."""
2
2
 
3
3
  from collections.abc import Sequence
4
- from typing import Optional
5
4
 
6
5
  from .base import TransportClosed, TransportError
7
6
 
@@ -18,8 +17,8 @@ class FakeSpiTransport:
18
17
 
19
18
  def __init__(
20
19
  self,
21
- responses: Optional[list[list[int]]] = None,
22
- default: Optional[list[int]] = None,
20
+ responses: list[list[int]] | None = None,
21
+ default: list[int] | None = None,
23
22
  strict: bool = True,
24
23
  ) -> None:
25
24
  """
@@ -1,6 +1,6 @@
1
1
  """Default SPI backend selection shared by the device constructors."""
2
2
 
3
- from typing import TYPE_CHECKING, Optional
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  if TYPE_CHECKING:
6
6
  from .base import SpiTransport
@@ -29,12 +29,12 @@ GPIOZERO_PIN_ARGS: tuple[str, ...] = (
29
29
 
30
30
  def build_default_transport( # noqa: PLR0913
31
31
  *,
32
- port: Optional[int] = None,
33
- device: Optional[int] = None,
34
- clock_pin: Optional[int] = None,
35
- mosi_pin: Optional[int] = None,
36
- miso_pin: Optional[int] = None,
37
- select_pin: Optional[int] = None,
32
+ port: int | None = None,
33
+ device: int | None = None,
34
+ clock_pin: int | None = None,
35
+ mosi_pin: int | None = None,
36
+ miso_pin: int | None = None,
37
+ select_pin: int | None = None,
38
38
  ) -> "SpiTransport":
39
39
  """
40
40
  Build the default SPI transport from the legacy keyword arguments.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BDPotentiometer
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: BD Digital Potentiometer
5
5
  Author-email: Anton Bondarenko <bond.anton@gmail.com>
6
6
  License: MIT License
@@ -28,13 +28,12 @@ Project-URL: Homepage, https://github.com/bond-anton/BDPotentiometer
28
28
  Project-URL: Bug Tracker, https://github.com/bond-anton/BDPotentiometer/issues
29
29
  Project-URL: Documentation, https://bdpotentiometer.readthedocs.io
30
30
  Classifier: Programming Language :: Python :: 3
31
- Classifier: Programming Language :: Python :: 3.9
32
31
  Classifier: Programming Language :: Python :: 3.10
33
32
  Classifier: Programming Language :: Python :: 3.11
34
33
  Classifier: Programming Language :: Python :: 3.12
35
34
  Classifier: License :: OSI Approved :: MIT License
36
35
  Classifier: Operating System :: OS Independent
37
- Requires-Python: >=3.9
36
+ Requires-Python: >=3.10
38
37
  Description-Content-Type: text/markdown
39
38
  License-File: LICENSE
40
39
  Provides-Extra: gpiozero
File without changes