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:
parent
9fc431e0a7
commit
b202dc77d1
2
Pipfile
2
Pipfile
@ -21,4 +21,6 @@ black = "==21.6b0"
|
||||
flake8-quotes = "*"
|
||||
flake8-black = "*"
|
||||
circuitpython-stubs = "==7.0.0a6.dev195"
|
||||
pyright = "*"
|
||||
typing = "*"
|
||||
mypy = "*"
|
||||
|
131
Pipfile.lock
generated
131
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "e80d827684ac8c56b762a74548440c5b371c5b3ee5fcb5b74e68ae6d9bff0665"
|
||||
"sha256": "cee0eeba8c8dad66dccffe0935656829132f7ca928569e3aa957f278e6e92da6"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@ -94,11 +94,11 @@
|
||||
},
|
||||
"flake8-comprehensions": {
|
||||
"hashes": [
|
||||
"sha256:b07aef3277623db32310aa241a1cec67212b53c1d18e767d7e26d4d83aa05bf7",
|
||||
"sha256:f24be9032587127f7a5bc6d066bf755b6e66834f694383adb8a673e229c1f559"
|
||||
"sha256:4888de89248b7f7535159189ff693c77f8354f6d37a02619fa28c9921a913aa0",
|
||||
"sha256:e9a010b99aa90c05790d45281ad9953df44a4a08a1a8f6cd41f98b4fc6a268a0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.5.0"
|
||||
"version": "==3.6.1"
|
||||
},
|
||||
"flake8-isort": {
|
||||
"hashes": [
|
||||
@ -110,10 +110,10 @@
|
||||
},
|
||||
"flake8-quotes": {
|
||||
"hashes": [
|
||||
"sha256:3f1116e985ef437c130431ac92f9b3155f8f652fda7405ac22ffdfd7a9d1055e"
|
||||
"sha256:f1dd87830ed77ff2ce47fc0ee0fd87ae20e8f045355354ffbf4dcaa18d528217"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.2.0"
|
||||
"version": "==3.3.0"
|
||||
},
|
||||
"greenlet": {
|
||||
"hashes": [
|
||||
@ -300,6 +300,13 @@
|
||||
"index": "pypi",
|
||||
"version": "==0.3.1"
|
||||
},
|
||||
"nodeenv": {
|
||||
"hashes": [
|
||||
"sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b",
|
||||
"sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"
|
||||
],
|
||||
"version": "==1.6.0"
|
||||
},
|
||||
"parso": {
|
||||
"hashes": [
|
||||
"sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398",
|
||||
@ -332,11 +339,11 @@
|
||||
},
|
||||
"prompt-toolkit": {
|
||||
"hashes": [
|
||||
"sha256:08360ee3a3148bdb5163621709ee322ec34fc4375099afa4bbf751e9b7b7fa4f",
|
||||
"sha256:7089d8d2938043508aa9420ec18ce0922885304cddae87fb96eebca942299f88"
|
||||
"sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c",
|
||||
"sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.1'",
|
||||
"version": "==3.0.19"
|
||||
"markers": "python_full_version >= '3.6.2'",
|
||||
"version": "==3.0.20"
|
||||
},
|
||||
"ptyprocess": {
|
||||
"hashes": [
|
||||
@ -363,11 +370,11 @@
|
||||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f",
|
||||
"sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"
|
||||
"sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380",
|
||||
"sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==2.9.0"
|
||||
"version": "==2.10.0"
|
||||
},
|
||||
"pynvim": {
|
||||
"hashes": [
|
||||
@ -375,6 +382,14 @@
|
||||
],
|
||||
"version": "==0.4.3"
|
||||
},
|
||||
"pyright": {
|
||||
"hashes": [
|
||||
"sha256:dd8e18c54321340be44a708b6037c0b967486c32b3f492741fffdc205cb82f15",
|
||||
"sha256:e2668730cddf580e696d4a11946e740e2f5647df1eb45f7c55b7029376eac5a1"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.0.9"
|
||||
},
|
||||
"pyserial": {
|
||||
"hashes": [
|
||||
"sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb",
|
||||
@ -408,41 +423,49 @@
|
||||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
"sha256:026beb631097a4a3def7299aa5825e05e057de3c6d72b139c37813bfa351274b",
|
||||
"sha256:14caacd1853e40103f59571f169704367e79fb78fac3d6d09ac84d9197cadd16",
|
||||
"sha256:16d9eaa8c7e91537516c20da37db975f09ac2e7772a0694b245076c6d68f85da",
|
||||
"sha256:18fdc51458abc0a974822333bd3a932d4e06ba2a3243e9a1da305668bd62ec6d",
|
||||
"sha256:28e8af338240b6f39713a34e337c3813047896ace09d51593d6907c66c0708ba",
|
||||
"sha256:3835de96524a7b6869a6c710b26c90e94558c31006e96ca3cf6af6751b27dca1",
|
||||
"sha256:3905c86cc4ab6d71635d6419a6f8d972cab7c634539bba6053c47354fd04452c",
|
||||
"sha256:3c09d88a07483231119f5017904db8f60ad67906efac3f1baa31b9b7f7cca281",
|
||||
"sha256:4551728b767f35f86b8e5ec19a363df87450c7376d7419c3cac5b9ceb4bce576",
|
||||
"sha256:459bbe342c5b2dec5c5223e7c363f291558bc27982ef39ffd6569e8c082bdc83",
|
||||
"sha256:4f421e3cdd3a273bace013751c345f4ebeef08f05e8c10757533ada360b51a39",
|
||||
"sha256:577737ec3d4c195c4aef01b757905779a9e9aee608fa1cf0aec16b5576c893d3",
|
||||
"sha256:57fece29f7cc55d882fe282d9de52f2f522bb85290555b49394102f3621751ee",
|
||||
"sha256:7976d410e42be9ae7458c1816a416218364e06e162b82e42f7060737e711d9ce",
|
||||
"sha256:85f568892422a0e96235eb8ea6c5a41c8ccbf55576a2260c0160800dbd7c4f20",
|
||||
"sha256:8764a78c5464ac6bde91a8c87dd718c27c1cabb7ed2b4beaf36d3e8e390567f9",
|
||||
"sha256:8935937dad2c9b369c3d932b0edbc52a62647c2afb2fafc0c280f14a8bf56a6a",
|
||||
"sha256:8fe58d9f6e3d1abf690174fd75800fda9bdc23d2a287e77758dc0e8567e38ce6",
|
||||
"sha256:937b20955806381e08e54bd9d71f83276d1f883264808521b70b33d98e4dec5d",
|
||||
"sha256:9569da9e78f0947b249370cb8fadf1015a193c359e7e442ac9ecc585d937f08d",
|
||||
"sha256:a3b73390511edd2db2d34ff09aa0b2c08be974c71b4c0505b4a048d5dc128c2b",
|
||||
"sha256:a4eddbe2a715b2dd3849afbdeacf1cc283160b24e09baf64fa5675f51940419d",
|
||||
"sha256:a5c6dbe09aff091adfa8c7cfc1a0e83fdb8021ddb2c183512775a14f1435fe16",
|
||||
"sha256:b63e3571b24a7959017573b6455e05b675050bbbea69408f35f3cb984ec54363",
|
||||
"sha256:bb350eb1060591d8e89d6bac4713d41006cd4d479f5e11db334a48ff8999512f",
|
||||
"sha256:bf6d987edd4a44dd2fa2723fca2790f9442ae4de2c8438e53fcb1befdf5d823a",
|
||||
"sha256:bfa6a679410b394600eafd16336b2ce8de43e9b13f7fb9247d84ef5ad2b45e91",
|
||||
"sha256:c856ec9b42e5af4fe2d8e75970fcc3a2c15925cbcc6e7a9bcb44583b10b95e80",
|
||||
"sha256:cea56288eeda8b7511d507bbe7790d89ae7049daa5f51ae31a35ae3c05408531",
|
||||
"sha256:ea212df6e5d3f60341aef46401d32fcfded85593af1d82b8b4a7a68cd67fdd6b",
|
||||
"sha256:f35567470ee6dbfb946f069ed5f5615b40edcbb5f1e6e1d3d2b114468d505fc6",
|
||||
"sha256:fbc20975eee093efa2071de80df7f972b7b35e560b213aafabcec7c0bd00bd8c",
|
||||
"sha256:ff4a8ad9638b7ca52313d8732f37ecd5fd3c8e3aff10a8ccb93176fd5b3812f6"
|
||||
"sha256:0696eb934dee723e3292056a2c046ddb1e4dd3887685783a9f4af638e85dee76",
|
||||
"sha256:105122fa63da98d8456d5026bc6ac5a1399fd82fa6bad22c6ea641b1572c9142",
|
||||
"sha256:116c277774f84266044e889501fe79cfd293a8b4336b7a5e89b9f20f1e5a9f21",
|
||||
"sha256:12eaf0bbe568bd62e6cade7937e0bf01a2a4cef49a82f4fd204401e78409e158",
|
||||
"sha256:1401cfa4320691cbd91191ec678735c727dee674d0997b0902a5a38ad482faf5",
|
||||
"sha256:19acdb8831a4e3b03b23369db43178d8fee1f17b99c83af6cd907886f76bd9d4",
|
||||
"sha256:208851a2f8dd31e468f0b5aa6c94433975bd67a107a4e7da3bdda947c9f85e25",
|
||||
"sha256:24d68499a27b2d93831fde4a9b84ea5b19e0ab141425fbc9ab1e5b4dad179df7",
|
||||
"sha256:2778c6cb379d804e429cc8e627392909e60db5152b42c695c37ae5757aae50ae",
|
||||
"sha256:2a0a5e323cf86760784ce2b91d8ab5ea09d0865d6ef4da0151e03d15d097b24e",
|
||||
"sha256:2d9cbe0c755ab8b6f583169c0783f7278fc6b195e423b09c5a8da6f858025e96",
|
||||
"sha256:2de1429e4eeab799c168a4f6e6eecdf30fcaa389bba4039cc8a065d6b7aad647",
|
||||
"sha256:32753eda8d413ce4f208cfe01dd61171a78068a6f5d5f38ccd751e00585cdf1d",
|
||||
"sha256:3ee8ad16a35c45a5bab098e39020ecb6fec3b0e700a9d88983d35cbabcee79c8",
|
||||
"sha256:4f03fc0a25122cdcbf39136510d4ea7627f732206892db522adf510bc03b8c67",
|
||||
"sha256:4f3e36086d6631ceaf468503f96a3be0d247caef0660c9452fb1b0c055783851",
|
||||
"sha256:503c1ba0920a46a1844363725215ef44d59fcac2bd2c03ae3c59aa9d08d29bd6",
|
||||
"sha256:507861cf3d97a86fbe26ea6cc04660ae028b9e4080b8290e28b99547b4e15d89",
|
||||
"sha256:56ae6e3cf0506ec0c40b466e31f41ee7a7149a2b505ae0ee50edd9043b423d27",
|
||||
"sha256:6530b7b9505123cdea40a2301225183ca65f389bc6129f0c225b9b41680268d8",
|
||||
"sha256:6729914dd73483cd1c8aaace3ac082436fc98b0072743ac136eaea0b3811d42f",
|
||||
"sha256:7406dd2e44c7cfb4680c0a45a03264381802c67890cf506c147288f04c67177d",
|
||||
"sha256:7684016b73938ca12d160d2907d141f06b7597bd17d854e32bb7588be01afa1d",
|
||||
"sha256:7db58ad61f3f6ea393aaf124d774ee0c58806320bc85c06dc9480f5c7219c250",
|
||||
"sha256:83946ca9278b304728b637bc8d8200ab1663a79de85e47724594917aeed0e892",
|
||||
"sha256:84057cfae5676f456b03970eb78b7e182fddc80c2daafd83465a3d6ca9ff8dbf",
|
||||
"sha256:862b6164e9a38b5c495be2c2854e75fd8af12c5be4c61dc9b42d255980d7e907",
|
||||
"sha256:8ddb4f9ce6bb388ecc97b4b3eb37e786f05d7d5815e8822e0d87a3dbd7100649",
|
||||
"sha256:92eb03f47427fea452ff6956d11f5d5a3f22a048c90a0f34fa223e6badab6c85",
|
||||
"sha256:a5f3bc727fea58f21d99c22e6d4fca652dc11dbc2a1e7cfc4838cd53b2e3691f",
|
||||
"sha256:a6180dbf5945b27e9420e1b58c3cacfc79ad5278bdad3ea35109f5680fbe16d1",
|
||||
"sha256:b158f673ae6a6523f13704f70aa7e4ce875f91e379bece4362c89db18db189d5",
|
||||
"sha256:cd45b4542134de63e7b9dd653e0a2d7d47ffed9615e3637c27ca5f6b78ea68bb",
|
||||
"sha256:d2404336fd16788ea757d4218a2580de60adb052d9888031e765320be8884309",
|
||||
"sha256:db888d4fb33a2fd54b57ac55d5015e51fa849f0d8592bd799b4e47f83bd04e00",
|
||||
"sha256:dde0ac721c7c5bfa5f9fc285e811274dec3c392f2c1225f7d07ca98a8187ca84",
|
||||
"sha256:de0d06ccbc06af5bf93bddec10f4f80275c5d74ea6d28b456931f3955f58bc8c",
|
||||
"sha256:e02dad60e3e8442eefd28095e99b2ac98f2b8667167493ac6a2f3aadb5d84a17",
|
||||
"sha256:e960fe211496333b2f7e36badf4c22a919d740386681f79139ee346b403d1ca1",
|
||||
"sha256:e9700c52749cb3e90c98efd72b730c97b7e4962992fca5fbcaf1363be8e3b849",
|
||||
"sha256:ee318974a1fdacba1701bc9e552e9015788d6345416364af6fa987424ff8df53"
|
||||
],
|
||||
"version": "==2021.8.3"
|
||||
"version": "==2021.8.27"
|
||||
},
|
||||
"s3cmd": {
|
||||
"hashes": [
|
||||
@ -462,10 +485,10 @@
|
||||
},
|
||||
"testfixtures": {
|
||||
"hashes": [
|
||||
"sha256:9bddf79b2dddb36420a20c25a65c827a8e7398c6ed4e2c75c2697857cb006be9",
|
||||
"sha256:d4bd1c4f90eac90a73e1bdc59c31d03943f218d687f3c5a09e48478841a8af5f"
|
||||
"sha256:0a6422737f6d89b45cdef1e2df5576f52ad0f507956002ce1020daa9f44211d6",
|
||||
"sha256:486be7b01eb71326029811878a3317b7e7994324621c0ec633c8e24499d8d5b3"
|
||||
],
|
||||
"version": "==6.18.0"
|
||||
"version": "==6.18.1"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
@ -483,6 +506,14 @@
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==5.0.5"
|
||||
},
|
||||
"typing": {
|
||||
"hashes": [
|
||||
"sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9",
|
||||
"sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.7.4.3"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
|
||||
|
@ -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, ...]
|
||||
|
@ -24,18 +24,25 @@ exclude = '''
|
||||
'''
|
||||
|
||||
[tool.pyright]
|
||||
strict = ["kmk"]
|
||||
typeCheckingMode = "strict"
|
||||
include = ["kmk"]
|
||||
exclude = [
|
||||
"hardware",
|
||||
".venv",
|
||||
"user_keymaps",
|
||||
"boards"
|
||||
"boards",
|
||||
".git"
|
||||
]
|
||||
venvPath = ".venv"
|
||||
# stops constant reporting of missing board module etc.
|
||||
reportMissingModuleSource = false
|
||||
# reports missing typestubs allowing for a code action to
|
||||
# create new library typestubs
|
||||
reportMissingTypeStubs = true
|
||||
pythonVersion = "3.6"
|
||||
|
||||
[tool.mypy]
|
||||
exclude = "boards/|user_keymaps/"
|
||||
ignore_missing_imports = true
|
||||
python_version = "3.6"
|
||||
|
Loading…
Reference in New Issue
Block a user