Skip to content

Commit 4372e84

Browse files
authored
Merge pull request #39 from awordforthat/add-typing
add type hints, restrict return type of monitored callable
2 parents cbc9d38 + 4552414 commit 4372e84

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

adafruit_debouncer.py

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,31 @@
3131
from micropython import const
3232
from adafruit_ticks import ticks_ms, ticks_diff
3333

34-
_DEBOUNCED_STATE = const(0x01)
35-
_UNSTABLE_STATE = const(0x02)
36-
_CHANGED_STATE = const(0x04)
34+
try:
35+
from typing import Callable, Optional, Union
36+
from circuitpython_typing.io import ROValueIO
37+
except ImportError:
38+
pass
3739

38-
_TICKS_PER_SEC = const(1000)
40+
_DEBOUNCED_STATE: int = const(0x01)
41+
_UNSTABLE_STATE: int = const(0x02)
42+
_CHANGED_STATE: int = const(0x04)
43+
44+
_TICKS_PER_SEC: int = const(1000)
3945

4046

4147
class Debouncer:
4248
"""Debounce an input pin or an arbitrary predicate"""
4349

44-
def __init__(self, io_or_predicate, interval=0.010):
50+
def __init__(
51+
self,
52+
io_or_predicate: Union[ROValueIO, Callable[[], bool]],
53+
interval: float = 0.010,
54+
) -> None:
4555
"""Make an instance.
46-
:param DigitalInOut/function io_or_predicate: the DigitalIO or function to debounce
47-
:param int interval: bounce threshold in seconds (default is 0.010, i.e. 10 milliseconds)
56+
:param DigitalInOut/function io_or_predicate: the DigitalIO or
57+
function that returns a boolean to debounce
58+
:param float interval: bounce threshold in seconds (default is 0.010, i.e. 10 milliseconds)
4859
"""
4960
self.state = 0x00
5061
if hasattr(io_or_predicate, "value"):
@@ -59,21 +70,21 @@ def __init__(self, io_or_predicate, interval=0.010):
5970

6071
# Could use the .interval setter, but pylint prefers that we explicitly
6172
# set the real underlying attribute:
62-
self._interval_ticks = interval * _TICKS_PER_SEC
73+
self._interval_ticks = int(interval * _TICKS_PER_SEC)
6374

64-
def _set_state(self, bits):
75+
def _set_state(self, bits: int) -> None:
6576
self.state |= bits
6677

67-
def _unset_state(self, bits):
78+
def _unset_state(self, bits: int) -> None:
6879
self.state &= ~bits
6980

70-
def _toggle_state(self, bits):
81+
def _toggle_state(self, bits: int) -> None:
7182
self.state ^= bits
7283

73-
def _get_state(self, bits):
84+
def _get_state(self, bits: int) -> bool:
7485
return (self.state & bits) != 0
7586

76-
def update(self, new_state=None):
87+
def update(self, new_state: Optional[int] = None) -> None:
7788
"""Update the debouncer state. MUST be called frequently"""
7889
now_ticks = ticks_ms()
7990
self._unset_state(_CHANGED_STATE)
@@ -96,38 +107,38 @@ def update(self, new_state=None):
96107
self._state_changed_ticks = now_ticks
97108

98109
@property
99-
def interval(self):
110+
def interval(self) -> float:
100111
"""The debounce delay, in seconds"""
101112
return self._interval_ticks / _TICKS_PER_SEC
102113

103114
@interval.setter
104-
def interval(self, new_interval_s):
115+
def interval(self, new_interval_s: float) -> None:
105116
self._interval_ticks = new_interval_s * _TICKS_PER_SEC
106117

107118
@property
108-
def value(self):
119+
def value(self) -> bool:
109120
"""Return the current debounced value."""
110121
return self._get_state(_DEBOUNCED_STATE)
111122

112123
@property
113-
def rose(self):
124+
def rose(self) -> bool:
114125
"""Return whether the debounced value went from low to high at the most recent update."""
115126
return self._get_state(_DEBOUNCED_STATE) and self._get_state(_CHANGED_STATE)
116127

117128
@property
118-
def fell(self):
129+
def fell(self) -> bool:
119130
"""Return whether the debounced value went from high to low at the most recent update."""
120131
return (not self._get_state(_DEBOUNCED_STATE)) and self._get_state(
121132
_CHANGED_STATE
122133
)
123134

124135
@property
125-
def last_duration(self):
136+
def last_duration(self) -> float:
126137
"""Return the number of seconds the state was stable prior to the most recent transition."""
127138
return self._last_duration_ticks / _TICKS_PER_SEC
128139

129140
@property
130-
def current_duration(self):
141+
def current_duration(self) -> float:
131142
"""Return the number of seconds since the most recent transition."""
132143
return ticks_diff(ticks_ms(), self._state_changed_ticks) / _TICKS_PER_SEC
133144

@@ -148,12 +159,12 @@ class Button(Debouncer):
148159

149160
def __init__(
150161
self,
151-
pin,
152-
short_duration_ms=200,
153-
long_duration_ms=500,
154-
value_when_pressed=False,
162+
pin: Union[ROValueIO, Callable[[], bool]],
163+
short_duration_ms: int = 200,
164+
long_duration_ms: int = 500,
165+
value_when_pressed: bool = False,
155166
**kwargs
156-
):
167+
) -> None:
157168
self.short_duration_ms = short_duration_ms
158169
self.long_duration_ms = long_duration_ms
159170
self.value_when_pressed = value_when_pressed
@@ -165,20 +176,20 @@ def __init__(
165176
super().__init__(pin, **kwargs)
166177

167178
@property
168-
def pressed(self):
179+
def pressed(self) -> bool:
169180
"""Return whether the button was pressed or not at the last update."""
170181
return (self.value_when_pressed and self.rose) or (
171182
not self.value_when_pressed and self.fell
172183
)
173184

174185
@property
175-
def released(self):
186+
def released(self) -> bool:
176187
"""Return whether the button was release or not at the last update."""
177188
return (self.value_when_pressed and self.fell) or (
178189
not self.value_when_pressed and self.rose
179190
)
180191

181-
def update(self, new_state=None):
192+
def update(self, new_state: Optional[int] = None) -> None:
182193
super().update(new_state)
183194
if self.pressed:
184195
self.last_change_ms = ticks_ms()
@@ -210,12 +221,12 @@ def update(self, new_state=None):
210221
self.short_to_show = 0
211222

212223
@property
213-
def short_count(self):
224+
def short_count(self) -> int:
214225
"""Return the number of short press if a series of short presses has
215226
ended at the last update."""
216227
return self.short_to_show
217228

218229
@property
219-
def long_press(self):
230+
def long_press(self) -> bool:
220231
"""Return whether a long press has occured at the last update."""
221232
return self.long_to_show

0 commit comments

Comments
 (0)