Skip to content

Commit 6564bd7

Browse files
Release version 3.0.0 (#15)
* Added constants to `ButtonInput` for parameter `action`. Closes #11 * Updated the documentation to version 3.0.0 Resolves #12 * Tested and finalised version 3.0.0
2 parents 1f06d80 + 91bb079 commit 6564bd7

File tree

4 files changed

+129
-96
lines changed

4 files changed

+129
-96
lines changed

button_handler.py

Lines changed: 90 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def ticks_ms() -> int:
4141
except ImportError:
4242
pass
4343

44-
__version__ = "2.0.0"
44+
__version__ = "3.0.0"
4545
__repo__ = "https://github.com/EGJ-Moorington/CircuitPython_Button_Handler.git"
4646

4747
_TICKS_PERIOD = 1 << 29
@@ -73,22 +73,22 @@ def __init__(
7373
) -> None:
7474
"""
7575
:param bool enable_multi_press: Sets :attr:`.enable_multi_press`
76-
(whether to track multi presses).
76+
(whether to track multi-presses).
7777
:param float multi_press_interval: Sets :attr:`.multi_press_interval`
78-
(the time frame within which two presses should occur to count as a multi press).
78+
(the time frame within which two presses should occur to count as a multi-press).
7979
:param float long_press_threshold: Sets :attr:`.long_press_threshold`
8080
(the minimum length of a press to count as a long press).
8181
:param int max_multi_press: Sets :attr:`.max_multi_press`
82-
(the maximum amount of presses a multi press can have).
82+
(the maximum amount of presses a multi-press can have).
8383
8484
.. attribute:: enable_multi_press
8585
:type: bool
8686
:value: enable_multi_press = True
8787
8888
Whether to account for the possibility of another short press
89-
following a short press and counting as a multi press.
89+
following a short press and counting as a multi-press.
9090
If set to false, :meth:`ButtonHandler.update`
91-
returns ``SHORT_PRESS`` immediately after a short press.
91+
returns a short press :class:`ButtonInput` object immediately after a short press.
9292
9393
.. attribute:: long_press_threshold
9494
:type: float
@@ -101,16 +101,16 @@ def __init__(
101101
:type: int
102102
:value: max_multi_press = 2
103103
104-
The maximum amount of button presses that a multi press can be.
105-
:meth:`ButtonHandler.update` returns the appropiate ``_MULTI_PRESS`` immediaetly after
106-
the button has been pressed this many times.
104+
The maximum amount of button presses that a multi-press can be.
105+
:meth:`ButtonHandler.update` returns the appropiate multi-press :class:`ButtonInput`
106+
object immediaetly after the button has been pressed this many times.
107107
108108
.. attribute:: multi_press_interval
109109
:type: float
110110
:value: multi_press_interval = 175
111111
112112
The time frame from a button release within which
113-
another release should occur to count as a multi press.
113+
another release should occur to count as a multi-press.
114114
"""
115115
self.enable_multi_press = enable_multi_press
116116
self.long_press_threshold = long_press_threshold
@@ -137,8 +137,9 @@ def __init__(
137137
:value: config.enable_multi_press = True
138138
139139
Whether to account for the possibility of another short press
140-
following a short press and counting that as a multi press. If set to false,
141-
:meth:`ButtonHandler.update` returns ``SHORT_PRESS`` immediately after a short press.
140+
following a short press and counting that as a multi-press. If set to false,
141+
:meth:`ButtonHandler.update` returns a short press :class:`ButtonInput`
142+
object immediately after a short press.
142143
143144
.. attribute:: long_press_threshold
144145
:type: float
@@ -151,16 +152,16 @@ def __init__(
151152
:type: int
152153
:value: config.max_multi_press = 2
153154
154-
The maximum amount of button presses that a multi press can be.
155-
:meth:`ButtonHandler.update` returns the appropiate ``_MULTI_PRESS`` immediaetly after
156-
the button has been pressed this many times.
155+
The maximum amount of button presses that a multi-press can be.
156+
:meth:`ButtonHandler.update` returns the appropiate multi-press :class:`ButtonInput`
157+
object immediaetly after the button has been pressed this many times.
157158
158159
.. attribute:: multi_press_interval
159160
:type: float
160161
:value: config.multi_press_interval = 175
161162
162163
The time frame from a button release within which
163-
another release should occur to count as a multi press.
164+
another release should occur to count as a multi-press.
164165
165166
.. caution:: Attributes with a *leading underscore (_)* are meant for **internal use only**,
166167
and accessing them may cause **unexpected behaviour**. Please consider accessing
@@ -192,15 +193,15 @@ def __init__(
192193
:value: None
193194
194195
The time (in miliseconds, tracked by :meth:`supervisor.ticks_ms`) that has passed since
195-
the start of the previous press of a multi press. It is set to :type:`None`
196+
the start of the previous press of a multi-press. It is set to :type:`None`
196197
after the time specified by :attr:`.multi_press_interval` has passed.
197198
198199
.. attribute:: _press_count
199200
:type: int
200201
:value: 0
201202
202203
The amount of times the button has been pressed since the last
203-
multi press ended. It is set to 0 if the time set
204+
multi-press ended. It is set to 0 if the time set
204205
by :attr:`.multi_press_interval` passes after a short press.
205206
206207
.. attribute:: _press_start_time
@@ -257,12 +258,12 @@ def _check_multi_press_timeout(self, current_time: int) -> Union[int, None]:
257258
.. caution:: Methods with a *leading underscore (_)* are meant for **internal use only**,
258259
and calling them may cause **unexpected behaviour**. Please refrain from using them.
259260
260-
Check whether a multi press has ended.
261-
If it has, return the amount of times the button was pressed in that multi press.
261+
Check whether a multi-press has ended.
262+
If it has, return the amount of times the button was pressed in that multi-press.
262263
263264
:param int current_time: The current time, provided by :meth:`supervisor.ticks_ms`.
264-
:return: The amount of times the button was pressed in a multi press,
265-
if a multi press has ended.
265+
:return: The amount of times the button was pressed in a multi-press,
266+
if a multi-press has ended.
266267
:rtype: int or None
267268
"""
268269
if (
@@ -301,9 +302,14 @@ def _is_held(self, current_time: int) -> bool:
301302
class ButtonInput:
302303
"""Defines a button's input's characteristics."""
303304

305+
SHORT_PRESS = 1
306+
DOUBLE_PRESS = 2
307+
HOLD = "H"
308+
LONG_PRESS = "L"
309+
304310
def __init__(
305311
self,
306-
action: Union[Literal["SHORT_PRESS", "LONG_PRESS", "HOLD", "DOUBLE_PRESS"], str],
312+
action: Union[int, str],
307313
button_number: int = 0,
308314
callback: Callable[[], None] = lambda: None,
309315
timestamp: int = 0,
@@ -317,7 +323,13 @@ def __init__(
317323
:param int timestamp: Sets :attr:`timestamp` (the time at which the input was performed).
318324
319325
.. type:: InputAction
320-
:canonical: Literal["SHORT_PRESS", "LONG_PRESS", "HOLD", "DOUBLE_PRESS"] | str
326+
:canonical: int | str
327+
328+
Represents the action the :class:`ButtonInput` object represents.
329+
Using a constant defined by :class:`ButtonInput` when available is recommended.
330+
To represent a multi-press, use the number of presses in that multi-press.
331+
Available constants are :const:`SHORT_PRESS`, :const:`DOUBLE_PRESS`,
332+
:const:`HOLD` and :const:`LONG_PRESS`.
321333
322334
.. attribute:: button_number
323335
:type: int
@@ -339,6 +351,37 @@ def __init__(
339351
The timestamp (in milliseconds, provided by :meth:`supervisor.ticks_ms`)
340352
at which the input was performed.
341353
354+
.. warning:: Variables written in *upper case with underscores* are constants and
355+
should not be modified. Doing so may cause **unexpected behaviour**.
356+
357+
.. data:: SHORT_PRESS
358+
:type: int
359+
:value: 1
360+
361+
Represents a short press to pass as an argument to
362+
parameter `action` in :class:`ButtonInput`.
363+
364+
.. data:: DOUBLE_PRESS
365+
:type: int
366+
:value: 2
367+
368+
Represents a double press to pass as an argument to
369+
parameter `action` in :class:`ButtonInput`.
370+
371+
.. data:: HOLD
372+
:type: str
373+
:value: "H"
374+
375+
Represents a hold action to pass as an argument to
376+
parameter `action` in :class:`ButtonInput`.
377+
378+
.. data:: LONG_PRESS
379+
:type: str
380+
:value: "L"
381+
382+
Represents a long press to pass as an argument to
383+
parameter `action` in :class:`ButtonInput`.
384+
342385
.. caution:: Attributes with a *leading underscore (_)* are meant for
343386
**internal use only**, and accessing them may cause **unexpected behaviour**.
344387
Please consider accessing a *property* (if available) instead.
@@ -361,31 +404,23 @@ def action(self):
361404
362405
:type: InputAction
363406
:param InputAction action: The action associated with the input.
364-
:raise ValueError: if action is not a valid action. Valid actions are ``LONG_PRESS``,
365-
``HOLD``, ``SHORT_PRESS`` (exactly the same as ``1_MULTI_PRESS``),
366-
``DOUBLE_PRESS`` (exactly the same as ``2_MULTI_PRESS``) and
367-
``x_MULTI_PRESS`` where x is an :type:`int` bigger than 0.
407+
:raise ValueError: if *action* is not a valid action. Valid actions are
408+
:const:`SHORT_PRESS`, :const:`DOUBLE_PRESS`, :const:`HOLD`, :const:`LONG_PRESS`
409+
and any :type:`int` bigger than 0.
368410
369411
"""
370412
return self._action
371413

372414
@action.setter
373-
def action(
374-
self, action: Union[Literal["SHORT_PRESS", "LONG_PRESS", "HOLD", "DOUBLE_PRESS"], str]
375-
):
376-
if action in {"SHORT_PRESS", "LONG_PRESS", "HOLD"}:
415+
def action(self, action: Union[int, str]):
416+
if action in {ButtonInput.LONG_PRESS, ButtonInput.HOLD}:
377417
self._action = action
378418
return
379419
try:
380-
if action == "DOUBLE_PRESS":
381-
action = "2_MULTI_PRESS"
382-
if not action.endswith("_MULTI_PRESS"):
420+
if not isinstance(action, int):
383421
raise ValueError
384-
num = int(action.split("_")[0])
385-
if num < 1:
422+
if action < 1:
386423
raise ValueError
387-
if num == 1:
388-
action = "SHORT_PRESS"
389424
self._action = action
390425
except ValueError:
391426
raise ValueError(f"Invalid action: {action}.")
@@ -446,15 +481,15 @@ def __init__(
446481
:param keypad.EventQueue event_queue: Sets :attr:`_event_queue`
447482
(the :class:`keypad.EventQueue` object the handler should read events from).
448483
:param set[ButtonInput] callable_inputs: Sets :attr:`callable_inputs`
449-
(the :class:`ButtonInitConfig` objects used to define the callback functions).
484+
(the :class:`ButtonInput` objects used to define the callback functions).
450485
:param int button_amount: The amount of buttons scanned by the :mod:`keypad` scanner
451-
that created the event_queue parameter's argument :class:`keypad.EventQueue` object.
486+
that created the *event_queue* parameter's argument :class:`keypad.EventQueue` object.
452487
:param dict[int, ButtonInitConfig] config: A dictionary containing
453488
:class:`ButtonInitConfig` objects used to initialise :class:`Button` objects.
454489
The dictionary's keys should be the index numbers of the target buttons.
455490
For each button that doesn't have a :class:`ButtonInitConfig` attached to it, an object
456491
containing the default values is created.
457-
:raise ValueError: if *button_amount* is smaller than 1, or if it is not an :type:`int`..
492+
:raise ValueError: if *button_amount* is smaller than 1, or if it is not an :type:`int`.
458493
459494
.. attribute:: callable_inputs
460495
:type: set[ButtonInput]
@@ -507,7 +542,7 @@ def buttons(self) -> list[Button]:
507542

508543
def update(self) -> set[ButtonInput]:
509544
"""
510-
Check if any button ended a multi press since the last time this method was called,
545+
Check if any button ended a multi-press since the last time this method was called,
511546
process the next :class:`keypad.Event` in :attr:`_event_queue`, call all the relevant
512547
callback functions and return a set of the detected :class:`ButtonInput`\\ s.
513548
@@ -553,7 +588,7 @@ def _handle_buttons(self) -> set[ButtonInput]:
553588
and calling them may cause **unexpected behaviour**. Please refrain from using them.
554589
555590
Check if any button began being held down since the last time this mehod was called
556-
and if any multi press ended, and return every detected :class:`ButtonInput`.
591+
and if any multi-press ended, and return every detected :class:`ButtonInput`.
557592
558593
:return: A set containing every detected :class:`ButtonInput`.
559594
:rtype: set[ButtonInput]
@@ -562,15 +597,13 @@ def _handle_buttons(self) -> set[ButtonInput]:
562597
current_time = ticks_ms()
563598
for button in self._buttons:
564599
if button._is_held(current_time):
565-
inputs.add(ButtonInput("HOLD", button.button_number, timestamp=current_time))
600+
inputs.add(
601+
ButtonInput(ButtonInput.HOLD, button.button_number, timestamp=current_time)
602+
)
566603
else:
567604
num = button._check_multi_press_timeout(current_time)
568605
if num:
569-
inputs.add(
570-
ButtonInput(
571-
f"{num}_MULTI_PRESS", button.button_number, timestamp=current_time
572-
)
573-
)
606+
inputs.add(ButtonInput(num, button.button_number, timestamp=current_time))
574607
return inputs
575608

576609
def _handle_event(self, event: Event) -> Union[ButtonInput, None]:
@@ -598,17 +631,21 @@ def _handle_event(self, event: Event) -> Union[ButtonInput, None]:
598631
< button.long_press_threshold
599632
): # Short press
600633
if not button.enable_multi_press:
601-
input_ = ButtonInput("SHORT_PRESS", event.key_number, timestamp=event.timestamp)
634+
input_ = ButtonInput(
635+
ButtonInput.SHORT_PRESS, event.key_number, timestamp=event.timestamp
636+
)
602637
elif button._press_count == button.max_multi_press:
603638
input_ = ButtonInput(
604-
f"{button.max_multi_press}_MULTI_PRESS",
639+
button.max_multi_press,
605640
event.key_number,
606641
timestamp=event.timestamp,
607642
)
608643
else: # More short presses could follow
609644
return None
610645
else:
611-
input_ = ButtonInput("LONG_PRESS", event.key_number, timestamp=event.timestamp)
646+
input_ = ButtonInput(
647+
ButtonInput.LONG_PRESS, event.key_number, timestamp=event.timestamp
648+
)
612649
button._is_holding = False
613650
button._last_press_time = None
614651
button._press_count = 0

examples/button_handler_doublebutton.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ def long_press_1_holding_0():
102102
config = ButtonInitConfig(max_multi_press=3)
103103
scanner = Keys([board.D9, board.A2], value_when_pressed=False)
104104
callback_inputs = {
105-
ButtonInput("DOUBLE_PRESS", 0, double_press_0),
106-
ButtonInput("DOUBLE_PRESS", 1, double_press_1),
107-
ButtonInput("3_MULTI_PRESS", 0, triple_press_0),
108-
ButtonInput("3_MULTI_PRESS", 1, triple_press_1),
109-
ButtonInput("SHORT_PRESS", 0, short_press_0),
110-
ButtonInput("SHORT_PRESS", 1, short_press_1),
111-
ButtonInput("LONG_PRESS", 0, long_press_0),
112-
ButtonInput("LONG_PRESS", 1, long_press_1),
105+
ButtonInput(ButtonInput.DOUBLE_PRESS, 0, double_press_0),
106+
ButtonInput(ButtonInput.DOUBLE_PRESS, 1, double_press_1),
107+
ButtonInput(3, 0, triple_press_0),
108+
ButtonInput(3, 1, triple_press_1),
109+
ButtonInput(ButtonInput.SHORT_PRESS, 0, short_press_0),
110+
ButtonInput(ButtonInput.SHORT_PRESS, 1, short_press_1),
111+
ButtonInput(ButtonInput.LONG_PRESS, 0, long_press_0),
112+
ButtonInput(ButtonInput.LONG_PRESS, 1, long_press_1),
113113
}
114114
button_handler = ButtonHandler(scanner.events, callback_inputs, 2, {0: config, 1: config})
115115

examples/button_handler_singlebutton.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import board
99
from keypad import Keys
1010

11-
from button_handler import ButtonHandler, ButtonInput
11+
from button_handler import ButtonHandler, ButtonInitConfig, ButtonInput
1212

1313

1414
def double_press():
@@ -28,10 +28,10 @@ def hold():
2828

2929

3030
actions = {
31-
ButtonInput("DOUBLE_PRESS", callback=double_press),
32-
ButtonInput("SHORT_PRESS", callback=short_press),
33-
ButtonInput("LONG_PRESS", callback=long_press),
34-
ButtonInput("HOLD", callback=hold),
31+
ButtonInput(ButtonInput.DOUBLE_PRESS, callback=double_press),
32+
ButtonInput(ButtonInput.SHORT_PRESS, callback=short_press),
33+
ButtonInput(ButtonInput.LONG_PRESS, callback=long_press),
34+
ButtonInput(ButtonInput.HOLD, callback=hold),
3535
}
3636

3737
scanner = Keys([board.D9], value_when_pressed=False)

0 commit comments

Comments
 (0)