Type annotate kmk_keyboard.py

Update refs from KeyAttrDict to Key in encoder.py
Update types.py for validity
Complete typing of key_validators.py
This commit is contained in:
sofubi 2021-08-16 00:15:09 +00:00
parent 75f9d10cc7
commit 8cb2a8b485
4 changed files with 92 additions and 87 deletions

View File

@ -1,3 +1,5 @@
from typing import List, Optional, Tuple
from kmk.keys import Key
from kmk.types import ( from kmk.types import (
KeySeqSleepMeta, KeySeqSleepMeta,
LayerKeyMeta, LayerKeyMeta,
@ -11,7 +13,7 @@ def key_seq_sleep_validator(ms: float) -> KeySeqSleepMeta:
return KeySeqSleepMeta(ms) return KeySeqSleepMeta(ms)
def layer_key_validator(layer, kc=None): def layer_key_validator(layer: int, kc: Key = None) -> LayerKeyMeta:
''' '''
Validates the syntax (but not semantics) of a layer key call. We won't Validates the syntax (but not semantics) of a layer key call. We won't
have access to the keymap here, so we can't verify much of anything useful have access to the keymap here, so we can't verify much of anything useful
@ -22,16 +24,16 @@ def layer_key_validator(layer, kc=None):
return LayerKeyMeta(layer=layer, kc=kc) return LayerKeyMeta(layer=layer, kc=kc)
def mod_tap_validator(kc, mods=None): def mod_tap_validator(kc: Key, mods: Optional[List[Key]] = None) -> ModTapKeyMeta:
''' '''
Validates that mod tap keys are correctly used Validates that mod tap keys are correctly used
''' '''
return ModTapKeyMeta(kc=kc, mods=mods) return ModTapKeyMeta(kc=kc, mods=mods)
def tap_dance_key_validator(*codes): def tap_dance_key_validator(*codes: Key) -> TapDanceKeyMeta:
return TapDanceKeyMeta(codes) return TapDanceKeyMeta(codes)
def unicode_mode_key_validator(mode): def unicode_mode_key_validator(mode: int) -> UnicodeModeKeyMeta:
return UnicodeModeKeyMeta(mode) return UnicodeModeKeyMeta(mode)

View File

@ -1,73 +1,77 @@
from __future__ import annotations
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
from kmk.consts import KMK_RELEASE, UnicodeMode from kmk.consts import KMK_RELEASE, UnicodeMode
from kmk.hid import BLEHID, USBHID, AbstractHID, HIDModes from kmk.hid import AbstractHID, BLEHID, USBHID, HIDModes
from kmk.keys import KC from kmk.keys import KC, Key, KeyAttrDict
from kmk.kmktime import ticks_ms from kmk.kmktime import ticks_ms
from kmk.matrix import MatrixScanner, intify_coordinate from kmk.matrix import MatrixScanner, intify_coordinate
from kmk.types import TapDanceKeyMeta from kmk.types import TapDanceKeyMeta
class Sandbox: class Sandbox:
matrix_update = None matrix_update: Optional[bytearray] = None
secondary_matrix_update = None secondary_matrix_update: Optional[bytearray] = None
active_layers = None active_layers: Optional[List[int]] = None
class KMKKeyboard: class KMKKeyboard:
##### #####
# User-configurable # User-configurable
debug_enabled = False debug_enabled: bool = False
keymap = [] keymap: List[KeyAttrDict] = []
coord_mapping = None coord_mapping: Optional[List[int]] = None
row_pins = None row_pins: Optional[Tuple[Any, ...]] = None
col_pins = None col_pins: Optional[Tuple[Any, ...]] = None
diode_orientation = None diode_orientation: Optional[int] = None
matrix = None matrix: Optional[MatrixScanner] = None
matrix_scanner = MatrixScanner matrix_scanner: Type[MatrixScanner] = MatrixScanner
uart_buffer = [] uart_buffer: List[Any] = []
unicode_mode = UnicodeMode.NOOP unicode_mode: int = UnicodeMode.NOOP
tap_time = 300 tap_time: int = 300
modules = [] modules: List[Type[Any]] = []
extensions = [] extensions: List[Type[Any]] = []
sandbox = Sandbox() sandbox: Sandbox = Sandbox()
##### #####
# Internal State # Internal State
keys_pressed = set() keys_pressed: Set[Key] = set()
_coordkeys_pressed = {} _coordkeys_pressed: Dict[Any, Any] = {}
hid_type = HIDModes.USB hid_type: int = HIDModes.USB
secondary_hid_type = None secondary_hid_type: Optional[int] = None
_hid_helper = None _hid_helper: Optional[Union[Type[AbstractHID], Type[BLEHID], Type[USBHID]]] = None
hid_pending = False hid_pending: bool = False
state_layer_key = None state_layer_key: Optional[Key] = None
matrix_update = None matrix_update: Optional[Union[bytearray, None]] = None
secondary_matrix_update = None secondary_matrix_update: Optional[Union[bytearray, None]] = None
_matrix_modify = None _matrix_modify: Optional[Any] = None
state_changed = False state_changed: bool = False
_old_timeouts_len = None _old_timeouts_len: Optional[int] = None
_new_timeouts_len = None _new_timeouts_len: Optional[int] = None
_trigger_powersave_enable = False _trigger_powersave_enable: bool = False
_trigger_powersave_disable = False _trigger_powersave_disable: bool = False
i2c_deinit_count = 0 i2c_deinit_count: int = 0
# this should almost always be PREpended to, replaces # this should almost always be PREpended to, replaces
# former use of reversed_active_layers which had pointless # former use of reversed_active_layers which had pointless
# overhead (the underlying list was never used anyway) # overhead (the underlying list was never used anyway)
active_layers = [0] active_layers: List[int] = [0]
_timeouts = {} _timeouts: Dict[float, Callable[[], Key]] = {}
_tapping = False _tapping: bool = False
_tap_dance_counts = {} _tap_dance_counts: Dict[Union[Key, TapDanceKeyMeta], Union[int, None]] = {}
_tap_side_effects = {} _tap_side_effects: Dict[Union[Key, TapDanceKeyMeta], Union[Key, None]] = {}
# on some M4 setups (such as klardotsh/klarank_feather_m4, CircuitPython # on some M4 setups (such as klardotsh/klarank_feather_m4, CircuitPython
# 6.0rc1) this runs out of RAM every cycle and takes down the board. no # 6.0rc1) this runs out of RAM every cycle and takes down the board. no
# real known fix yet other than turning off debug, but M4s have always been # real known fix yet other than turning off debug, but M4s have always been
# tight on RAM so.... # tight on RAM so....
def __repr__(self): def __repr__(self) -> str:
return ( return (
'KMKKeyboard(' 'KMKKeyboard('
'debug_enabled={} ' 'debug_enabled={} '
@ -103,22 +107,22 @@ class KMKKeyboard:
self._tap_side_effects, self._tap_side_effects,
) )
def _print_debug_cycle(self, init=False): def _print_debug_cycle(self, init: bool = False) -> None:
if self.debug_enabled: if self.debug_enabled:
if init: if init:
print('KMKInit(release={})'.format(KMK_RELEASE)) print('KMKInit(release={})'.format(KMK_RELEASE))
print(self) print(self)
def _send_hid(self): def _send_hid(self) -> None:
self._hid_helper.create_report(self.keys_pressed).send() self._hid_helper.create_report(self.keys_pressed).send()
self.hid_pending = False self.hid_pending = False
def _handle_matrix_report(self, update=None): def _handle_matrix_report(self, update: bytearray = None) -> None:
if update is not None: if update is not None:
self._on_matrix_changed(update[0], update[1], update[2]) self._on_matrix_changed(update[0], update[1], update[2])
self.state_changed = True self.state_changed = True
def _find_key_in_map(self, int_coord, row, col): def _find_key_in_map(self, int_coord: int, row: int, col: int) -> Union[Key, None]:
self.state_layer_key = None self.state_layer_key = None
try: try:
idx = self.coord_mapping.index(int_coord) idx = self.coord_mapping.index(int_coord)
@ -143,7 +147,7 @@ class KMKKeyboard:
return self.state_layer_key return self.state_layer_key
def _on_matrix_changed(self, row, col, is_pressed): def _on_matrix_changed(self, row: int, col: int, is_pressed: int) -> KMKKeyboard:
if self.debug_enabled: if self.debug_enabled:
print('MatrixChange(col={} row={} pressed={})'.format(col, row, is_pressed)) print('MatrixChange(col={} row={} pressed={})'.format(col, row, is_pressed))
@ -156,7 +160,7 @@ class KMKKeyboard:
return self.process_key(kc_changed, is_pressed, int_coord, (row, col)) return self.process_key(kc_changed, is_pressed, int_coord, (row, col))
def process_key(self, key, is_pressed, coord_int=None, coord_raw=None): def process_key(self, key: Union[Key, TapDanceKeyMeta], is_pressed: int, coord_int: Optional[int] = None, coord_raw: Tuple[int, int] = None) -> KMKKeyboard:
if self._tapping and not isinstance(key.meta, TapDanceKeyMeta): if self._tapping and not isinstance(key.meta, TapDanceKeyMeta):
self._process_tap_dance(key, is_pressed) self._process_tap_dance(key, is_pressed)
else: else:
@ -167,22 +171,22 @@ class KMKKeyboard:
return self return self
def remove_key(self, keycode): def remove_key(self, keycode: Key) -> KMKKeyboard:
self.keys_pressed.discard(keycode) self.keys_pressed.discard(keycode)
return self.process_key(keycode, False) return self.process_key(keycode, False)
def add_key(self, keycode): def add_key(self, keycode: Key) -> KMKKeyboard:
self.keys_pressed.add(keycode) self.keys_pressed.add(keycode)
return self.process_key(keycode, True) return self.process_key(keycode, True)
def tap_key(self, keycode): def tap_key(self, keycode: Key) -> KMKKeyboard:
self.add_key(keycode) self.add_key(keycode)
# On the next cycle, we'll remove the key. # On the next cycle, we'll remove the key.
self.set_timeout(False, lambda: self.remove_key(keycode)) self.set_timeout(False, lambda: self.remove_key(keycode))
return self return self
def _process_tap_dance(self, changed_key, is_pressed): def _process_tap_dance(self, changed_key: Union[Key, TapDanceKeyMeta], is_pressed: int) -> KMKKeyboard:
if is_pressed: if is_pressed:
if not isinstance(changed_key.meta, TapDanceKeyMeta): if not isinstance(changed_key.meta, TapDanceKeyMeta):
# If we get here, changed_key is not a TapDanceKey and thus # If we get here, changed_key is not a TapDanceKey and thus
@ -219,7 +223,7 @@ class KMKKeyboard:
return self return self
def _end_tap_dance(self, td_key): def _end_tap_dance(self, td_key: Union[Key, TapDanceKeyMeta]) -> KMKKeyboard:
v = self._tap_dance_counts[td_key] - 1 v = self._tap_dance_counts[td_key] - 1
if v >= 0: if v >= 0:
@ -240,12 +244,12 @@ class KMKKeyboard:
return self return self
def _cleanup_tap_dance(self, td_key): def _cleanup_tap_dance(self, td_key: Union[Key, TapDanceKeyMeta]) -> KMKKeyboard:
self._tap_dance_counts[td_key] = 0 self._tap_dance_counts[td_key] = 0
self._tapping = any(count > 0 for count in self._tap_dance_counts.values()) self._tapping = any(count > 0 for count in self._tap_dance_counts.values())
return self return self
def set_timeout(self, after_ticks, callback): def set_timeout(self, after_ticks: float, callback: Callable[[], Key]) -> float:
if after_ticks is False: if after_ticks is False:
# We allow passing False as an implicit "run this on the next process timeouts cycle" # We allow passing False as an implicit "run this on the next process timeouts cycle"
timeout_key = ticks_ms() timeout_key = ticks_ms()
@ -258,11 +262,11 @@ class KMKKeyboard:
self._timeouts[timeout_key] = callback self._timeouts[timeout_key] = callback
return timeout_key return timeout_key
def _cancel_timeout(self, timeout_key): def _cancel_timeout(self, timeout_key: float) -> None:
if timeout_key in self._timeouts: if timeout_key in self._timeouts:
del self._timeouts[timeout_key] del self._timeouts[timeout_key]
def _process_timeouts(self): def _process_timeouts(self) -> KMKKeyboard:
if not self._timeouts: if not self._timeouts:
return self return self
@ -279,7 +283,7 @@ class KMKKeyboard:
return self return self
def _init_sanity_check(self): def _init_sanity_check(self) -> KMKKeyboard:
''' '''
Ensure the provided configuration is *probably* bootable Ensure the provided configuration is *probably* bootable
''' '''
@ -293,7 +297,7 @@ class KMKKeyboard:
return self return self
def _init_coord_mapping(self): def _init_coord_mapping(self) -> None:
''' '''
Attempt to sanely guess a coord_mapping if one is not provided. No-op Attempt to sanely guess a coord_mapping if one is not provided. No-op
if `kmk.extensions.split.Split` is used, it provides equivalent if `kmk.extensions.split.Split` is used, it provides equivalent
@ -315,7 +319,7 @@ class KMKKeyboard:
for cidx in range(cols_to_calc): for cidx in range(cols_to_calc):
self.coord_mapping.append(intify_coordinate(ridx, cidx)) self.coord_mapping.append(intify_coordinate(ridx, cidx))
def _init_hid(self): def _init_hid(self) -> None:
if self.hid_type == HIDModes.NOOP: if self.hid_type == HIDModes.NOOP:
self._hid_helper = AbstractHID self._hid_helper = AbstractHID
elif self.hid_type == HIDModes.USB: elif self.hid_type == HIDModes.USB:
@ -326,7 +330,7 @@ class KMKKeyboard:
self._hid_helper = AbstractHID self._hid_helper = AbstractHID
self._hid_helper = self._hid_helper() self._hid_helper = self._hid_helper()
def _init_matrix(self): def _init_matrix(self) -> KMKKeyboard:
self.matrix = MatrixScanner( self.matrix = MatrixScanner(
cols=self.col_pins, cols=self.col_pins,
rows=self.row_pins, rows=self.row_pins,
@ -336,7 +340,7 @@ class KMKKeyboard:
return self return self
def before_matrix_scan(self): def before_matrix_scan(self) -> None:
for module in self.modules: for module in self.modules:
try: try:
module.before_matrix_scan(self) module.before_matrix_scan(self)
@ -351,7 +355,7 @@ class KMKKeyboard:
if self.debug_enabled: if self.debug_enabled:
print('Failed to run pre matrix function in extension: ', err, ext) print('Failed to run pre matrix function in extension: ', err, ext)
def after_matrix_scan(self): def after_matrix_scan(self) -> None:
for module in self.modules: for module in self.modules:
try: try:
module.after_matrix_scan(self) module.after_matrix_scan(self)
@ -366,7 +370,7 @@ class KMKKeyboard:
if self.debug_enabled: if self.debug_enabled:
print('Failed to run post matrix function in extension: ', err, ext) print('Failed to run post matrix function in extension: ', err, ext)
def before_hid_send(self): def before_hid_send(self) -> None:
for module in self.modules: for module in self.modules:
try: try:
module.before_hid_send(self) module.before_hid_send(self)
@ -381,7 +385,7 @@ class KMKKeyboard:
if self.debug_enabled: if self.debug_enabled:
print('Failed to run pre hid function in extension: ', err, ext) print('Failed to run pre hid function in extension: ', err, ext)
def after_hid_send(self): def after_hid_send(self) -> None:
for module in self.modules: for module in self.modules:
try: try:
module.after_hid_send(self) module.after_hid_send(self)
@ -396,7 +400,7 @@ class KMKKeyboard:
if self.debug_enabled: if self.debug_enabled:
print('Failed to run post hid function in extension: ', err, ext) print('Failed to run post hid function in extension: ', err, ext)
def powersave_enable(self): def powersave_enable(self) -> None:
for module in self.modules: for module in self.modules:
try: try:
module.on_powersave_enable(self) module.on_powersave_enable(self)
@ -411,7 +415,7 @@ class KMKKeyboard:
if self.debug_enabled: if self.debug_enabled:
print('Failed to run post hid function in extension: ', err, ext) print('Failed to run post hid function in extension: ', err, ext)
def powersave_disable(self): def powersave_disable(self) -> None:
for module in self.modules: for module in self.modules:
try: try:
module.on_powersave_disable(self) module.on_powersave_disable(self)
@ -425,7 +429,7 @@ class KMKKeyboard:
if self.debug_enabled: if self.debug_enabled:
print('Failed to run post hid function in extension: ', err, ext) print('Failed to run post hid function in extension: ', err, ext)
def go(self, hid_type=HIDModes.USB, secondary_hid_type=None, **kwargs): def go(self, hid_type: int = HIDModes.USB, secondary_hid_type: Optional[int] = None, **kwargs: Dict[Any, Any]) -> None:
self.hid_type = hid_type self.hid_type = hid_type
self.secondary_hid_type = secondary_hid_type self.secondary_hid_type = secondary_hid_type

View File

@ -2,14 +2,14 @@ import digitalio
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
from kmk.keys import KeyAttrDict from kmk.keys import Key
from kmk.kmk_keyboard import KMKKeyboard from kmk.kmk_keyboard import KMKKeyboard
from kmk.kmktime import ticks_ms from kmk.kmktime import ticks_ms
from kmk.modules import Module from kmk.modules import Module
EncoderMap = Tuple[ EncoderMap = Tuple[
List[Tuple[KeyAttrDict, KeyAttrDict, int]], List[Tuple[Key, Key, int]],
List[Tuple[KeyAttrDict, KeyAttrDict, int]], List[Tuple[Key, Key, int]],
List[Tuple[None, None, int]], List[Tuple[None, None, int]],
] ]

View File

@ -1,7 +1,6 @@
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from kmk.consts import UnicodeMode from kmk.keys import Key
from kmk.keys import KeyAttrDict
class AttrDict(dict): class AttrDict(dict):
@ -18,20 +17,20 @@ class AttrDict(dict):
class LayerKeyMeta: class LayerKeyMeta:
def __init__(self, layer: int, kc: Optional[KeyAttrDict] = None) -> None: def __init__(self, layer: int, kc: Optional[Key] = None) -> None:
self.layer: int = layer self.layer: int = layer
self.kc: Optional[KeyAttrDict] = kc self.kc: Optional[Key] = kc
class ModTapKeyMeta: class ModTapKeyMeta:
def __init__(self, kc: Optional[KeyAttrDict] = None, mods: Optional[List[KeyAttrDict]] = None) -> None: def __init__(self, kc: Optional[Key] = None, mods: Optional[List[Key]] = None) -> None:
self.mods: Optional[List[KeyAttrDict]] = mods self.mods: Optional[List[Key]] = mods
self.kc: Optional[KeyAttrDict] = kc self.kc: Optional[Key] = kc
class KeySequenceMeta: class KeySequenceMeta:
def __init__(self, seq: List[KeyAttrDict]): def __init__(self, seq: List[Key]):
self.seq: List[KeyAttrDict] = seq self.seq: List[Key] = seq
class KeySeqSleepMeta: class KeySeqSleepMeta:
@ -40,10 +39,10 @@ class KeySeqSleepMeta:
class UnicodeModeKeyMeta: class UnicodeModeKeyMeta:
def __init__(self, mode: UnicodeMode): def __init__(self, mode: int):
self.mode = mode self.mode: int = mode
class TapDanceKeyMeta: class TapDanceKeyMeta:
def __init__(self, codes: Tuple[KeyAttrDict, ...]): def __init__(self, codes: Tuple[Key, ...]):
self.codes = codes self.codes: Tuple[Key, ...] = codes