Reformat type hints to use comment style syntax
Update Pipfile to add typing module and pyright Update pyproject.toml for pyright and mypy configs
This commit is contained in:
@@ -11,3 +11,17 @@ class UnicodeMode:
|
||||
LINUX = IBUS = const(1)
|
||||
MACOS = OSX = RALT = const(2)
|
||||
WINC = const(3)
|
||||
|
||||
|
||||
TYPING_PLATFORMS = [
|
||||
'linux',
|
||||
'linux2',
|
||||
'win32',
|
||||
'cygwin',
|
||||
'msys',
|
||||
'darwin',
|
||||
'freebsd7',
|
||||
'freebsd8',
|
||||
'freebsdN',
|
||||
'openbsd6',
|
||||
]
|
||||
|
@@ -1,16 +1,21 @@
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
|
||||
|
||||
class InvalidExtensionEnvironment(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Extension:
|
||||
_enabled = True
|
||||
_enabled = True # type: bool
|
||||
|
||||
def enable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
self._enabled = True
|
||||
|
||||
self.on_runtime_enable(keyboard)
|
||||
|
||||
def disable(self, keyboard):
|
||||
# type (KMKKeyboard) -> None
|
||||
self._enabled = False
|
||||
|
||||
self.on_runtime_disable(keyboard)
|
||||
@@ -18,34 +23,43 @@ class Extension:
|
||||
# The below methods should be implemented by subclasses
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
'''
|
||||
Return value will be injected as an extra matrix update
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
'''
|
||||
Return value will be replace matrix update if supplied
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def on_powersave_disable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
@@ -1,6 +1,7 @@
|
||||
'''Adds international keys'''
|
||||
from kmk.extensions import Extension
|
||||
from kmk.keys import make_key
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
|
||||
|
||||
class International(Extension):
|
||||
@@ -32,28 +33,37 @@ class International(Extension):
|
||||
make_key(code=152, names=('LANG9',))
|
||||
|
||||
def on_runtime_enable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def during_bootup(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def before_hid_send(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def after_hid_send(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def on_powersave_enable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def on_powersave_disable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
@@ -1,23 +1,29 @@
|
||||
from typing import Any, Optional
|
||||
import sys
|
||||
|
||||
from kmk.keys import Key, KeyAttrDict
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.consts import TYPING_PLATFORMS
|
||||
from kmk.kmktime import sleep_ms
|
||||
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import Any, Optional
|
||||
|
||||
from kmk.keys import Key, KeyAttrDict
|
||||
from kmk.kmk_keyboard import KMKKeyboard # Avoid cyclical imports
|
||||
|
||||
|
||||
def passthrough(key, keyboard, *args, **kwargs):
|
||||
return keyboard
|
||||
|
||||
|
||||
def default_pressed(
|
||||
key: Key,
|
||||
keyboard: KMKKeyboard,
|
||||
KC: KeyAttrDict,
|
||||
coord_int: Optional[int] = None,
|
||||
coord_raw: Optional[str] = None,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> KMKKeyboard:
|
||||
key, # type: Key
|
||||
keyboard, # type: KMKKeyboard
|
||||
KC, # type: KeyAttrDict
|
||||
coord_int=None, # type: Optional[int]
|
||||
coord_raw=None, # type: Optional[str]
|
||||
*args, # type: Any
|
||||
**kwargs, # type: Any
|
||||
):
|
||||
# type: (...) -> KMKKeyboard
|
||||
keyboard.hid_pending = True
|
||||
|
||||
if coord_int is not None:
|
||||
@@ -29,14 +35,15 @@ def default_pressed(
|
||||
|
||||
|
||||
def default_released(
|
||||
key: Key,
|
||||
keyboard: KMKKeyboard,
|
||||
KC: KeyAttrDict,
|
||||
coord_int: Optional[int] = None,
|
||||
coord_raw: Optional[str] = None,
|
||||
*args: Any,
|
||||
**kwargs: Any, # NOQA
|
||||
key, # type: Key
|
||||
keyboard, # type: KMKKeyboard
|
||||
KC, # type: KeyAttrDict
|
||||
coord_int=None, # type: Optional[int]
|
||||
coord_raw=None, # type: Optional[str]
|
||||
*args, # type: Any
|
||||
**kwargs, # type: Any # NOQA
|
||||
):
|
||||
# type: (...) -> KMKKeyboard
|
||||
keyboard.hid_pending = True
|
||||
keyboard.keys_pressed.discard(key)
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
from typing import List, Optional
|
||||
import sys
|
||||
|
||||
from kmk.keys import Key
|
||||
from kmk.consts import TYPING_PLATFORMS
|
||||
from kmk.types import (
|
||||
KeySeqSleepMeta,
|
||||
LayerKeyMeta,
|
||||
@@ -9,12 +9,20 @@ from kmk.types import (
|
||||
UnicodeModeKeyMeta,
|
||||
)
|
||||
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import List, Optional
|
||||
|
||||
def key_seq_sleep_validator(ms: float) -> KeySeqSleepMeta:
|
||||
# Avoid cyclical imports
|
||||
from kmk.keys import Key
|
||||
|
||||
|
||||
def key_seq_sleep_validator(ms):
|
||||
# type: (float) -> KeySeqSleepMeta
|
||||
return KeySeqSleepMeta(ms)
|
||||
|
||||
|
||||
def layer_key_validator(layer: int, kc: Key = None) -> LayerKeyMeta:
|
||||
def layer_key_validator(layer, kc=None):
|
||||
# type: (int, Optional[Key]) -> LayerKeyMeta
|
||||
'''
|
||||
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
|
||||
@@ -25,16 +33,19 @@ def layer_key_validator(layer: int, kc: Key = None) -> LayerKeyMeta:
|
||||
return LayerKeyMeta(layer=layer, kc=kc)
|
||||
|
||||
|
||||
def mod_tap_validator(kc: Key, mods: Optional[List[Key]] = None) -> ModTapKeyMeta:
|
||||
def mod_tap_validator(kc, mods):
|
||||
# type: (Key, Optional[List[Key]]) -> ModTapKeyMeta
|
||||
'''
|
||||
Validates that mod tap keys are correctly used
|
||||
'''
|
||||
return ModTapKeyMeta(kc=kc, mods=mods)
|
||||
|
||||
|
||||
def tap_dance_key_validator(*codes: Key) -> TapDanceKeyMeta:
|
||||
def tap_dance_key_validator(*codes):
|
||||
# type: (*Key) -> TapDanceKeyMeta
|
||||
return TapDanceKeyMeta(codes)
|
||||
|
||||
|
||||
def unicode_mode_key_validator(mode: int) -> UnicodeModeKeyMeta:
|
||||
def unicode_mode_key_validator(mode):
|
||||
# type: (int) -> UnicodeModeKeyMeta
|
||||
return UnicodeModeKeyMeta(mode)
|
||||
|
253
kmk/keys.py
253
kmk/keys.py
@@ -1,43 +1,37 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import gc
|
||||
from micropython import const
|
||||
|
||||
from typing import Any, Callable, List, Optional, Protocol, Set, Tuple, Union
|
||||
import sys
|
||||
|
||||
import kmk.handlers.stock as handlers
|
||||
from kmk.consts import UnicodeMode
|
||||
from kmk.consts import TYPING_PLATFORMS, UnicodeMode
|
||||
from kmk.key_validators import (
|
||||
key_seq_sleep_validator,
|
||||
tap_dance_key_validator,
|
||||
unicode_mode_key_validator,
|
||||
)
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.types import AttrDict, UnicodeModeKeyMeta
|
||||
|
||||
DEBUG_OUTPUT: bool = False
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import Any, Callable, List, Optional, Set, Tuple, Union
|
||||
|
||||
FIRST_KMK_INTERNAL_KEY: int = const(1000)
|
||||
NEXT_AVAILABLE_KEY: int = 1000
|
||||
# Avoid cyclical imports
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
|
||||
KEY_SIMPLE: int = const(0)
|
||||
KEY_MODIFIER: int = const(1)
|
||||
KEY_CONSUMER: int = const(2)
|
||||
|
||||
ALL_ALPHAS: str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
ALL_NUMBERS: str = '1234567890'
|
||||
DEBUG_OUTPUT = False # type: bool
|
||||
|
||||
FIRST_KMK_INTERNAL_KEY = const(1000) # type: int
|
||||
NEXT_AVAILABLE_KEY = 1000 # type: int
|
||||
|
||||
KEY_SIMPLE = const(0) # type: int
|
||||
KEY_MODIFIER = const(1) # type: int
|
||||
KEY_CONSUMER = const(2) # type: int
|
||||
|
||||
ALL_ALPHAS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' # type: str
|
||||
ALL_NUMBERS = '1234567890' # type: str
|
||||
# since KC.1 isn't valid Python, alias to KC.N1
|
||||
ALL_NUMBER_ALIASES: Tuple[str, ...] = tuple(f'N{x}' for x in ALL_NUMBERS)
|
||||
|
||||
|
||||
KeyReturn = Union[Key, ModifierKey, ConsumerKey, None]
|
||||
|
||||
|
||||
class LeftPipeCallback(Protocol):
|
||||
def __call__(
|
||||
self, candidate: str, code: Union[str, int], names: Tuple[str, ...]
|
||||
) -> KeyReturn:
|
||||
...
|
||||
ALL_NUMBER_ALIASES = tuple(f'N{x}' for x in ALL_NUMBERS) # type: Tuple[str, ...]
|
||||
|
||||
|
||||
class InfiniteLoopDetected(Exception):
|
||||
@@ -47,10 +41,11 @@ class InfiniteLoopDetected(Exception):
|
||||
# this is a bit of an FP style thing - combining a pipe operator a-la F# with
|
||||
# a bootleg Maybe monad to clean up these make_key sequences
|
||||
def left_pipe_until_some(
|
||||
candidate: str,
|
||||
functor: LeftPipeCallback,
|
||||
*args_iter: Tuple[Union[str, int], Tuple[str, ...]],
|
||||
) -> KeyReturn:
|
||||
candidate, # type: str
|
||||
functor, # type: Callable[[str, Union[str, int], Tuple[str, ...]], Optional[Union[Key, ModifierKey, ConsumerKey]]]
|
||||
*args_iter, # type: Tuple[Union[str, int], Tuple[str, ...]]
|
||||
):
|
||||
# type: (...) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
for args in args_iter:
|
||||
result = functor(candidate, *args)
|
||||
if result is not None:
|
||||
@@ -58,41 +53,43 @@ def left_pipe_until_some(
|
||||
|
||||
|
||||
def first_truthy(
|
||||
candidate: str,
|
||||
*funcs: Callable[[str], Union[Key, ModifierKey, ConsumerKey, None]],
|
||||
) -> KeyReturn:
|
||||
candidate, # type: str
|
||||
*funcs, # type: Callable[[str], Union[Key, ModifierKey, ConsumerKey, None]]
|
||||
):
|
||||
# type: (...) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
for func in funcs:
|
||||
result = func(candidate)
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
|
||||
def maybe_make_mod_key(candidate: str, code: int, names: Tuple[str, ...]) -> KeyReturn:
|
||||
def maybe_make_mod_key(candidate, code, names):
|
||||
# type: (str, int, Tuple[str, ...]) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
if candidate in names:
|
||||
return make_mod_key(code=code, names=names)
|
||||
|
||||
|
||||
def maybe_make_key(candidate: str, code: int, names: Tuple[str, ...]) -> KeyReturn:
|
||||
def maybe_make_key(candidate, code, names):
|
||||
# type: (str, int, Tuple[str, ...]) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
if candidate in names:
|
||||
return make_key(code=code, names=names)
|
||||
|
||||
|
||||
def maybe_make_shifted_key(
|
||||
candidate: str, target_name: str, names: Tuple[str, ...]
|
||||
) -> KeyReturn:
|
||||
def maybe_make_shifted_key(candidate, target_name, names):
|
||||
# type: (str, str, Tuple[str, ...]) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
if candidate in names:
|
||||
return make_shifted_key(target_name=target_name, names=names)
|
||||
|
||||
|
||||
def maybe_make_consumer_key(
|
||||
candidate: str, code: int, names: Tuple[str, ...]
|
||||
) -> KeyReturn:
|
||||
def maybe_make_consumer_key(candidate, code, names):
|
||||
# type: (str, int, Tuple[str, ...]) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
if candidate in names:
|
||||
return make_consumer_key(code=code, names=names)
|
||||
|
||||
|
||||
class KeyAttrDict(AttrDict):
|
||||
def __getattr__(self, key: str, depth: int = 0) -> KeyReturn:
|
||||
def __getattr__(self, key, depth=0):
|
||||
# type: (str, int) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
if depth > 1:
|
||||
raise InfiniteLoopDetected()
|
||||
|
||||
@@ -410,54 +407,46 @@ class KeyAttrDict(AttrDict):
|
||||
KC = KeyAttrDict()
|
||||
|
||||
|
||||
class DefaultPressRelease(Protocol):
|
||||
def __call__(
|
||||
self,
|
||||
key: Key,
|
||||
keyboard: KMKKeyboard,
|
||||
KC: KeyAttrDict,
|
||||
coord_int: Optional[int],
|
||||
coord_raw: Optional[str],
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> KMKKeyboard:
|
||||
...
|
||||
|
||||
|
||||
Handler = Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]
|
||||
|
||||
|
||||
HandlerList = List[Handler]
|
||||
|
||||
|
||||
class Key:
|
||||
def __init__(
|
||||
self,
|
||||
code: int,
|
||||
has_modifiers: Optional[Set[int]] = None,
|
||||
no_press: Optional[bool] = False,
|
||||
no_release: Optional[bool] = False,
|
||||
on_press: DefaultPressRelease = handlers.default_pressed,
|
||||
on_release: DefaultPressRelease = handlers.default_released,
|
||||
meta: object = object(),
|
||||
) -> None:
|
||||
self.code: int = code
|
||||
self.has_modifiers: Optional[Set[int]] = has_modifiers
|
||||
code, # type: int
|
||||
has_modifiers=None, # type: Optional[Set[int]]
|
||||
no_press=False, # type: bool
|
||||
no_release=False, # type: bool
|
||||
on_press=handlers.default_pressed, # type: Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]
|
||||
on_release=handlers.default_released, # type: Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]
|
||||
meta=object(), # type: object
|
||||
):
|
||||
# type: (...) -> None
|
||||
self.code = code # type: int
|
||||
self.has_modifiers = has_modifiers # type: Optional[Set[int]]
|
||||
# cast to bool() in case we get a None value
|
||||
self.no_press: bool = bool(no_press)
|
||||
self.no_release: bool = bool(no_press)
|
||||
self.no_press = bool(no_press) # type: bool
|
||||
self.no_release = bool(no_press) # type: bool
|
||||
|
||||
self._pre_press_handlers: HandlerList = []
|
||||
self._post_press_handlers: HandlerList = []
|
||||
self._pre_release_handlers: HandlerList = []
|
||||
self._post_release_handlers: HandlerList = []
|
||||
self._handle_press: DefaultPressRelease = on_press
|
||||
self._handle_release: DefaultPressRelease = on_release
|
||||
self.meta: object = meta
|
||||
self._pre_press_handlers = (
|
||||
[]
|
||||
) # type: List[Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]]
|
||||
self._post_press_handlers = (
|
||||
[]
|
||||
) # type: List[Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]]
|
||||
self._pre_release_handlers = (
|
||||
[]
|
||||
) # type: List[Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]]
|
||||
self._post_release_handlers = (
|
||||
[]
|
||||
) # type: List[Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]]
|
||||
self._handle_press = (
|
||||
on_press
|
||||
) # type: Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]
|
||||
self._handle_release = (
|
||||
on_release
|
||||
) # type: Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]
|
||||
self.meta = meta # type: object
|
||||
|
||||
def __call__(
|
||||
self, no_press: Optional[bool] = None, no_release: Optional[bool] = None
|
||||
) -> Key:
|
||||
def __call__(self, no_press, no_release):
|
||||
# type: (Optional[bool], Optional[bool]) -> Key
|
||||
if no_press is None and no_release is None:
|
||||
return self
|
||||
|
||||
@@ -469,37 +458,43 @@ class Key:
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
# type: () -> str
|
||||
return 'Key(code={}, has_modifiers={})'.format(self.code, self.has_modifiers)
|
||||
|
||||
def on_press(
|
||||
self, state: KMKKeyboard, coord_int: int, coord_raw: str
|
||||
) -> Union[KMKKeyboard, None]:
|
||||
def on_press(self, state, coord_int, coord_raw):
|
||||
# type: (KMKKeyboard, int, str) -> Optional[Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]]
|
||||
for fn in self._pre_press_handlers:
|
||||
if not fn(self, state, KC, coord_int, coord_raw):
|
||||
return None
|
||||
|
||||
ret = self._handle_press(self, state, KC, coord_int, coord_raw)
|
||||
# TODO -- SOFUBI -- look into way to type hint *args and **kwargs of a Callable signature
|
||||
ret = self._handle_press(
|
||||
self, state, KC, coord_int, coord_raw
|
||||
) # type: Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]
|
||||
|
||||
for fn in self._post_press_handlers:
|
||||
fn(self, state, KC, coord_int, coord_raw)
|
||||
|
||||
return ret
|
||||
|
||||
def on_release(
|
||||
self, state: KMKKeyboard, coord_int: int, coord_raw: str
|
||||
) -> Union[KMKKeyboard, None]:
|
||||
def on_release(self, state, coord_int, coord_raw):
|
||||
# type: (KMKKeyboard, int, str) -> Optional[Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]]
|
||||
for fn in self._pre_release_handlers:
|
||||
if not fn(self, state, KC, coord_int, coord_raw):
|
||||
return None
|
||||
|
||||
ret = self._handle_release(self, state, KC, coord_int, coord_raw)
|
||||
# TODO -- SOFUBI -- look into way to type hint *args and **kwargs of a Callable signature
|
||||
ret = self._handle_release(
|
||||
self, state, KC, coord_int, coord_raw
|
||||
) # type: Callable[[Key, KMKKeyboard, KeyAttrDict, Optional[int], Optional[str], Any, Any], KMKKeyboard]
|
||||
|
||||
for fn in self._post_release_handlers:
|
||||
fn(self, state, KC, coord_int, coord_raw)
|
||||
|
||||
return ret
|
||||
|
||||
def clone(self) -> Key:
|
||||
def clone(self):
|
||||
# type: () -> Key
|
||||
'''
|
||||
Return a shallow clone of the current key without any pre/post press/release
|
||||
handlers attached. Almost exclusively useful for creating non-colliding keys
|
||||
@@ -516,7 +511,8 @@ class Key:
|
||||
meta=self.meta,
|
||||
)
|
||||
|
||||
def before_press_handler(self, fn: Handler) -> Key:
|
||||
def before_press_handler(self, fn):
|
||||
# type: (Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]) -> Key
|
||||
'''
|
||||
Attach a callback to be run prior to the on_press handler for this key.
|
||||
Receives the following:
|
||||
@@ -540,7 +536,8 @@ class Key:
|
||||
self._pre_press_handlers.append(fn)
|
||||
return self
|
||||
|
||||
def after_press_handler(self, fn: Handler) -> Key:
|
||||
def after_press_handler(self, fn):
|
||||
# type: (Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]) -> Key
|
||||
'''
|
||||
Attach a callback to be run after the on_release handler for this key.
|
||||
Receives the following:
|
||||
@@ -563,7 +560,8 @@ class Key:
|
||||
self._post_press_handlers.append(fn)
|
||||
return self
|
||||
|
||||
def before_release_handler(self, fn: Handler) -> Key:
|
||||
def before_release_handler(self, fn):
|
||||
# type: (Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]) -> Key
|
||||
'''
|
||||
Attach a callback to be run prior to the on_release handler for this
|
||||
key. Receives the following:
|
||||
@@ -587,7 +585,8 @@ class Key:
|
||||
self._pre_release_handlers.append(fn)
|
||||
return self
|
||||
|
||||
def after_release_handler(self, fn: Handler) -> Key:
|
||||
def after_release_handler(self, fn):
|
||||
# type: (Callable[[Any, KMKKeyboard, KeyAttrDict, int, str], KMKKeyboard]) -> Key
|
||||
'''
|
||||
Attach a callback to be run after the on_release handler for this key.
|
||||
Receives the following:
|
||||
@@ -615,14 +614,15 @@ class ModifierKey(Key):
|
||||
# FIXME this is atrocious to read. Please, please, please, strike down upon
|
||||
# this with great vengeance and furious anger.
|
||||
|
||||
FAKE_CODE: int = const(-1)
|
||||
FAKE_CODE = const(-1) # type: int
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
modified_code: Optional[Key] = None,
|
||||
no_press: Optional[bool] = None,
|
||||
no_release: Optional[bool] = None,
|
||||
) -> Union[Key, ModifierKey]:
|
||||
modified_code=None, # type: Optional[Key]
|
||||
no_press=None, # type: Optional[bool]
|
||||
no_release=None, # type: Optional[bool]
|
||||
):
|
||||
# type: (...) -> Union[Key, ModifierKey]
|
||||
if modified_code is None and no_press is None and no_release is None:
|
||||
return self
|
||||
|
||||
@@ -655,7 +655,8 @@ class ModifierKey(Key):
|
||||
|
||||
return new_keycode
|
||||
|
||||
def __repr__(self) -> str:
|
||||
def __repr__(self):
|
||||
# () -> str
|
||||
return 'ModifierKey(code={}, has_modifiers={})'.format(
|
||||
self.code, self.has_modifiers
|
||||
)
|
||||
@@ -665,7 +666,8 @@ class ConsumerKey(Key):
|
||||
pass
|
||||
|
||||
|
||||
def register_key_names(key: Key, names: Tuple[str, ...] = tuple()): # NOQA
|
||||
def register_key_names(key, names=tuple()): # NOQA
|
||||
# type: (Key, Tuple[str, ...]) -> Key
|
||||
'''
|
||||
Names are globally unique. If a later key is created with
|
||||
the same name as an existing entry in `KC`, it will overwrite
|
||||
@@ -686,12 +688,8 @@ def register_key_names(key: Key, names: Tuple[str, ...] = tuple()): # NOQA
|
||||
return key
|
||||
|
||||
|
||||
def make_key(
|
||||
code: Optional[int] = None,
|
||||
names: Tuple[str, ...] = tuple(),
|
||||
type: int = KEY_SIMPLE,
|
||||
**kwargs: Any,
|
||||
) -> KeyReturn: # NOQA
|
||||
def make_key(code=None, names=tuple(), type=KEY_SIMPLE, **kwargs): # NOQA
|
||||
# type: (Optional[int], Tuple[str, ...], int, **Any) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
'''
|
||||
Create a new key, aliased by `names` in the KC lookup table.
|
||||
|
||||
@@ -733,16 +731,13 @@ def make_key(
|
||||
return key
|
||||
|
||||
|
||||
def make_mod_key(
|
||||
code: Optional[int],
|
||||
names: Tuple[str, ...],
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
):
|
||||
def make_mod_key(code, names, *args, **kwargs):
|
||||
# type: (Optional[int], Tuple[str, ...], *Any, **Any) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
return make_key(code, names, *args, **kwargs, type=KEY_MODIFIER)
|
||||
|
||||
|
||||
def make_shifted_key(target_name, names=tuple()): # NOQA
|
||||
# type: (str, Tuple[str, ...]) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
# For... probably a few years, a bug existed here where keys were looked
|
||||
# up by `KC[...]`, but that's incorrect: an AttrDit exposes a dictionary
|
||||
# with attributes, but key-based dictionary access with brackets does
|
||||
@@ -757,34 +752,28 @@ def make_shifted_key(target_name, names=tuple()): # NOQA
|
||||
return key
|
||||
|
||||
|
||||
def make_consumer_key(*args: Any, **kwargs: Any):
|
||||
def make_consumer_key(*args, **kwargs):
|
||||
# type: (*Any, **Any) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
return make_key(*args, **kwargs, type=KEY_CONSUMER)
|
||||
|
||||
|
||||
class ArgumentedKey(Protocol):
|
||||
def __call__(self, *user_args: Any, **user_kwargs: Any) -> Key:
|
||||
...
|
||||
|
||||
|
||||
class Validator(Protocol):
|
||||
def __call__(self, *validator_args: Any, **validator_kwargs: Any) -> object:
|
||||
...
|
||||
|
||||
|
||||
# Argumented keys are implicitly internal, so auto-gen of code
|
||||
# is almost certainly the best plan here
|
||||
def make_argumented_key(
|
||||
validator: Validator = lambda *validator_args, **validator_kwargs: object(),
|
||||
names: Tuple = tuple(), # NOQA
|
||||
*constructor_args: Any,
|
||||
**constructor_kwargs: Any,
|
||||
) -> Optional[ArgumentedKey]:
|
||||
validator=lambda *validator_args, **validator_kwargs: object(), # type: object
|
||||
names=tuple(), # type: Tuple[str, ...] # NOQA
|
||||
*constructor_args, # type; Any
|
||||
**constructor_kwargs, # type: Any
|
||||
):
|
||||
global NEXT_AVAILABLE_KEY
|
||||
|
||||
def _argumented_key(*user_args: Any, **user_kwargs: Any):
|
||||
def _argumented_key(*user_args, **user_kwargs):
|
||||
# type: (*Any, **Any) -> Union[Key, ModifierKey, ConsumerKey]
|
||||
global NEXT_AVAILABLE_KEY
|
||||
|
||||
meta = validator(*user_args, **user_kwargs)
|
||||
meta = validator(
|
||||
*user_args, **user_kwargs
|
||||
) # type: Callable[[Any, Any], object]
|
||||
|
||||
if meta:
|
||||
key = Key(
|
||||
|
@@ -1,77 +1,80 @@
|
||||
from __future__ import annotations
|
||||
import sys
|
||||
|
||||
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, TYPING_PLATFORMS, UnicodeMode
|
||||
from kmk.hid import BLEHID, USBHID, AbstractHID, HIDModes
|
||||
from kmk.keys import KC, Key, KeyAttrDict
|
||||
from kmk.kmktime import ticks_ms
|
||||
from kmk.matrix import MatrixScanner, intify_coordinate
|
||||
from kmk.types import TapDanceKeyMeta
|
||||
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
|
||||
|
||||
|
||||
class Sandbox:
|
||||
matrix_update: Optional[bytearray] = None
|
||||
secondary_matrix_update: Optional[bytearray] = None
|
||||
active_layers: Optional[List[int]] = None
|
||||
matrix_update = None # type: Optional[bytearray]
|
||||
secondary_matrix_update = None # type: Optional[bytearray]
|
||||
active_layers = None # type: Optional[List[int]]
|
||||
|
||||
|
||||
class KMKKeyboard:
|
||||
#####
|
||||
# User-configurable
|
||||
debug_enabled: bool = False
|
||||
debug_enabled = False # type: bool
|
||||
|
||||
keymap: List[KeyAttrDict] = []
|
||||
coord_mapping: Optional[List[int]] = None
|
||||
keymap = [] # type: List[KeyAttrDict]
|
||||
coord_mapping = None # type: Optional[List[int]]
|
||||
|
||||
row_pins: Optional[Tuple[Any, ...]] = None
|
||||
col_pins: Optional[Tuple[Any, ...]] = None
|
||||
diode_orientation: Optional[int] = None
|
||||
matrix: Optional[MatrixScanner] = None
|
||||
matrix_scanner: Type[MatrixScanner] = MatrixScanner
|
||||
uart_buffer: List[Any] = []
|
||||
row_pins = None # type: Optional[Tuple[Any, ...]]
|
||||
col_pins = None # type: Optional[Tuple[Any, ...]]
|
||||
diode_orientation = None # type: Optional[int]
|
||||
matrix = None # type: Optional[MatrixScanner]
|
||||
matrix_scanner = MatrixScanner # type: Type[MatrixScanner]
|
||||
uart_buffer = [] # type: List[Any]
|
||||
|
||||
unicode_mode: int = UnicodeMode.NOOP
|
||||
tap_time: int = 300
|
||||
unicode_mode = UnicodeMode.NOOP # type: int
|
||||
tap_time = 300 # type: int
|
||||
|
||||
modules: List[Type[Any]] = []
|
||||
extensions: List[Type[Any]] = []
|
||||
sandbox: Sandbox = Sandbox()
|
||||
modules = [] # type: List[Type[Any]]
|
||||
extensions = [] # type: List[Type[Any]]
|
||||
sandbox = Sandbox() # type: Sandbox
|
||||
|
||||
#####
|
||||
# Internal State
|
||||
keys_pressed: Set[Key] = set()
|
||||
_coordkeys_pressed: Dict[Any, Any] = {}
|
||||
hid_type: int = HIDModes.USB
|
||||
secondary_hid_type: Optional[int] = None
|
||||
_hid_helper: Optional[Union[Type[AbstractHID], Type[BLEHID], Type[USBHID]]] = None
|
||||
hid_pending: bool = False
|
||||
state_layer_key: Optional[Key] = None
|
||||
matrix_update: Optional[Union[bytearray, None]] = None
|
||||
secondary_matrix_update: Optional[Union[bytearray, None]] = None
|
||||
_matrix_modify: Optional[Any] = None
|
||||
state_changed: bool = False
|
||||
_old_timeouts_len: Optional[int] = None
|
||||
_new_timeouts_len: Optional[int] = None
|
||||
_trigger_powersave_enable: bool = False
|
||||
_trigger_powersave_disable: bool = False
|
||||
i2c_deinit_count: int = 0
|
||||
keys_pressed = set() # type: Set[Key]
|
||||
_coordkeys_pressed = {} # type: Dict[Any, Any]
|
||||
hid_type = HIDModes.USB # type: int
|
||||
secondary_hid_type = None # type: Optional[int]
|
||||
_hid_helper = (
|
||||
None
|
||||
) # type: Optional[Union[Type[AbstractHID], Type[BLEHID], Type[USBHID]]]
|
||||
hid_pending = False # type: bool
|
||||
state_layer_key = None # type: Optional[Key]
|
||||
matrix_update = None # type: Optional[Union[bytearray, None]]
|
||||
secondary_matrix_update = None # type: Optional[Union[bytearray, None]]
|
||||
_matrix_modify = None # type: Optional[Any]
|
||||
state_changed = False # type: bool
|
||||
_old_timeouts_len = None # type: Optional[int]
|
||||
_new_timeouts_len = None # type: Optional[int]
|
||||
_trigger_powersave_enable = False # type: bool
|
||||
_trigger_powersave_disable = False # type: bool
|
||||
i2c_deinit_count = 0 # type: int
|
||||
|
||||
# this should almost always be PREpended to, replaces
|
||||
# former use of reversed_active_layers which had pointless
|
||||
# overhead (the underlying list was never used anyway)
|
||||
active_layers: List[int] = [0]
|
||||
active_layers = [0] # type: List[int]
|
||||
|
||||
_timeouts: Dict[float, Callable[[], Key]] = {}
|
||||
_tapping: bool = False
|
||||
_tap_dance_counts: Dict[Union[Key, TapDanceKeyMeta], Union[int, None]] = {}
|
||||
_tap_side_effects: Dict[Union[Key, TapDanceKeyMeta], Union[Key, None]] = {}
|
||||
_timeouts = {} # type: Dict[float, Callable[[], Key]]
|
||||
_tapping = False # type: bool
|
||||
_tap_dance_counts = {} # type: Dict[Union[Key, TapDanceKeyMeta], Union[int, None]]
|
||||
_tap_side_effects = {} # type: Dict[Union[Key, TapDanceKeyMeta], Union[int, None]]
|
||||
|
||||
# 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
|
||||
# real known fix yet other than turning off debug, but M4s have always been
|
||||
# tight on RAM so....
|
||||
def __repr__(self) -> str:
|
||||
def __repr__(self): # type: () -> str
|
||||
return (
|
||||
'KMKKeyboard('
|
||||
'debug_enabled={} '
|
||||
@@ -107,22 +110,26 @@ class KMKKeyboard:
|
||||
self._tap_side_effects,
|
||||
)
|
||||
|
||||
def _print_debug_cycle(self, init: bool = False) -> None:
|
||||
def _print_debug_cycle(self, init=False):
|
||||
# type: (bool) -> None
|
||||
if self.debug_enabled:
|
||||
if init:
|
||||
print('KMKInit(release={})'.format(KMK_RELEASE))
|
||||
print(self)
|
||||
|
||||
def _send_hid(self) -> None:
|
||||
def _send_hid(self):
|
||||
# type: () -> None
|
||||
self._hid_helper.create_report(self.keys_pressed).send()
|
||||
self.hid_pending = False
|
||||
|
||||
def _handle_matrix_report(self, update: bytearray = None) -> None:
|
||||
def _handle_matrix_report(self, update=None):
|
||||
# type: (Optional[bytearray]) -> None
|
||||
if update is not None:
|
||||
self._on_matrix_changed(update[0], update[1], update[2])
|
||||
self.state_changed = True
|
||||
|
||||
def _find_key_in_map(self, int_coord: int, row: int, col: int) -> Union[Key, None]:
|
||||
def _find_key_in_map(self, int_coord, row, col):
|
||||
# type: (int, int, int) -> Optional[Key]
|
||||
self.state_layer_key = None
|
||||
try:
|
||||
idx = self.coord_mapping.index(int_coord)
|
||||
@@ -147,7 +154,8 @@ class KMKKeyboard:
|
||||
|
||||
return self.state_layer_key
|
||||
|
||||
def _on_matrix_changed(self, row: int, col: int, is_pressed: int) -> KMKKeyboard:
|
||||
def _on_matrix_changed(self, row, col, is_pressed):
|
||||
# type: (int, int, int) -> KMKKeyboard
|
||||
if self.debug_enabled:
|
||||
print('MatrixChange(col={} row={} pressed={})'.format(col, row, is_pressed))
|
||||
|
||||
@@ -162,11 +170,12 @@ class KMKKeyboard:
|
||||
|
||||
def process_key(
|
||||
self,
|
||||
key: Union[Key, TapDanceKeyMeta],
|
||||
is_pressed: int,
|
||||
coord_int: Optional[int] = None,
|
||||
coord_raw: Tuple[int, int] = None,
|
||||
) -> KMKKeyboard:
|
||||
key, # type: Union[Key, TapDanceKeyMeta]
|
||||
is_pressed, # type: int
|
||||
coord_int=None, # type: Optional[int]
|
||||
coord_raw=None, # type: Optional[Tuple[int, int]]
|
||||
):
|
||||
# (...) -> KMKKeyboard
|
||||
if self._tapping and not isinstance(key.meta, TapDanceKeyMeta):
|
||||
self._process_tap_dance(key, is_pressed)
|
||||
else:
|
||||
@@ -177,24 +186,26 @@ class KMKKeyboard:
|
||||
|
||||
return self
|
||||
|
||||
def remove_key(self, keycode: Key) -> KMKKeyboard:
|
||||
def remove_key(self, keycode):
|
||||
# type: (Key) -> KMKKeyboard
|
||||
self.keys_pressed.discard(keycode)
|
||||
return self.process_key(keycode, False)
|
||||
|
||||
def add_key(self, keycode: Key) -> KMKKeyboard:
|
||||
def add_key(self, keycode):
|
||||
# type: (Key) -> KMKKeyboard
|
||||
self.keys_pressed.add(keycode)
|
||||
return self.process_key(keycode, True)
|
||||
|
||||
def tap_key(self, keycode: Key) -> KMKKeyboard:
|
||||
def tap_key(self, keycode):
|
||||
# type: (Key) -> KMKKeyboard
|
||||
self.add_key(keycode)
|
||||
# On the next cycle, we'll remove the key.
|
||||
self.set_timeout(False, lambda: self.remove_key(keycode))
|
||||
|
||||
return self
|
||||
|
||||
def _process_tap_dance(
|
||||
self, changed_key: Union[Key, TapDanceKeyMeta], is_pressed: int
|
||||
) -> KMKKeyboard:
|
||||
def _process_tap_dance(self, changed_key, is_pressed):
|
||||
# type: (Union[Key, TapDanceKeyMeta], int) -> KMKKeyboard
|
||||
if is_pressed:
|
||||
if not isinstance(changed_key.meta, TapDanceKeyMeta):
|
||||
# If we get here, changed_key is not a TapDanceKey and thus
|
||||
@@ -231,7 +242,8 @@ class KMKKeyboard:
|
||||
|
||||
return self
|
||||
|
||||
def _end_tap_dance(self, td_key: Union[Key, TapDanceKeyMeta]) -> KMKKeyboard:
|
||||
def _end_tap_dance(self, td_key):
|
||||
# type: (Union[Key, TapDanceKeyMeta]) -> KMKKeyboard
|
||||
v = self._tap_dance_counts[td_key] - 1
|
||||
|
||||
if v >= 0:
|
||||
@@ -252,12 +264,14 @@ class KMKKeyboard:
|
||||
|
||||
return self
|
||||
|
||||
def _cleanup_tap_dance(self, td_key: Union[Key, TapDanceKeyMeta]) -> KMKKeyboard:
|
||||
def _cleanup_tap_dance(self, td_key):
|
||||
# type: (Union[Key, TapDanceKeyMeta]) -> KMKKeyboard
|
||||
self._tap_dance_counts[td_key] = 0
|
||||
self._tapping = any(count > 0 for count in self._tap_dance_counts.values())
|
||||
return self
|
||||
|
||||
def set_timeout(self, after_ticks: float, callback: Callable[[], Key]) -> float:
|
||||
def set_timeout(self, after_ticks, callback):
|
||||
# type: (float, Callable[[], Key]) -> float
|
||||
if after_ticks is False:
|
||||
# We allow passing False as an implicit "run this on the next process timeouts cycle"
|
||||
timeout_key = ticks_ms()
|
||||
@@ -270,11 +284,13 @@ class KMKKeyboard:
|
||||
self._timeouts[timeout_key] = callback
|
||||
return timeout_key
|
||||
|
||||
def _cancel_timeout(self, timeout_key: float) -> None:
|
||||
def _cancel_timeout(self, timeout_key):
|
||||
# type: (float) -> None
|
||||
if timeout_key in self._timeouts:
|
||||
del self._timeouts[timeout_key]
|
||||
|
||||
def _process_timeouts(self) -> KMKKeyboard:
|
||||
def _process_timeouts(self):
|
||||
# type: () -> KMKKeyboard
|
||||
if not self._timeouts:
|
||||
return self
|
||||
|
||||
@@ -291,7 +307,8 @@ class KMKKeyboard:
|
||||
|
||||
return self
|
||||
|
||||
def _init_sanity_check(self) -> KMKKeyboard:
|
||||
def _init_sanity_check(self):
|
||||
# type: () -> KMKKeyboard
|
||||
'''
|
||||
Ensure the provided configuration is *probably* bootable
|
||||
'''
|
||||
@@ -305,7 +322,8 @@ class KMKKeyboard:
|
||||
|
||||
return self
|
||||
|
||||
def _init_coord_mapping(self) -> None:
|
||||
def _init_coord_mapping(self):
|
||||
# () -> None
|
||||
'''
|
||||
Attempt to sanely guess a coord_mapping if one is not provided. No-op
|
||||
if `kmk.extensions.split.Split` is used, it provides equivalent
|
||||
@@ -327,7 +345,8 @@ class KMKKeyboard:
|
||||
for cidx in range(cols_to_calc):
|
||||
self.coord_mapping.append(intify_coordinate(ridx, cidx))
|
||||
|
||||
def _init_hid(self) -> None:
|
||||
def _init_hid(self):
|
||||
# type: () -> None
|
||||
if self.hid_type == HIDModes.NOOP:
|
||||
self._hid_helper = AbstractHID
|
||||
elif self.hid_type == HIDModes.USB:
|
||||
@@ -338,7 +357,8 @@ class KMKKeyboard:
|
||||
self._hid_helper = AbstractHID
|
||||
self._hid_helper = self._hid_helper()
|
||||
|
||||
def _init_matrix(self) -> KMKKeyboard:
|
||||
def _init_matrix(self):
|
||||
# type: () -> KMKKeyboard
|
||||
self.matrix = MatrixScanner(
|
||||
cols=self.col_pins,
|
||||
rows=self.row_pins,
|
||||
@@ -348,7 +368,8 @@ class KMKKeyboard:
|
||||
|
||||
return self
|
||||
|
||||
def before_matrix_scan(self) -> None:
|
||||
def before_matrix_scan(self):
|
||||
# type: () -> None
|
||||
for module in self.modules:
|
||||
try:
|
||||
module.before_matrix_scan(self)
|
||||
@@ -363,7 +384,8 @@ class KMKKeyboard:
|
||||
if self.debug_enabled:
|
||||
print('Failed to run pre matrix function in extension: ', err, ext)
|
||||
|
||||
def after_matrix_scan(self) -> None:
|
||||
def after_matrix_scan(self):
|
||||
# type: () -> None
|
||||
for module in self.modules:
|
||||
try:
|
||||
module.after_matrix_scan(self)
|
||||
@@ -378,7 +400,8 @@ class KMKKeyboard:
|
||||
if self.debug_enabled:
|
||||
print('Failed to run post matrix function in extension: ', err, ext)
|
||||
|
||||
def before_hid_send(self) -> None:
|
||||
def before_hid_send(self):
|
||||
# type: () -> None
|
||||
for module in self.modules:
|
||||
try:
|
||||
module.before_hid_send(self)
|
||||
@@ -393,7 +416,8 @@ class KMKKeyboard:
|
||||
if self.debug_enabled:
|
||||
print('Failed to run pre hid function in extension: ', err, ext)
|
||||
|
||||
def after_hid_send(self) -> None:
|
||||
def after_hid_send(self):
|
||||
# type: () -> None
|
||||
for module in self.modules:
|
||||
try:
|
||||
module.after_hid_send(self)
|
||||
@@ -408,7 +432,8 @@ class KMKKeyboard:
|
||||
if self.debug_enabled:
|
||||
print('Failed to run post hid function in extension: ', err, ext)
|
||||
|
||||
def powersave_enable(self) -> None:
|
||||
def powersave_enable(self):
|
||||
# type: () -> None
|
||||
for module in self.modules:
|
||||
try:
|
||||
module.on_powersave_enable(self)
|
||||
@@ -423,7 +448,8 @@ class KMKKeyboard:
|
||||
if self.debug_enabled:
|
||||
print('Failed to run post hid function in extension: ', err, ext)
|
||||
|
||||
def powersave_disable(self) -> None:
|
||||
def powersave_disable(self):
|
||||
# type: () -> None
|
||||
for module in self.modules:
|
||||
try:
|
||||
module.on_powersave_disable(self)
|
||||
@@ -439,10 +465,11 @@ class KMKKeyboard:
|
||||
|
||||
def go(
|
||||
self,
|
||||
hid_type: int = HIDModes.USB,
|
||||
secondary_hid_type: Optional[int] = None,
|
||||
**kwargs: Dict[Any, Any],
|
||||
) -> None:
|
||||
hid_type=HIDModes.USB, # type: int
|
||||
secondary_hid_type=None, # type: Optional[int]
|
||||
**kwargs, # type: Dict[Any, Any]
|
||||
):
|
||||
# (...) -> None
|
||||
self.hid_type = hid_type
|
||||
self.secondary_hid_type = secondary_hid_type
|
||||
|
||||
|
@@ -1,23 +1,28 @@
|
||||
import time
|
||||
|
||||
|
||||
def sleep_ms(ms: float) -> None:
|
||||
def sleep_ms(ms):
|
||||
# type: (float) -> None
|
||||
return time.sleep(ms / 1000)
|
||||
|
||||
|
||||
def ticks_ms() -> float:
|
||||
def ticks_ms():
|
||||
# type: () -> float
|
||||
'''Has .25s granularity, but is cheap'''
|
||||
return time.monotonic() * 1000
|
||||
|
||||
|
||||
def ticks_diff(new: float, old: float) -> float:
|
||||
def ticks_diff(new, old):
|
||||
# type: (float, float) -> float
|
||||
return new - old
|
||||
|
||||
|
||||
def accurate_ticks() -> int:
|
||||
def accurate_ticks():
|
||||
# type: () -> int
|
||||
'''Is more expensive, but good for time critical things'''
|
||||
return time.monotonic_ns()
|
||||
|
||||
|
||||
def accurate_ticks_diff(new: float, old: float, ms: float) -> bool:
|
||||
def accurate_ticks_diff(new, old, ms):
|
||||
# type: (float, float, float) -> bool
|
||||
return bool(new - old < ms * 1000000)
|
||||
|
49
kmk/types.py
49
kmk/types.py
@@ -1,6 +1,12 @@
|
||||
from typing import List, Optional, Tuple
|
||||
import sys
|
||||
|
||||
from kmk.keys import Key
|
||||
from kmk.consts import TYPING_PLATFORMS
|
||||
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import List, Optional, Tuple, Union
|
||||
|
||||
# Avoid cyclical imports
|
||||
from kmk.keys import ConsumerKey, Key, ModifierKey
|
||||
|
||||
|
||||
class AttrDict(dict):
|
||||
@@ -12,39 +18,44 @@ class AttrDict(dict):
|
||||
This is read-only on purpose.
|
||||
'''
|
||||
|
||||
def __getattr__(self, key: str) -> str:
|
||||
def __getattr__(self, key):
|
||||
# type: (str) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
return self[key]
|
||||
|
||||
|
||||
class LayerKeyMeta:
|
||||
def __init__(self, layer: int, kc: Optional[Key] = None) -> None:
|
||||
self.layer: int = layer
|
||||
self.kc: Optional[Key] = kc
|
||||
def __init__(self, layer, kc=None):
|
||||
# type: (int, Optional[Key]) -> None
|
||||
self.layer = layer # type: int
|
||||
self.kc = kc # type: Optional[Key]
|
||||
|
||||
|
||||
class ModTapKeyMeta:
|
||||
def __init__(
|
||||
self, kc: Optional[Key] = None, mods: Optional[List[Key]] = None
|
||||
) -> None:
|
||||
self.mods: Optional[List[Key]] = mods
|
||||
self.kc: Optional[Key] = kc
|
||||
def __init__(self, kc=None, mods=None):
|
||||
# type: (Optional[Key], Optional[List[Key]]) -> None
|
||||
self.mods = mods # type: Optional[List[Key]]
|
||||
self.kc = kc # type: Optional[Key]
|
||||
|
||||
|
||||
class KeySequenceMeta:
|
||||
def __init__(self, seq: List[Key]):
|
||||
self.seq: List[Key] = seq
|
||||
def __init__(self, seq):
|
||||
# type: (List[Key]) -> None
|
||||
self.seq = seq # type: List[Key]
|
||||
|
||||
|
||||
class KeySeqSleepMeta:
|
||||
def __init__(self, ms: float):
|
||||
self.ms: float = ms
|
||||
def __init__(self, ms):
|
||||
# type: (float) -> None
|
||||
self.ms = ms # type: float
|
||||
|
||||
|
||||
class UnicodeModeKeyMeta:
|
||||
def __init__(self, mode: int):
|
||||
self.mode: int = mode
|
||||
def __init__(self, mode):
|
||||
# type: (int) -> None
|
||||
self.mode = mode # type: int
|
||||
|
||||
|
||||
class TapDanceKeyMeta:
|
||||
def __init__(self, codes: Tuple[Key, ...]):
|
||||
self.codes: Tuple[Key, ...] = codes
|
||||
def __init__(self, codes):
|
||||
# type: (Tuple[Key, ...]) -> None
|
||||
self.codes = codes # type: Tuple[Key, ...]
|
||||
|
Reference in New Issue
Block a user