Open peterwhitesell opened 1 year ago
Really glad to see this PR and just wanted to note that I originally forked this from https://github.com/kbjunky/Dactyl5 when he was experiencing weirdness in the driver with debugging enabled. I "fixed" that by adding the same workaround as QMK uses in their pmw33xx_common.c driver. At line 203, a conditional checks for an odd state and resets burst mode which uses the recovery logic in QMK's driver.
I'd also like to see this merged. Skimming over the code, we may need a couple of iterations of review to get there. Let's start with linting. Run make fix-isort fix-formatting
for automatic corrections and before every push make sure make test
passes.
At the end of the code review, we'll need documentation; you can hold off on that for now.
Hey @xs5871, I did the isort and formatting fixes and pushed. make test
didn't pass for me, but they are not passing for me on master either, and it's the same 12 failures on this branch.
Please share the error output.
Of course! first error:
kmk_firmware $ make test
./kmk/modules/autoshift.py:33:32: W601 .has_key() is deprecated, use 'in'
make: *** [lint] Error 1
if I fix that in autoshift.py, replacing keyboard._hid_helper.has_key(KC.LSHIFT)
with KC.LSHIFT in keyboard._hid_helper.has_key
, I get to the test errors:
kmk_firmware $ make test
EEEEEEEEEEEE
======================================================================
ERROR: tests.test_autoshift (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_autoshift
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_autoshift.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_capsword (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_capsword
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_capsword.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_combos (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_combos
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_combos.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_holdtap (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_holdtap
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_holdtap.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_kmk_extension_stringy_keymaps (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_kmk_extension_stringy_keymaps
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_kmk_extension_stringy_keymaps.py", line 3, in <module>
from kmk.extensions.stringy_keymaps import StringyKeymaps
File "/Users/peter/Dev/kmk_firmware/kmk/extensions/stringy_keymaps.py", line 2, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_kmk_keyboard (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_kmk_keyboard
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_kmk_keyboard.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_kmk_keys (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_kmk_keys
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_kmk_keys.py", line 3, in <module>
from kmk.keys import KC, Key, ModifierKey, make_key
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_layers (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_layers
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_layers.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_oneshot (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_oneshot
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_oneshot.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_sticky_mod (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_sticky_mod
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_sticky_mod.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_string_substitution (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_string_substitution
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_string_substitution.py", line 3, in <module>
from kmk.keys import ALL_ALPHAS, ALL_NUMBERS, KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
======================================================================
ERROR: tests.test_tapdance (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_tapdance
Traceback (most recent call last):
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
module = self._get_module_from_name(name)
File "/Users/peter/.asdf/installs/python/3.6.15/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
__import__(name)
File "/Users/peter/Dev/kmk_firmware/tests/test_tapdance.py", line 3, in <module>
from kmk.keys import KC
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 495, in <module>
class Key:
File "/Users/peter/Dev/kmk_firmware/kmk/keys.py", line 508, in Key
meta: object = object(),
TypeError: 'type' object is not subscriptable
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (errors=12)
make: *** [unit-tests] Error 1
Do you not see these symptoms? maybe my dev env isn't set up correctly. I'm using python 3.6.15
:
kmk_firmware $ pipenv run python --version
Python 3.6.15
3.6 is ancient, try a current version.
3.6 is ancient, try a current version.
Indeed it is. Saw it in the docs somewhere. I also tried 3.9, as seen in the dockerfile, with the same results. What version do you recommend?
It worked just before you tried to use it (see #801). My guess is flake8 very recently dropped python 3.9 support
Thanks for fixing my code and happy to see this merged into KMK.
Any updates on making the linter happy with the updated library version requirements?
hey @xs5871, make fix-isort
and make fix-formatting
are passing for me now (🥳). I see make test
is still failing, with actual test failures now, though they are failing on master
as well. they are AssertionError: reports don't match up
failures, and they seem flakey. here's an example failure with debug_enabled
turned on for the tests that were failing:
..........match: 2 combo, within timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 3 combo, within timeout, shuffled
assert mods: 0 == 0 keys: {'Y'} == {'Y'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo + overlap, after timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'C'} == {'C'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo + overlap, interleaved, after timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: {'C', 'X'} == {'C', 'X'} matching?: True
assert mods: 0 == 0 keys: {'C'} == {'C'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo hold + other, interleaved, after timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: {'X', 'E'} == {'X', 'E'} matching?: True
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo hold + overlap, interleaved, after timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: {'C', 'X'} == {'C', 'X'} matching?: True
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: other + 2 combo, after timeout
assert mods: 0 == 0 keys: {'E'} == {'E'} matching?: True
assert mods: 0 == 0 keys: {'X', 'E'} == {'X', 'E'} matching?: True
assert mods: 0 == 0 keys: {'E'} == {'E'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo + other, after timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: {'X', 'E'} == {'X', 'E'} matching?: True
assert mods: 0 == 0 keys: {'E'} == {'E'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo, partial release and repeat
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo, partial release and repeat
assert mods: 0 == 0 keys: {'Y'} == {'Y'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'Y'} == {'Y'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo + 2 combo, after timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: {'X', 'Z'} == {'X', 'Z'} matching?: True
assert mods: 0 == 0 keys: {'Z'} == {'Z'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 combo hold + 2 combo, after timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: {'X', 'Z'} == {'X', 'Z'} matching?: True
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: partial combo, after timeout
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: partial combo, repeated
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: partial combo, repeated
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: 3 combo after timout
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: {'A', 'C'} == {'A', 'C'} matching?: True
assert mods: 0 == 0 keys: {'A', 'B', 'C'} == {'A', 'B', 'C'} matching?: True
assert mods: 0 == 0 keys: {'A', 'C'} == {'A', 'C'} matching?: True
assert mods: 0 == 0 keys: {'C'} == {'C'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: other + 2 combo within timeout
assert mods: 0 == 0 keys: {'E'} == {'E'} matching?: True
assert mods: 0 == 0 keys: {'A', 'E'} == {'A', 'E'} matching?: True
assert mods: 0 == 0 keys: {'A', 'B', 'E'} == {'A', 'B', 'E'} matching?: True
assert mods: 0 == 0 keys: {'A', 'E'} == {'A', 'E'} matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: 2 combo + other within timeout
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: {'A', 'B'} == {'A', 'B'} matching?: True
assert mods: 0 == 0 keys: {'A', 'B', 'E'} == {'A', 'B', 'E'} matching?: True
assert mods: 0 == 0 keys: {'A', 'E'} == {'A', 'E'} matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: 2 combo after timeout
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: Combo + other, within timeout
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: {'A', 'B'} == {'A', 'B'} matching?: True
assert mods: 0 == 0 keys: {'A', 'B', 'E'} == {'A', 'B', 'E'} matching?: True
assert mods: 0 == 0 keys: {'B', 'E'} == {'B', 'E'} matching?: True
assert mods: 0 == 0 keys: {'E'} == {'E'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: Combo + other, within timeout
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: {'A', 'E'} == {'A', 'E'} matching?: True
assert mods: 0 == 0 keys: {'A', 'B', 'E'} == {'A', 'B', 'E'} matching?: True
assert mods: 0 == 0 keys: {'B', 'E'} == {'B', 'E'} matching?: True
assert mods: 0 == 0 keys: {'E'} == {'E'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: Combo containing layer switch, within timeout
assert mods: 0 == 0 keys: {'Z'} == {'Z'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match: Combo containing layer switch + other, within timeout
assert mods: 0 == 0 keys: {'1'} == {'1'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: Other pressed and released before combo, delay after other press but within the combo timeout
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'Z'} == {'Z'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: Other pressed and released before combo, delay after other release but within the combo timeout
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'Z'} == {'Z'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: Other pressed and released before combo, delay after other pressed but within the combo timeout, other is part of another combo
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'Z'} == {'Z'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: Other pressed and released before combo, delay after other release but within the combo timeout, other is part of another combo
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'Z'} == {'Z'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
.match: leader sequence, within timeout
assert mods: 0 == 0 keys: {'V'} == {'V'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 sequence, within timeout
assert mods: 0 == 0 keys: {'X'} == {'X'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 2 sequence, within long timeout
assert mods: 0 == 0 keys: {'Z'} == {'Z'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match: 3 sequence, within timeout
assert mods: 0 == 0 keys: {'1'} == {'Y'} matching?: False
assert mods: 0 == 0 keys: set() == set() matching?: False
assert mods: 0 == None keys: {'2'} == {None} matching?: False
assert mods: 0 == None keys: set() == {None} matching?: False
assert mods: 0 == None keys: {'HASH'} == {None} matching?: False
assert mods: 0 == None keys: set() == {None} matching?: False
FF.................................................multi-character key, single-character value
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
multi-character value, single-character key
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
shifted alphanumeric or symbol in key and/or value
assert mods: 2 == 2 keys: set() == set() matching?: True
assert mods: 2 == 2 keys: {'2'} == {'2'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
backspace is only tapped as many times as necessary to delete the difference between the key and value
assert mods: 0 == 0 keys: {'D'} == {'D'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'C'} == {'C'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'C'} == {'C'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
the presence of non-shift modifiers prevents a multi-character match
assert mods: 1 == 1 keys: set() == set() matching?: True
assert mods: 1 == 1 keys: {'A'} == {'A'} matching?: True
assert mods: 1 == 1 keys: set() == set() matching?: True
assert mods: 1 == 1 keys: {'A'} == {'A'} matching?: True
assert mods: 1 == 1 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
the presence of non-shift modifiers prevents a single-character match
assert mods: 1 == 1 keys: set() == set() matching?: True
assert mods: 1 == 1 keys: {'B'} == {'B'} matching?: True
assert mods: 1 == 1 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
the presence of non-shift modifiers resets current potential matches
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 1 == 1 keys: set() == set() matching?: True
assert mods: 1 == 1 keys: {'A'} == {'A'} matching?: True
assert mods: 1 == 1 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match found and replaced when there are preceding characters
assert mods: 0 == 0 keys: {'C'} == {'C'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
match found and replaced when there are trailing characters, and the trailing characters are sent
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'C'} == {'C'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
no match
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'1'} == {'1'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
multiple backspaces
assert mods: 0 == 0 keys: {'D'} == {'D'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'D'} == {'D'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'D'} == {'D'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'D'} == {'D'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'BACKSPACE'} == {'BACKSPACE'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'B'} == {'B'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: 0 == 0 keys: {'A'} == {'A'} matching?: True
assert mods: 0 == 0 keys: set() == set() matching?: True
assert mods: None == 0 keys: {None} == {'B'} matching?: False
assert mods: None == 0 keys: {None} == set() matching?: False
F..........
======================================================================
FAIL: test_sequence (tests.test_combos.TestCombo.test_sequence)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/peter/Dev/kmk_firmware/tests/test_combos.py", line 464, in test_sequence
keyboard.test(
File "/Users/peter/.asdf/installs/python/3.11.3/lib/python3.11/unittest/mock.py", line 1369, in patched
return func(*newargs, **newkeywargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/peter/Dev/kmk_firmware/tests/keyboard_test.py", line 131, in test
assert matching, "reports don't match up"
AssertionError: reports don't match up
======================================================================
FAIL: test_holdtap (tests.test_holdtap.TestHoldTap.test_holdtap)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/peter/Dev/kmk_firmware/tests/test_holdtap.py", line 98, in test_holdtap
keyboard.test(
File "/Users/peter/.asdf/installs/python/3.11.3/lib/python3.11/unittest/mock.py", line 1369, in patched
return func(*newargs, **newkeywargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/peter/Dev/kmk_firmware/tests/keyboard_test.py", line 131, in test
assert matching, "reports don't match up"
AssertionError: reports don't match up
======================================================================
FAIL: test_keyboard_events_are_correct (tests.test_string_substitution.TestStringSubstitution.test_keyboard_events_are_correct)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/peter/Dev/kmk_firmware/tests/test_string_substitution.py", line 184, in test_keyboard_events_are_correct
self.keyboard.test(
File "/Users/peter/.asdf/installs/python/3.11.3/lib/python3.11/unittest/mock.py", line 1369, in patched
return func(*newargs, **newkeywargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/peter/Dev/kmk_firmware/tests/keyboard_test.py", line 131, in test
assert matching, "reports don't match up"
AssertionError: reports don't match up
----------------------------------------------------------------------
Ran 73 tests in 4.599s
FAILED (failures=3)
make: *** [unit-tests] Error 1
the test failures are unrelated to this changeset (as they fail on master as well), but just being diligent here, running make test
for each commit
hey @xs5871, I was planning to start writing documentation for the module. Is there anything major interface-wise that would be good to address before that? I believe the linting is all good at this point
Unfortunately, yes, there's quite a bit that can be improved, code quality wise. Since this is a big chunk of a module, it'll take me a while to go through all of it. I'm positive we can work through it together.
@xs5871 totally understand it'll take a while to review 😃 just making sure I'm not holding up the review on my end. for full transparency I copied this code from bullwinkle3000's fork of kbjunky's original code, and then hacked it a bit myself for my needs, but I think I understand it well enough at this point to address any feedback.
I'll look forward to your feedbacks as you have a chance to review. not sure if you like to do comprehensive or iterative reviews, but I'm happy to address points along the way if that's helpful
I went ahead and pushed up some initial docs for the module as well
hey @xs5871 thank you for the review and feedback. It may take me some time to address, but just writing now to acknowledge receipt and thank you for the time
It's my fault this took so long. A bunch of my reviews got stuck for some reason and I only noticed yesterday. I actually wrote this over a month ago... apologies.
Is there any update on this? I would like to test it and debug it. Can I just use this module or is it now too obsolete?
Hi @lucacri, sorry I haven't attended to this PR for so long. I've changed tactics a bit, and haven't had a chance to new PR for it. What I do now is I use the whimsee/CircuitPython_PMW3360 library, with a much thinner kmk module built on that. If you want to try it out, it's pretty simple and you're more than welcome to open a PR for it if you get to that before I do.
Steps to use it are as follows, assuming you already have kmk setup on your board:
<your board>/lib/pmw3360.py
<your board>/kmk/modules/pmw3660.py
from kmk.modules.pmw3360 import PMW3360
...
keyboard.modules.append(PMW3360(
sck_pin, mosi_pin, miso_pin, cs_pin, # assuming you have defined these variables
cpi=800,
scroll_layers=[2, 4],
))
Adds pmw3360 trackball module for the pmw3360 motion sensor
PMW3360
For using PMW3360 motion sensor for pointer, scrolling and volume. The default behavior converts sensor XY movement into cursor XY movement.
The firmware for this sensor has to be placed in
kmk\modules\PMW3360_firmware.py
Scrolling and Volume
Scrolling and Volumne control can be enabled either in key event handlers, e.g.
or via layers, e.g.
Constructor parameters