From 5c0c13e8d0f6ef5e8bb810b4f4efd6e925e8b8a7 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Wed, 24 Jul 2019 22:56:10 -0700 Subject: [PATCH 1/3] Prepare for Black autoformatting: dependencies, string staging, single-quote string override --- Makefile | 4 ++ Pipfile | 2 + Pipfile.lock | 38 +++++++++++- README.md | 11 ++++ kmk/handlers/layers.py | 29 ++++++--- kmk/keyboard_config.py | 5 +- kmk/keys.py | 6 +- kmk/led.py | 12 ++-- kmk/rgb.py | 68 ++++++++++----------- pyproject.toml | 22 +++++++ setup.cfg | 14 ++++- user_keymaps/kdb424/gherkin.py | 2 +- user_keymaps/kdb424/klanck.py | 2 +- user_keymaps/klardotsh/iris_r2.py | 2 +- user_keymaps/klardotsh/klarank_featherm4.py | 2 +- 15 files changed, 159 insertions(+), 60 deletions(-) create mode 100644 pyproject.toml diff --git a/Makefile b/Makefile index 3734385..5ce5448 100644 --- a/Makefile +++ b/Makefile @@ -89,8 +89,12 @@ docker-base-deploy: docker-base devdeps: .devdeps lint: devdeps + @$(PIPENV) run black --check @$(PIPENV) run flake8 +fix-formatting: devdeps + @$(PIPENV) run black . + fix-isort: devdeps @find kmk/ tests/ user_keymaps/ -name "*.py" | xargs $(PIPENV) run isort diff --git a/Pipfile b/Pipfile index e6eb58b..a8579ee 100644 --- a/Pipfile +++ b/Pipfile @@ -18,6 +18,8 @@ ipython = "*" isort = "*" neovim = "*" s3cmd = "*" +black = "==19.3b0" +flake8-quotes = "*" [requires] python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index 93fb96e..ddcad6c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "8f51706fcfb278497a6d3083109744210150dc3c644ead11eda3e3cd806e2e14" + "sha256": "019b67ce05e7e68766ba54ddbfd3e2faf5dd81c7ded79f80ff3ef85b0017c99d" }, "pipfile-spec": 6, "requires": { @@ -25,6 +25,20 @@ "index": "pypi", "version": "==1.0.7" }, + "appdirs": { + "hashes": [ + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" + ], + "version": "==1.4.3" + }, + "attrs": { + "hashes": [ + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" + ], + "version": "==19.1.0" + }, "backcall": { "hashes": [ "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4", @@ -32,6 +46,14 @@ ], "version": "==0.1.0" }, + "black": { + "hashes": [ + "sha256:09a9dcb7c46ed496a9850b76e4e825d6049ecd38b611f1224857a79bd985a8cf", + "sha256:68950ffd4d9169716bcb8719a56c07a2f4485354fec061cdd5910aa07369731c" + ], + "index": "pypi", + "version": "==19.3b0" + }, "click": { "hashes": [ "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", @@ -86,6 +108,13 @@ "index": "pypi", "version": "==0.8.1" }, + "flake8-quotes": { + "hashes": [ + "sha256:10c9af6b472d4302a8e721c5260856c3f985c5c082b04841aefd2f808ac02038" + ], + "index": "pypi", + "version": "==2.0.1" + }, "greenlet": { "hashes": [ "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0", @@ -304,6 +333,13 @@ ], "version": "==6.10.0" }, + "toml": { + "hashes": [ + "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", + "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" + ], + "version": "==0.10.0" + }, "traitlets": { "hashes": [ "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", diff --git a/README.md b/README.md index 8f42fbd..0fcc6a0 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,17 @@ below (we'll try to keep this up to date!): > their help has been crucial to KMK's success, KMK is not an official Adafruit > project, and the Core team is not compensated by Adafruit for its development. +## Code Style + +KMK uses [Black](https://github.com/psf/black) with a Python 3.6 target and, +[(controversially?)](https://github.com/psf/black/issues/594) single quotes. +Further code styling is enforced with isort and flake8 with several plugins. +`make fix-isort fix-formatting` before a commit is a good idea, and CI will fail +if inbound code does not adhere to these formatting rules. Some exceptions are +found in `setup.cfg` loosening the rules in isolated cases, notably +`user_keymaps` (which is *also* not subject to Black formatting for reasons +documented in `pyproject.toml`). + ## License, Copyright, and Legal All software in this repository is licensed under the [GNU Public License, diff --git a/kmk/handlers/layers.py b/kmk/handlers/layers.py index 599f4d1..8bddbc2 100644 --- a/kmk/handlers/layers.py +++ b/kmk/handlers/layers.py @@ -2,13 +2,17 @@ from kmk.kmktime import ticks_diff, ticks_ms def df_pressed(key, state, *args, **kwargs): - """Switches the default layer""" + ''' + Switches the default layer + ''' state.active_layers[-1] = key.meta.layer return state def mo_pressed(key, state, *args, **kwargs): - """Momentarily activates layer, switches off when you let go""" + ''' + Momentarily activates layer, switches off when you let go + ''' state.active_layers.insert(0, key.meta.layer) return state @@ -32,7 +36,9 @@ def mo_released(key, state, KC, *args, **kwargs): def lm_pressed(key, state, *args, **kwargs): - """As MO(layer) but with mod active""" + ''' + As MO(layer) but with mod active + ''' state.hid_pending = True # Sets the timer start and acts like MO otherwise state.start_time['lm'] = ticks_ms() @@ -41,7 +47,9 @@ def lm_pressed(key, state, *args, **kwargs): def lm_released(key, state, *args, **kwargs): - """As MO(layer) but with mod active""" + ''' + As MO(layer) but with mod active + ''' state.hid_pending = True state.keys_pressed.discard(key.meta.kc) state.start_time['lm'] = None @@ -68,8 +76,9 @@ def lt_released(key, state, *args, **kwargs): def tg_pressed(key, state, *args, **kwargs): - """Toggles the layer (enables it if not active, and vise versa)""" - + ''' + Toggles the layer (enables it if not active, and vise versa) + ''' # See mo_released for implementation details around this try: del_idx = state.active_layers.index(key.meta.layer) @@ -81,7 +90,9 @@ def tg_pressed(key, state, *args, **kwargs): def to_pressed(key, state, *args, **kwargs): - """Activates layer and deactivates all other layers""" + ''' + Activates layer and deactivates all other layers + ''' state.active_layers.clear() state.active_layers.insert(0, key.meta.layer) @@ -89,7 +100,9 @@ def to_pressed(key, state, *args, **kwargs): def tt_pressed(key, state, *args, **kwargs): - """Momentarily activates layer if held, toggles it if tapped repeatedly""" + ''' + Momentarily activates layer if held, toggles it if tapped repeatedly + ''' # TODO Make this work with tap dance to function more correctly, but technically works. if state.start_time['tt'] is None: # Sets the timer start and acts like MO otherwise diff --git a/kmk/keyboard_config.py b/kmk/keyboard_config.py index b4fb95b..e32ce66 100644 --- a/kmk/keyboard_config.py +++ b/kmk/keyboard_config.py @@ -274,10 +274,9 @@ class KeyboardConfig: if self.split_flip and not self.is_master: self.col_pins = list(reversed(self.col_pins)) - - if self.split_side == "Left": + if self.split_side == 'Left': self.split_master_left = self.is_master - elif self.split_side == "Right": + elif self.split_side == 'Right': self.split_master_left = not self.is_master else: self.is_master = True diff --git a/kmk/keys.py b/kmk/keys.py index 1ffb6e5..54ff112 100644 --- a/kmk/keys.py +++ b/kmk/keys.py @@ -361,7 +361,7 @@ def make_argumented_key( else: raise ValueError( 'Argumented key validator failed for unknown reasons. ' - 'This may not be the keymap\'s fault, as a more specific error ' + "This may not be the keymap's fault, as a more specific error " 'should have been raised.', ) @@ -439,7 +439,7 @@ make_key(code=47, names=('LBRACKET', 'LBRC', '[')) make_key(code=48, names=('RBRACKET', 'RBRC', ']')) make_key(code=49, names=('BACKSLASH', 'BSLASH', 'BSLS', '\\')) make_key(code=51, names=('SEMICOLON', 'SCOLON', 'SCLN', ';')) -make_key(code=52, names=('QUOTE', 'QUOT', '\'')) +make_key(code=52, names=('QUOTE', 'QUOT', "'")) make_key(code=53, names=('GRAVE', 'GRV', 'ZKHK', '`')) make_key(code=54, names=('COMMA', 'COMM', ',')) make_key(code=55, names=('DOT', '.')) @@ -539,7 +539,7 @@ make_shifted_key('LBRACKET', names=('LEFT_CURLY_BRACE', 'LCBR', '{')) make_shifted_key('RBRACKET', names=('RIGHT_CURLY_BRACE', 'RCBR', '}')) make_shifted_key('BACKSLASH', names=('PIPE', '|')) make_shifted_key('SEMICOLON', names=('COLON', 'COLN', ':')) -make_shifted_key('QUOTE', names=('DOUBLE_QUOTE', 'DQUO', 'DQT', '\'')) +make_shifted_key('QUOTE', names=('DOUBLE_QUOTE', 'DQUO', 'DQT', '"')) make_shifted_key('COMMA', names=('LEFT_ANGLE_BRACKET', 'LABK', '<')) make_shifted_key('DOT', names=('RIGHT_ANGLE_BRACKET', 'RABK', '>')) make_shifted_key('SLSH', names=('QUESTION', 'QUES', '?')) diff --git a/kmk/led.py b/kmk/led.py index d72456f..4d0e14c 100644 --- a/kmk/led.py +++ b/kmk/led.py @@ -88,20 +88,20 @@ class led: self.set_brightness(0) def increase_ani(self): - """ + ''' Increases animation speed by 1 amount stopping at 10 :param step: - """ + ''' if (self.animation_speed + 1) >= 10: self.animation_speed = 10 else: self.val += 1 def decrease_ani(self): - """ + ''' Decreases animation speed by 1 amount stopping at 0 :param step: - """ + ''' if (self.val - 1) <= 0: self.val = 0 else: @@ -127,10 +127,10 @@ class led: return self def animate(self): - """ + ''' Activates a "step" in the animation based on the active mode :return: Returns the new state in animation - """ + ''' if self.effect_init: self._init_effect() if self.enabled: diff --git a/kmk/rgb.py b/kmk/rgb.py index 1aef3a1..74f8ca0 100644 --- a/kmk/rgb.py +++ b/kmk/rgb.py @@ -97,13 +97,13 @@ class RGB: return int(time.monotonic() * 1000) def hsv_to_rgb(self, hue, sat, val): - """ + ''' Converts HSV values, and returns a tuple of RGB values :param hue: :param sat: :param val: :return: (r, g, b) - """ + ''' r = 0 g = 0 b = 0 @@ -149,24 +149,24 @@ class RGB: return int(r), int(g), int(b) def hsv_to_rgbw(self, hue, sat, val): - """ + ''' Converts HSV values, and returns a tuple of RGBW values :param hue: :param sat: :param val: :return: (r, g, b, w) - """ + ''' rgb = self.hsv_to_rgb(hue, sat, val) return rgb[0], rgb[1], rgb[2], min(rgb) def set_hsv(self, hue, sat, val, index): - """ + ''' Takes HSV values and displays it on a single LED/Neopixel :param hue: :param sat: :param val: :param index: Index of LED/Pixel - """ + ''' if self.neopixel: if self.rgbw: self.set_rgb(self.hsv_to_rgbw(hue, sat, val), index) @@ -176,12 +176,12 @@ class RGB: return self def set_hsv_fill(self, hue, sat, val): - """ + ''' Takes HSV values and displays it on all LEDs/Neopixels :param hue: :param sat: :param val: - """ + ''' if self.neopixel: if self.rgbw: self.set_rgb_fill(self.hsv_to_rgbw(hue, sat, val)) @@ -190,11 +190,11 @@ class RGB: return self def set_rgb(self, rgb, index): - """ + ''' Takes an RGB or RGBW and displays it on a single LED/Neopixel :param rgb: RGB or RGBW :param index: Index of LED/Pixel - """ + ''' if self.neopixel and 0 <= index <= self.num_pixels - 1: self.neopixel[index] = rgb if not self.disable_auto_write: @@ -203,10 +203,10 @@ class RGB: return self def set_rgb_fill(self, rgb): - """ + ''' Takes an RGB or RGBW and displays it on all LEDs/Neopixels :param rgb: RGB or RGBW - """ + ''' if self.neopixel: self.neopixel.fill(rgb) if not self.disable_auto_write: @@ -215,10 +215,10 @@ class RGB: return self def increase_hue(self, step=None): - """ + ''' Increases hue by step amount rolling at 360 and returning to 0 :param step: - """ + ''' if not step: step = self.hue_step @@ -230,10 +230,10 @@ class RGB: return self def decrease_hue(self, step=None): - """ + ''' Decreases hue by step amount rolling at 0 and returning to 360 :param step: - """ + ''' if not step: step = self.hue_step @@ -248,10 +248,10 @@ class RGB: return self def increase_sat(self, step=None): - """ + ''' Increases saturation by step amount stopping at 100 :param step: - """ + ''' if not step: step = self.sat_step @@ -266,10 +266,10 @@ class RGB: return self def decrease_sat(self, step=None): - """ + ''' Decreases saturation by step amount stopping at 0 :param step: - """ + ''' if not step: step = self.sat_step @@ -284,10 +284,10 @@ class RGB: return self def increase_val(self, step=None): - """ + ''' Increases value by step amount stopping at 100 :param step: - """ + ''' if not step: step = self.val_step if (self.val + step) >= 100: @@ -301,10 +301,10 @@ class RGB: return self def decrease_val(self, step=None): - """ + ''' Decreases value by step amount stopping at 0 :param step: - """ + ''' if not step: step = self.val_step if (self.val - step) <= 0: @@ -318,20 +318,20 @@ class RGB: return self def increase_ani(self): - """ + ''' Increases animation speed by 1 amount stopping at 10 :param step: - """ + ''' if (self.animation_speed + 1) >= 10: self.animation_speed = 10 else: self.val += 1 def decrease_ani(self): - """ + ''' Decreases animation speed by 1 amount stopping at 0 :param step: - """ + ''' if (self.val - 1) <= 0: self.val = 0 else: @@ -340,28 +340,28 @@ class RGB: return self def off(self): - """ + ''' Turns off all LEDs/Neopixels without changing stored values - """ + ''' if self.neopixel: self.set_hsv_fill(0, 0, 0) return self def show(self): - """ + ''' Turns on all LEDs/Neopixels without changing stored values - """ + ''' if self.neopixel: self.neopixel.show() return self def animate(self): - """ + ''' Activates a "step" in the animation based on the active mode :return: Returns the new state in animation - """ + ''' if self.effect_init: self._init_effect() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a7c1e5c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,22 @@ +[tool.black] +# since black refuses to allow single-quotes... see locked conversation at +# https://github.com/psf/black/issues/594 +skip-string-normalization = true +target = "py36" +# explicitly exculde user_keymaps from black formatting rules +# because a visually-appealing keymap list will be flattened +# by black into a much harder to understand format +exclude = ''' +/( + \.git + | \.mypy_cache + | \.tox + | \.venv + | \.pytest_cache + | \.compiled + | dist + | build + | docs + | user_keymaps +)/ +''' diff --git a/setup.cfg b/setup.cfg index c8b74b0..d4d6f77 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,13 @@ [flake8] exclude = .git,__pycache__,vendor,.venv,build -max_line_length = 99 +# match black expectations +max_line_length = 88 + +# enforce single quotes +select = Q0 +docstring-quotes = ''' +multiline-quotes = ''' + ignore = X100, E262 per-file-ignores = # Allow crazy line lengths, unused variables, and multiple spaces after commas in lists (for grid alignment) @@ -11,3 +18,8 @@ per-file-ignores = [isort] known_third_party = analogio,bitbangio,bleio,board,busio,digitalio,framebuf,gamepad,gc,microcontroller,micropython,pulseio,pyb,pydux,uio,ubluepy,machine,pyb,uos +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +use_parentheses=True +line_length=88 diff --git a/user_keymaps/kdb424/gherkin.py b/user_keymaps/kdb424/gherkin.py index 615d25d..1d55b55 100644 --- a/user_keymaps/kdb424/gherkin.py +++ b/user_keymaps/kdb424/gherkin.py @@ -70,7 +70,7 @@ keyboard.leader_dictionary = { 'yay': emoticons.YAY, } -WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.") +WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') # ---------------------- Keymap --------------------------------------------------------- diff --git a/user_keymaps/kdb424/klanck.py b/user_keymaps/kdb424/klanck.py index 97c3d1a..9bf8b7f 100644 --- a/user_keymaps/kdb424/klanck.py +++ b/user_keymaps/kdb424/klanck.py @@ -43,7 +43,7 @@ keyboard.leader_dictionary = { 'yay': emoticons.YAY, } -WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.") +WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') # ---------------------- Keymap --------------------------------------------------------- diff --git a/user_keymaps/klardotsh/iris_r2.py b/user_keymaps/klardotsh/iris_r2.py index 892089c..e686a47 100644 --- a/user_keymaps/klardotsh/iris_r2.py +++ b/user_keymaps/klardotsh/iris_r2.py @@ -41,7 +41,7 @@ emoticons = cuss({ 'TABLE_FLIP': r'(╯°□°)╯︵ ┻━┻', }) -WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.") +WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') keyboard.leader_mode = LeaderMode.ENTER keyboard.leader_dictionary = { diff --git a/user_keymaps/klardotsh/klarank_featherm4.py b/user_keymaps/klardotsh/klarank_featherm4.py index b6525c7..c1e5897 100644 --- a/user_keymaps/klardotsh/klarank_featherm4.py +++ b/user_keymaps/klardotsh/klarank_featherm4.py @@ -40,7 +40,7 @@ emoticons = cuss({ 'TABLE_FLIP': r'(╯°□°)╯︵ ┻━┻', }) -WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.") +WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') keyboard.leader_mode = LeaderMode.TIMEOUT keyboard.leader_dictionary = { From aaeaa74a0c998e2277176600891f62d6c238f1c6 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Wed, 24 Jul 2019 22:57:11 -0700 Subject: [PATCH 2/3] Run black against source tree --- kmk/boards/klarank.py | 9 +-- kmk/handlers/layers.py | 4 +- kmk/handlers/modtap.py | 2 +- kmk/handlers/sequences.py | 24 ++---- kmk/hid.py | 9 +-- kmk/internal_state.py | 42 ++++------ kmk/key_validators.py | 9 ++- kmk/keyboard_config.py | 18 ++--- kmk/keys.py | 81 ++++++++++--------- kmk/matrix.py | 14 ++-- kmk/rgb.py | 22 ++--- kmk/types.py | 2 + kmk/util.py | 4 + tests/test_data/keymaps/duplicate_row_pins.py | 12 +-- .../duplicated_pins_between_row_col.py | 12 +-- tests/test_data/keymaps/ghosted_layer_mo.py | 12 +-- tests/test_data/keymaps/known_good.py | 12 +-- util/bootloader.py | 2 + util/reset.py | 2 + 19 files changed, 126 insertions(+), 166 deletions(-) diff --git a/kmk/boards/klarank.py b/kmk/boards/klarank.py index a88c1b2..db3f397 100644 --- a/kmk/boards/klarank.py +++ b/kmk/boards/klarank.py @@ -7,14 +7,7 @@ from kmk.util import intify_coordinate as ic # board, by flipping various row3 (bottom physical row) keys so their # coord_mapping matches what the user pressed (even if the wiring # underneath is sending different coordinates) -_r3_swap_conversions = { - 3: 9, - 4: 10, - 5: 11, - 9: 3, - 10: 4, - 11: 5, -} +_r3_swap_conversions = {3: 9, 4: 10, 5: 11, 9: 3, 10: 4, 11: 5} def r3_swap(col): diff --git a/kmk/handlers/layers.py b/kmk/handlers/layers.py index 8bddbc2..f20b9af 100644 --- a/kmk/handlers/layers.py +++ b/kmk/handlers/layers.py @@ -114,7 +114,9 @@ def tt_pressed(key, state, *args, **kwargs): def tt_released(key, state, *args, **kwargs): - tap_timed_out = ticks_diff(ticks_ms(), state.start_time['tt']) >= state.config.tap_time + tap_timed_out = ( + ticks_diff(ticks_ms(), state.start_time['tt']) >= state.config.tap_time + ) if state.start_time['tt'] is None or tap_timed_out: # On first press, works like MO. On second press, does nothing unless let up within # time window, then acts like TG. diff --git a/kmk/handlers/modtap.py b/kmk/handlers/modtap.py index c88dad4..f81ec0d 100644 --- a/kmk/handlers/modtap.py +++ b/kmk/handlers/modtap.py @@ -14,7 +14,7 @@ def mt_released(key, state, *args, **kwargs): state.keys_pressed.discard(key.meta.mods) timer_name = 'mod_tap' if state.start_time[timer_name] and ( - ticks_diff(ticks_ms(), state.start_time[timer_name]) < state.config.tap_time + ticks_diff(ticks_ms(), state.start_time[timer_name]) < state.config.tap_time ): state.hid_pending = True state.tap_key(key.meta.kc) diff --git a/kmk/handlers/sequences.py b/kmk/handlers/sequences.py index 8f11cbf..9b5d907 100644 --- a/kmk/handlers/sequences.py +++ b/kmk/handlers/sequences.py @@ -64,10 +64,7 @@ def unicode_string_sequence(unistring): Allows sending things like (╯°□°)╯︵ ┻━┻ directly, without manual conversion to Unicode codepoints. ''' - return unicode_codepoint_sequence([ - hex(get_wide_ordinal(s))[2:] - for s in unistring - ]) + return unicode_codepoint_sequence([hex(get_wide_ordinal(s))[2:] for s in unistring]) def generate_codepoint_keysym_seq(codepoint, expected_length=4): @@ -95,31 +92,22 @@ def generate_leader_dictionary_seq(string): def unicode_codepoint_sequence(codepoints): - kc_seqs = ( - generate_codepoint_keysym_seq(codepoint) - for codepoint in codepoints - ) + kc_seqs = (generate_codepoint_keysym_seq(codepoint) for codepoint in codepoints) - kc_macros = [ - simple_key_sequence(kc_seq) - for kc_seq in kc_seqs - ] + kc_macros = [simple_key_sequence(kc_seq) for kc_seq in kc_seqs] def _unicode_sequence(key, state, *args, **kwargs): if state.config.unicode_mode == UnicodeMode.IBUS: state.process_key( - simple_key_sequence(_ibus_unicode_sequence(kc_macros, state)), - True, + simple_key_sequence(_ibus_unicode_sequence(kc_macros, state)), True ) elif state.config.unicode_mode == UnicodeMode.RALT: state.process_key( - simple_key_sequence(_ralt_unicode_sequence(kc_macros, state)), - True, + simple_key_sequence(_ralt_unicode_sequence(kc_macros, state)), True ) elif state.config.unicode_mode == UnicodeMode.WINC: state.process_key( - simple_key_sequence(_winc_unicode_sequence(kc_macros, state)), - True, + simple_key_sequence(_winc_unicode_sequence(kc_macros, state)), True ) return make_key(on_press=_unicode_sequence) diff --git a/kmk/hid.py b/kmk/hid.py index c095628..e2eb2b7 100644 --- a/kmk/hid.py +++ b/kmk/hid.py @@ -22,10 +22,7 @@ class USB_HID: self.post_init() def __repr__(self): - return '{}(REPORT_BYTES={})'.format( - self.__class__.__name__, - self.REPORT_BYTES, - ) + return '{}(REPORT_BYTES={})'.format(self.__class__.__name__, self.REPORT_BYTES) def post_init(self): pass @@ -157,10 +154,12 @@ class USB_HID: try: import usb_hid + PLATFORM_CIRCUITPYTHON = True except ImportError: PLATFORM_CIRCUITPYTHON = False else: + class CircuitPythonUSB_HID(USB_HID): REPORT_BYTES = 9 @@ -192,5 +191,5 @@ else: reporting_device_const = self.report_device[0] return self.devices[reporting_device_const].send_report( - evt[1:HID_REPORT_SIZES[reporting_device_const] + 1], + evt[1 : HID_REPORT_SIZES[reporting_device_const] + 1] ) diff --git a/kmk/internal_state.py b/kmk/internal_state.py index 6a6db5f..c149589 100644 --- a/kmk/internal_state.py +++ b/kmk/internal_state.py @@ -18,13 +18,7 @@ class InternalState: # overhead (the underlying list was never used anyway) active_layers = [0] - start_time = { - 'lt': None, - 'tg': None, - 'tt': None, - 'lm': None, - 'leader': None, - } + start_time = {'lt': None, 'tg': None, 'tt': None, 'lm': None, 'leader': None} timeouts = {} tapping = False tap_dance_counts = {} @@ -72,11 +66,7 @@ class InternalState: except ValueError: if self.config.debug_enabled: print( - 'CoordMappingNotFound(ic={}, row={}, col={})'.format( - ic, - row, - col, - ), + 'CoordMappingNotFound(ic={}, row={}, col={})'.format(ic, row, col) ) return None @@ -128,11 +118,7 @@ class InternalState: def matrix_changed(self, row, col, is_pressed): if self.config.debug_enabled: - print('MatrixChange(col={} row={} pressed={})'.format( - col, - row, - is_pressed, - )) + print('MatrixChange(col={} row={} pressed={})'.format(col, row, is_pressed)) int_coord = intify_coordinate(row, col) kc_changed = self._find_key_in_map(row, col) @@ -189,10 +175,13 @@ class InternalState: return self if ( - changed_key not in self.tap_dance_counts or not self.tap_dance_counts[changed_key] + changed_key not in self.tap_dance_counts + or not self.tap_dance_counts[changed_key] ): self.tap_dance_counts[changed_key] = 1 - self.set_timeout(self.config.tap_time, lambda: self._end_tap_dance(changed_key)) + self.set_timeout( + self.config.tap_time, lambda: self._end_tap_dance(changed_key) + ) self.tapping = True else: self.tap_dance_counts[changed_key] += 1 @@ -201,7 +190,9 @@ class InternalState: self.tap_side_effects[changed_key] = None else: has_side_effects = self.tap_side_effects[changed_key] is not None - hit_max_defined_taps = self.tap_dance_counts[changed_key] == len(changed_key.codes) + hit_max_defined_taps = self.tap_dance_counts[changed_key] == len( + changed_key.codes + ) if has_side_effects or hit_max_defined_taps: self._end_tap_dance(changed_key) @@ -241,7 +232,9 @@ class InternalState: self.config.leader_mode += 1 if self.config.leader_mode == LeaderMode.TIMEOUT_ACTIVE: - self.set_timeout(self.config.leader_timeout, self._handle_leader_sequence) + self.set_timeout( + self.config.leader_timeout, self._handle_leader_sequence + ) return self @@ -256,8 +249,7 @@ class InternalState: self.process_key(self.config.leader_dictionary[lmh], True) self.set_timeout( - False, - lambda: self.remove_key(self.config.leader_dictionary[lmh]), + False, lambda: self.remove_key(self.config.leader_dictionary[lmh]) ) return self @@ -273,9 +265,7 @@ class InternalState: self.leader_last_len = len(self.keys_pressed) for key in keys_pressed: - if ( - self.config.leader_mode == LeaderMode.ENTER_ACTIVE and key == KC.ENT - ): + if self.config.leader_mode == LeaderMode.ENTER_ACTIVE and key == KC.ENT: self._handle_leader_sequence() break elif key == KC.ESC or key == KC.GESC: diff --git a/kmk/key_validators.py b/kmk/key_validators.py index bff9bfd..71af33d 100644 --- a/kmk/key_validators.py +++ b/kmk/key_validators.py @@ -1,5 +1,10 @@ -from kmk.types import (KeySeqSleepMeta, LayerKeyMeta, ModTapKeyMeta, - TapDanceKeyMeta, UnicodeModeKeyMeta) +from kmk.types import ( + KeySeqSleepMeta, + LayerKeyMeta, + ModTapKeyMeta, + TapDanceKeyMeta, + UnicodeModeKeyMeta, +) def key_seq_sleep_validator(ms): diff --git a/kmk/keyboard_config.py b/kmk/keyboard_config.py index e32ce66..5b64f15 100644 --- a/kmk/keyboard_config.py +++ b/kmk/keyboard_config.py @@ -156,12 +156,11 @@ class KeyboardConfig: print(self) print(self._state) - print('GCStats(pre_alloc={} pre_free={} alloc={} free={})'.format( - pre_alloc, - pre_free, - gc.mem_alloc(), - gc.mem_free(), - )) + print( + 'GCStats(pre_alloc={} pre_free={} alloc={} free={})'.format( + pre_alloc, pre_free, gc.mem_alloc(), gc.mem_free() + ) + ) def _send_hid(self): self._hid_helper_inst.create_report(self._state.keys_pressed).send() @@ -183,11 +182,7 @@ class KeyboardConfig: ''' if update is not None: - self._state.matrix_changed( - update[0], - update[1], - update[2], - ) + self._state.matrix_changed(update[0], update[1], update[2]) def _send_to_master(self, update): if self.split_master_left: @@ -202,6 +197,7 @@ class KeyboardConfig: if self.uart.in_waiting >= 60: # This is a dirty hack to prevent crashes in unrealistic cases import microcontroller + microcontroller.reset() while self.uart.in_waiting >= 3: diff --git a/kmk/keys.py b/kmk/keys.py index 54ff112..658a54c 100644 --- a/kmk/keys.py +++ b/kmk/keys.py @@ -4,9 +4,13 @@ import kmk.handlers.layers as layers import kmk.handlers.modtap as modtap import kmk.handlers.stock as handlers from kmk.consts import UnicodeMode -from kmk.key_validators import (key_seq_sleep_validator, layer_key_validator, - mod_tap_validator, tap_dance_key_validator, - unicode_mode_key_validator) +from kmk.key_validators import ( + key_seq_sleep_validator, + layer_key_validator, + mod_tap_validator, + tap_dance_key_validator, + unicode_mode_key_validator, +) from kmk.types import AttrDict, UnicodeModeKeyMeta FIRST_KMK_INTERNAL_KEY = 1000 @@ -231,16 +235,14 @@ class ModifierKey(Key): if modified_code.has_modifiers: new_keycode.has_modifiers |= modified_code.has_modifiers else: - new_keycode = Key( - self.code, - no_press=no_press, - no_release=no_release, - ) + new_keycode = Key(self.code, no_press=no_press, no_release=no_release) return new_keycode def __repr__(self): - return 'ModifierKey(code={}, has_modifiers={})'.format(self.code, self.has_modifiers) + return 'ModifierKey(code={}, has_modifiers={})'.format( + self.code, self.has_modifiers + ) class ConsumerKey(Key): @@ -268,12 +270,7 @@ def register_key_names(key, names=tuple()): # NOQA return key -def make_key( - code=None, - names=tuple(), # NOQA - type=KEY_SIMPLE, - **kwargs, -): +def make_key(code=None, names=tuple(), type=KEY_SIMPLE, **kwargs): # NOQA ''' Create a new key, aliased by `names` in the KC lookup table. @@ -348,10 +345,7 @@ def make_argumented_key( if meta: key = Key( - NEXT_AVAILABLE_KEY, - meta=meta, - *constructor_args, - **constructor_kwargs, + NEXT_AVAILABLE_KEY, meta=meta, *constructor_args, **constructor_kwargs ) NEXT_AVAILABLE_KEY += 1 @@ -362,7 +356,7 @@ def make_argumented_key( raise ValueError( 'Argumented key validator failed for unknown reasons. ' "This may not be the keymap's fault, as a more specific error " - 'should have been raised.', + 'should have been raised.' ) for name in names: @@ -584,7 +578,9 @@ make_consumer_key(code=234, names=('AUDIO_VOL_DOWN', 'VOLD')) # 0xEA make_consumer_key(code=181, names=('MEDIA_NEXT_TRACK', 'MNXT')) # 0xB5 make_consumer_key(code=182, names=('MEDIA_PREV_TRACK', 'MPRV')) # 0xB6 make_consumer_key(code=183, names=('MEDIA_STOP', 'MSTP')) # 0xB7 -make_consumer_key(code=205, names=('MEDIA_PLAY_PAUSE', 'MPLY')) # 0xCD (this may not be right) +make_consumer_key( + code=205, names=('MEDIA_PLAY_PAUSE', 'MPLY') +) # 0xCD (this may not be right) make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT')) # 0xB8 make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD')) # 0xB3 make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4 @@ -596,19 +592,28 @@ make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4 # two keys with the exact same functionality for names in (('NO',), ('TRANSPARENT', 'TRNS')): make_key( - names=names, - on_press=handlers.passthrough, - on_release=handlers.passthrough, + names=names, on_press=handlers.passthrough, on_release=handlers.passthrough ) make_key(names=('RESET',), on_press=handlers.reset) make_key(names=('BOOTLOADER',), on_press=handlers.bootloader) -make_key(names=('DEBUG', 'DBG'), on_press=handlers.debug_pressed, on_release=handlers.passthrough) +make_key( + names=('DEBUG', 'DBG'), + on_press=handlers.debug_pressed, + on_release=handlers.passthrough, +) -make_key(names=('GESC',), on_press=handlers.gesc_pressed, on_release=handlers.gesc_released) -make_key(names=('BKDL',), on_press=handlers.bkdl_pressed, on_release=handlers.bkdl_released) -make_key(names=('GESC', 'GRAVE_ESC'), on_press=handlers.gesc_pressed, - on_release=handlers.gesc_released) +make_key( + names=('GESC',), on_press=handlers.gesc_pressed, on_release=handlers.gesc_released +) +make_key( + names=('BKDL',), on_press=handlers.bkdl_pressed, on_release=handlers.bkdl_released +) +make_key( + names=('GESC', 'GRAVE_ESC'), + on_press=handlers.gesc_pressed, + on_release=handlers.gesc_released, +) make_key(names=('RGB_TOG',), on_press=handlers.rgb_tog) make_key(names=('RGB_HUI',), on_press=handlers.rgb_hui) make_key(names=('RGB_HUD',), on_press=handlers.rgb_hud) @@ -621,8 +626,10 @@ make_key(names=('RGB_AND',), on_press=handlers.rgb_and) make_key(names=('RGB_MODE_PLAIN', 'RGB_M_P'), on_press=handlers.rgb_mode_static) make_key(names=('RGB_MODE_BREATHE', 'RGB_M_B'), on_press=handlers.rgb_mode_breathe) make_key(names=('RGB_MODE_RAINBOW', 'RGB_M_R'), on_press=handlers.rgb_mode_rainbow) -make_key(names=('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'), - on_press=handlers.rgb_mode_breathe_rainbow) +make_key( + names=('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'), + on_press=handlers.rgb_mode_breathe_rainbow, +) make_key(names=('RGB_MODE_SWIRL', 'RGB_M_S'), on_press=handlers.rgb_mode_swirl) make_key(names=('RGB_MODE_KNIGHT', 'RGB_M_K'), on_press=handlers.rgb_mode_knight) @@ -650,9 +657,7 @@ make_argumented_key( on_release=layers.mo_released, ) make_argumented_key( - validator=layer_key_validator, - names=('DF',), - on_press=layers.df_pressed, + validator=layer_key_validator, names=('DF',), on_press=layers.df_pressed ) make_argumented_key( validator=layer_key_validator, @@ -667,14 +672,10 @@ make_argumented_key( on_release=layers.lt_released, ) make_argumented_key( - validator=layer_key_validator, - names=('TG',), - on_press=layers.tg_pressed, + validator=layer_key_validator, names=('TG',), on_press=layers.tg_pressed ) make_argumented_key( - validator=layer_key_validator, - names=('TO',), - on_press=layers.to_pressed, + validator=layer_key_validator, names=('TO',), on_press=layers.to_pressed ) make_argumented_key( validator=layer_key_validator, diff --git a/kmk/matrix.py b/kmk/matrix.py index b142745..81806ec 100644 --- a/kmk/matrix.py +++ b/kmk/matrix.py @@ -5,7 +5,9 @@ from kmk.consts import DiodeOrientation class MatrixScanner: def __init__( - self, cols, rows, + self, + cols, + rows, diode_orientation=DiodeOrientation.COLUMNS, rollover_cols_every_rows=None, ): @@ -33,9 +35,9 @@ class MatrixScanner: self.inputs = self.cols self.translate_coords = False else: - raise ValueError('Invalid DiodeOrientation: {}'.format( - self.diode_orientation, - )) + raise ValueError( + 'Invalid DiodeOrientation: {}'.format(self.diode_orientation) + ) for pin in self.outputs: pin.switch_to_output() @@ -81,7 +83,9 @@ class MatrixScanner: if old_val != new_val: if self.translate_coords: - new_oidx = oidx + self.len_cols * (iidx // self.rollover_cols_every_rows) + new_oidx = oidx + self.len_cols * ( + iidx // self.rollover_cols_every_rows + ) new_iidx = iidx - self.rollover_cols_every_rows * ( iidx // self.rollover_cols_every_rows ) diff --git a/kmk/rgb.py b/kmk/rgb.py index 74f8ca0..7b01815 100644 --- a/kmk/rgb.py +++ b/kmk/rgb.py @@ -51,10 +51,13 @@ class RGB: def __init__(self, config, pixel_pin): try: import neopixel - self.neopixel = neopixel.NeoPixel(pixel_pin, - config['num_pixels'], - pixel_order=config['rgb_order'], - auto_write=False) + + self.neopixel = neopixel.NeoPixel( + pixel_pin, + config['num_pixels'], + pixel_order=config['rgb_order'], + auto_write=False, + ) if len(config['rgb_order']) == 4: self.rgbw = True self.num_pixels = const(config['num_pixels']) @@ -398,7 +401,10 @@ class RGB: return False def _init_effect(self): - if self.animation_mode == 'breathing' or self.animation_mode == 'breathing_rainbow': + if ( + self.animation_mode == 'breathing' + or self.animation_mode == 'breathing_rainbow' + ): self.intervals = (30, 20, 10, 5) elif self.animation_mode == 'swirl': self.intervals = (50, 50) @@ -451,10 +457,8 @@ class RGB: self.disable_auto_write = True # Turn off instantly showing for i in range(0, self.num_pixels): self.set_hsv( - (self.hue - (i * self.num_pixels)) % 360, - self.sat, - self.val, - i) + (self.hue - (i * self.num_pixels)) % 360, self.sat, self.val, i + ) # Show final results self.disable_auto_write = False # Resume showing changes diff --git a/kmk/types.py b/kmk/types.py index 73a6d60..d36b882 100644 --- a/kmk/types.py +++ b/kmk/types.py @@ -6,6 +6,7 @@ class AttrDict(dict): This is read-only on purpose. ''' + def __getattr__(self, key): return self[key] @@ -14,6 +15,7 @@ class Anything: ''' A stub class which will repr as a provided name ''' + def __init__(self, name): self.name = name diff --git a/kmk/util.py b/kmk/util.py index c53c505..9d450a9 100644 --- a/kmk/util.py +++ b/kmk/util.py @@ -24,19 +24,23 @@ def flatten_dict(d): def reset_keyboard(): try: import machine + machine.reset() except ImportError: import microcontroller + microcontroller.reset() def reset_bootloader(): try: import machine + machine.bootloader() except ImportError: import microcontroller + microcontroller.on_next_reset(microcontroller.RunMode.BOOTLOADER) microcontroller.reset() diff --git a/tests/test_data/keymaps/duplicate_row_pins.py b/tests/test_data/keymaps/duplicate_row_pins.py index 62d7c59..d82c928 100644 --- a/tests/test_data/keymaps/duplicate_row_pins.py +++ b/tests/test_data/keymaps/duplicate_row_pins.py @@ -16,14 +16,6 @@ keymap = [ [KC.MO(2), KC.I, KC.ENTER], [KC.LCTRL, KC.SPACE, KC.LSHIFT], ], - [ - [KC.TRNS, KC.B, KC.C], - [KC.NO, KC.D, KC.E], - [KC.F, KC.G, KC.H], - ], - [ - [KC.X, KC.Y, KC.Z], - [KC.TRNS, KC.N, KC.O], - [KC.R, KC.P, KC.Q], - ], + [[KC.TRNS, KC.B, KC.C], [KC.NO, KC.D, KC.E], [KC.F, KC.G, KC.H]], + [[KC.X, KC.Y, KC.Z], [KC.TRNS, KC.N, KC.O], [KC.R, KC.P, KC.Q]], ] diff --git a/tests/test_data/keymaps/duplicated_pins_between_row_col.py b/tests/test_data/keymaps/duplicated_pins_between_row_col.py index c31ed64..799333e 100644 --- a/tests/test_data/keymaps/duplicated_pins_between_row_col.py +++ b/tests/test_data/keymaps/duplicated_pins_between_row_col.py @@ -16,14 +16,6 @@ keymap = [ [KC.MO(2), KC.I, KC.ENTER], [KC.LCTRL, KC.SPACE, KC.LSHIFT], ], - [ - [KC.TRNS, KC.B, KC.C], - [KC.NO, KC.D, KC.E], - [KC.F, KC.G, KC.H], - ], - [ - [KC.X, KC.Y, KC.Z], - [KC.TRNS, KC.N, KC.O], - [KC.R, KC.P, KC.Q], - ], + [[KC.TRNS, KC.B, KC.C], [KC.NO, KC.D, KC.E], [KC.F, KC.G, KC.H]], + [[KC.X, KC.Y, KC.Z], [KC.TRNS, KC.N, KC.O], [KC.R, KC.P, KC.Q]], ] diff --git a/tests/test_data/keymaps/ghosted_layer_mo.py b/tests/test_data/keymaps/ghosted_layer_mo.py index 445284e..1e11b18 100644 --- a/tests/test_data/keymaps/ghosted_layer_mo.py +++ b/tests/test_data/keymaps/ghosted_layer_mo.py @@ -16,14 +16,6 @@ keymap = [ [KC.MO(2), KC.I, KC.ENTER], [KC.LCTRL, KC.SPACE, KC.LSHIFT], ], - [ - [KC.A, KC.B, KC.C], - [KC.NO, KC.D, KC.E], - [KC.F, KC.G, KC.H], - ], - [ - [KC.X, KC.Y, KC.Z], - [KC.TRNS, KC.N, KC.O], - [KC.R, KC.P, KC.Q], - ], + [[KC.A, KC.B, KC.C], [KC.NO, KC.D, KC.E], [KC.F, KC.G, KC.H]], + [[KC.X, KC.Y, KC.Z], [KC.TRNS, KC.N, KC.O], [KC.R, KC.P, KC.Q]], ] diff --git a/tests/test_data/keymaps/known_good.py b/tests/test_data/keymaps/known_good.py index 74281c9..0ed5001 100644 --- a/tests/test_data/keymaps/known_good.py +++ b/tests/test_data/keymaps/known_good.py @@ -16,14 +16,6 @@ keymap = [ [KC.MO(2), KC.I, KC.ENTER], [KC.LCTRL, KC.SPACE, KC.LSHIFT], ], - [ - [KC.TRNS, KC.B, KC.C], - [KC.NO, KC.D, KC.E], - [KC.F, KC.G, KC.H], - ], - [ - [KC.X, KC.Y, KC.Z], - [KC.TRNS, KC.N, KC.O], - [KC.R, KC.P, KC.Q], - ], + [[KC.TRNS, KC.B, KC.C], [KC.NO, KC.D, KC.E], [KC.F, KC.G, KC.H]], + [[KC.X, KC.Y, KC.Z], [KC.TRNS, KC.N, KC.O], [KC.R, KC.P, KC.Q]], ] diff --git a/util/bootloader.py b/util/bootloader.py index 064d74c..18a2635 100644 --- a/util/bootloader.py +++ b/util/bootloader.py @@ -1,8 +1,10 @@ try: import machine + machine.bootloader() except ImportError: import microcontroller + microcontroller.on_next_reset(microcontroller.RunMode.BOOTLOADER) microcontroller.reset() diff --git a/util/reset.py b/util/reset.py index 4003007..5c0f63b 100644 --- a/util/reset.py +++ b/util/reset.py @@ -1,7 +1,9 @@ try: import machine + machine.reset() except ImportError: import microcontroller + microcontroller.reset() From 64267bdc5ba149fe4edbc819087dee827b57b258 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Wed, 24 Jul 2019 23:15:57 -0700 Subject: [PATCH 3/3] fix a totally unrelated bug --- kmk/led.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmk/led.py b/kmk/led.py index 4d0e14c..9921ad1 100644 --- a/kmk/led.py +++ b/kmk/led.py @@ -35,7 +35,7 @@ class led: self.animation_mode = const(config['animation_mode']) self.animation_speed = const(config['animation_speed']) self.breathe_center = const(config['breathe_center']) - if config['user_animation']: + if config.get('user_animation'): self.user_animation = config['user_animation'] def __repr__(self):