Skip to content

change to ruff #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 16, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

.py text eol=lf
.rst text eol=lf
.txt text eol=lf
.yaml text eol=lf
.toml text eol=lf
.license text eol=lf
.md text eol=lf
43 changes: 11 additions & 32 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,42 +1,21 @@
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

repos:
- repo: https://github.com/python/black
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/fsfe/reuse-tool
rev: v1.1.2
hooks:
- id: reuse
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/pylint
rev: v2.17.4
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4
hooks:
- id: pylint
name: pylint (library code)
types: [python]
args:
- --disable=consider-using-f-string
exclude: "^(docs/|examples/|tests/|setup.py$)"
- id: pylint
name: pylint (example code)
description: Run pylint rules on "examples/*.py" files
types: [python]
files: "^examples/"
args:
- --disable=missing-docstring,invalid-name,consider-using-f-string,duplicate-code
- id: pylint
name: pylint (test code)
description: Run pylint rules on "tests/*.py" files
types: [python]
files: "^tests/"
args:
- --disable=missing-docstring,consider-using-f-string,duplicate-code
- id: ruff-format
- id: ruff
args: ["--fix"]
- repo: https://github.com/fsfe/reuse-tool
rev: v3.0.1
hooks:
- id: reuse
399 changes: 0 additions & 399 deletions .pylintrc

This file was deleted.

6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -17,9 +17,9 @@ Introduction
:alt: Build Status


.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Code Style: Black
.. image:: https://img.shields.io/endpoint?url=https://github.com/raw/astral-sh/ruff/main/assets/badge/v2.json
:target: https://github.com/astral-sh/ruff
:alt: Code Style: Ruff

A helper library for the Adafruit MacroPad RP2040.

54 changes: 24 additions & 30 deletions adafruit_macropad.py
Original file line number Diff line number Diff line change
@@ -49,39 +49,41 @@
import array
import math
import time

import adafruit_midi
import audiocore
import audiomp3
import audiopwmio
import board
import digitalio
import rotaryio
import displayio
import keypad
import neopixel
import displayio
import audiopwmio
import audiocore
import audiomp3
import rotaryio
import usb_hid
import usb_midi
from adafruit_debouncer import Debouncer
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_base import KeyboardLayoutBase
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from adafruit_hid.mouse import Mouse
import usb_midi
import adafruit_midi
from adafruit_midi.note_on import NoteOn
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
from adafruit_midi.pitch_bend import PitchBend
from adafruit_midi.control_change import ControlChange
from adafruit_midi.program_change import ProgramChange
from adafruit_simple_text_display import SimpleTextDisplay
from adafruit_debouncer import Debouncer

try:
# Only used for typing
from typing import Tuple, Optional, Union, Iterator
from neopixel import NeoPixel
from typing import Iterator, Optional, Tuple, Union

import adafruit_hid
from keypad import Keys
import adafruit_hid # pylint:disable=ungrouped-imports
from neopixel import NeoPixel
except ImportError:
pass

@@ -113,9 +115,7 @@ class _PixelMapLite:
def __init__(
self,
pixels: NeoPixel,
order: Tuple[
int, int, int, int, int, int, int, int, int, int, int, int
] = ROTATED_KEYMAP_0,
order: Tuple[int, int, int, int, int, int, int, int, int, int, int, int] = ROTATED_KEYMAP_0,
):
self._pixels = pixels
self._order = order
@@ -134,8 +134,7 @@ def __setitem__(self, index: int, val: int) -> None:
def __getitem__(self, index: int) -> int:
if isinstance(index, slice):
return [
self._pixels[self._order[idx]]
for idx in range(*index.indices(self._num_pixels))
self._pixels[self._order[idx]] for idx in range(*index.indices(self._num_pixels))
]
if index < 0:
index += self._num_pixels
@@ -171,7 +170,6 @@ def brightness(self, value: float) -> None:
self._pixels.brightness = value


# pylint: disable=too-many-lines, disable=invalid-name, too-many-instance-attributes, too-many-public-methods, too-many-arguments
class MacroPad:
"""
Class representing a single MacroPad.
@@ -283,10 +281,8 @@ def __init__(
self._mouse = None
self._layout_class = layout_class
self.Keycode = keycode_class
# pylint:disable=global-statement
global keycodes
keycodes = keycode_class
# pylint:enable=global-statement

# Define MIDI:
try:
@@ -315,13 +311,13 @@ def rotate(self, rotation):
is to the left, ``180`` is when the USB port is at the bottom, and
``270`` is when the USB port is to the right. Defaults to ``0``.
"""
if rotation not in (0, 90, 180, 270):
if rotation not in {0, 90, 180, 270}:
raise ValueError("Only 90 degree rotations are supported.")

self._rotation = rotation

def _keys_and_pixels(
order: Tuple[int, int, int, int, int, int, int, int, int, int, int, int]
order: Tuple[int, int, int, int, int, int, int, int, int, int, int, int],
) -> None:
"""
Generate key and pixel maps based on a specified order.
@@ -793,9 +789,7 @@ def PitchBend(pitch_bend: int, *, channel: Optional[int] = None) -> PitchBend:
return PitchBend(pitch_bend=pitch_bend, channel=channel)

@staticmethod
def ControlChange(
control: int, value: int, *, channel: Optional[int] = None
) -> ControlChange:
def ControlChange(control: int, value: int, *, channel: Optional[int] = None) -> ControlChange:
"""
Control Change MIDI message. For more details, see the ``adafruit_midi.control_change``
documentation in CircuitPython MIDI:
@@ -1081,15 +1075,15 @@ def play_file(self, file_name: str) -> None:
if file_name.lower().endswith(".wav"):
with audiopwmio.PWMAudioOut(board.SPEAKER) as audio, open(
file_name, "rb"
) as audio_file: # pylint: disable=not-callable
) as audio_file:
wavefile = audiocore.WaveFile(audio_file)
audio.play(wavefile)
while audio.playing:
pass
elif file_name.lower().endswith(".mp3"):
with audiopwmio.PWMAudioOut(board.SPEAKER) as audio, open(
file_name, "rb"
) as audio_file: # pylint: disable=not-callable
) as audio_file:
mp3file = audiomp3.MP3Decoder(audio_file)
audio.play(mp3file)
while audio.playing:
3 changes: 3 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@
.. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py)
.. use this format as the module name: "adafruit_foo.foo"
API Reference
#############

.. automodule:: adafruit_macropad
:members:

8 changes: 2 additions & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import datetime
import os
import sys
import datetime

sys.path.insert(0, os.path.abspath(".."))

@@ -67,9 +65,7 @@
creation_year = "2021"
current_year = str(datetime.datetime.now().year)
year_duration = (
current_year
if current_year == creation_year
else creation_year + " - " + current_year
current_year if current_year == creation_year else creation_year + " - " + current_year
)
copyright = year_duration + " Kattni Rembor"
author = "Kattni Rembor"
1 change: 1 addition & 0 deletions examples/macropad_display_image/macropad_display_image.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
"""
MacroPad display image demo. Displays a bitmap image on the built-in display.
"""

from adafruit_macropad import MacroPad

macropad = MacroPad()
4 changes: 3 additions & 1 deletion examples/macropad_grid_layout.py
Original file line number Diff line number Diff line change
@@ -5,10 +5,12 @@
Grid layout demo for MacroPad. Displays the key pressed in a grid matching the key layout on the
built-in display.
"""

import displayio
import terminalio
from adafruit_display_text import bitmap_label as label
from adafruit_displayio_layout.layouts.grid_layout import GridLayout

from adafruit_macropad import MacroPad

macropad = MacroPad()
@@ -39,6 +41,6 @@
key_event = macropad.keys.events.get()
if key_event:
if key_event.pressed:
labels[key_event.key_number].text = "KEY{}".format(key_event.key_number)
labels[key_event.key_number].text = f"KEY{key_event.key_number}"
else:
labels[key_event.key_number].text = ""
8 changes: 5 additions & 3 deletions examples/macropad_keyboard_layout.py
Original file line number Diff line number Diff line change
@@ -4,9 +4,12 @@
"""
International layout demo for MacroPad.
"""

import time

from keyboard_layout_win_fr import KeyboardLayout
from keycode_win_fr import Keycode

from adafruit_macropad import MacroPad

macropad = MacroPad(
@@ -39,7 +42,6 @@
macropad.keyboard.press(keycode)
else:
macropad.keyboard_layout.write(keycode)
else:
if isinstance(keycode, int):
macropad.keyboard.release(keycode)
elif isinstance(keycode, int):
macropad.keyboard.release(keycode)
time.sleep(0.05)
5 changes: 2 additions & 3 deletions examples/macropad_keyboard_mouse.py
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
pressed. Finally, it moves the mouse left and right when the rotary encoder is rotated
counterclockwise and clockwise respectively.
"""

from adafruit_macropad import MacroPad

macropad = MacroPad()
@@ -26,9 +27,7 @@
if key_event.key_number == 2:
macropad.keyboard_layout.write("Hello, World!")
if key_event.key_number == 3:
macropad.consumer_control.send(
macropad.ConsumerControlCode.VOLUME_DECREMENT
)
macropad.consumer_control.send(macropad.ConsumerControlCode.VOLUME_DECREMENT)

macropad.encoder_switch_debounced.update()

2 changes: 2 additions & 0 deletions examples/macropad_led_animation_example.py
Original file line number Diff line number Diff line change
@@ -5,8 +5,10 @@
This simpletest example displays the Blink animation on the
MacroPad neopixels
"""

from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.color import BLUE

from adafruit_macropad import MacroPad

macropad = MacroPad()
6 changes: 3 additions & 3 deletions examples/macropad_mp3/macropad_mp3.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,9 @@
is pressed. All keys light up a color of the rainbow when pressed, but no audio is played for the
rest of the keys.
"""

from rainbowio import colorwheel

from adafruit_macropad import MacroPad

macropad = MacroPad()
@@ -20,9 +22,7 @@

if key_event:
if key_event.pressed:
macropad.pixels[key_event.key_number] = colorwheel(
int(255 / 12) * key_event.key_number
)
macropad.pixels[key_event.key_number] = colorwheel(int(255 / 12) * key_event.key_number)
if key_event.key_number < len(audio_files):
macropad.play_file(audio_files[key_event.key_number])

6 changes: 4 additions & 2 deletions examples/macropad_rainbow_keys.py
Original file line number Diff line number Diff line change
@@ -6,11 +6,13 @@
layout on the built-in display, and animates a rainbow the first time you press a key and turns it
off on the next press.
"""

import displayio
import terminalio
from rainbowio import colorwheel
from adafruit_display_text import bitmap_label as label
from adafruit_displayio_layout.layouts.grid_layout import GridLayout
from rainbowio import colorwheel

from adafruit_macropad import MacroPad

macropad = MacroPad()
@@ -43,7 +45,7 @@
key_event = macropad.keys.events.get()
if key_event:
if key_event.pressed:
labels[key_event.key_number].text = "KEY{}".format(key_event.key_number)
labels[key_event.key_number].text = f"KEY{key_event.key_number}"
# Turn the LED on with the first press, and off with the second press.
lit_keys[key_event.key_number] = not lit_keys[key_event.key_number]
else:
10 changes: 5 additions & 5 deletions examples/macropad_rotation.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,9 @@
Lights up the associated pixel when the key is pressed. Displays the key number pressed and the
rotary encoder relative position on the display.
"""

from rainbowio import colorwheel

from adafruit_macropad import MacroPad

macropad = MacroPad(rotation=90)
@@ -17,11 +19,9 @@
key_event = macropad.keys.events.get()
if key_event:
if key_event.pressed:
text_lines[1].text = "Key {}!".format(key_event.key_number)
macropad.pixels[key_event.key_number] = colorwheel(
int(255 / 12) * key_event.key_number
)
text_lines[1].text = f"Key {key_event.key_number}!"
macropad.pixels[key_event.key_number] = colorwheel(int(255 / 12) * key_event.key_number)
else:
macropad.pixels.fill((0, 0, 0))
text_lines[2].text = "Encoder {}".format(macropad.encoder)
text_lines[2].text = f"Encoder {macropad.encoder}"
text_lines.show()
8 changes: 5 additions & 3 deletions examples/macropad_simpletest.py
Original file line number Diff line number Diff line change
@@ -5,15 +5,17 @@
Simpletest demo for MacroPad. Prints the key pressed, the relative position of the rotary
encoder, and the state of the rotary encoder switch to the serial console.
"""

import time

from adafruit_macropad import MacroPad

macropad = MacroPad()

while True:
key_event = macropad.keys.events.get()
if key_event and key_event.pressed:
print("Key pressed: {}".format(key_event.key_number))
print("Encoder: {}".format(macropad.encoder))
print("Encoder switch: {}".format(macropad.encoder_switch))
print(f"Key pressed: {key_event.key_number}")
print(f"Encoder: {macropad.encoder}")
print(f"Encoder switch: {macropad.encoder_switch}")
time.sleep(0.4)
7 changes: 4 additions & 3 deletions examples/macropad_simpletest_display.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
encoder, and the state of the rotary encoder switch to the built-in display. Note that the key
pressed line does not appear until a key is pressed.
"""

from adafruit_macropad import MacroPad

macropad = MacroPad()
@@ -15,7 +16,7 @@
while True:
key_event = macropad.keys.events.get()
if key_event and key_event.pressed:
text_lines[0].text = "Key {} pressed!".format(key_event.key_number)
text_lines[1].text = "Rotary encoder {}".format(macropad.encoder)
text_lines[2].text = "Encoder switch: {}".format(macropad.encoder_switch)
text_lines[0].text = f"Key {key_event.key_number} pressed!"
text_lines[1].text = f"Rotary encoder {macropad.encoder}"
text_lines[2].text = f"Encoder switch: {macropad.encoder_switch}"
text_lines.show()
6 changes: 3 additions & 3 deletions examples/macropad_tone_keypad.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,9 @@
MacroPad tone demo. Plays a different tone for each key pressed and lights up each key a different
color while the key is pressed.
"""

from rainbowio import colorwheel

from adafruit_macropad import MacroPad

macropad = MacroPad()
@@ -17,9 +19,7 @@

if key_event:
if key_event.pressed:
macropad.pixels[key_event.key_number] = colorwheel(
int(255 / 12) * key_event.key_number
)
macropad.pixels[key_event.key_number] = colorwheel(int(255 / 12) * key_event.key_number)
macropad.start_tone(tones[key_event.key_number])

else:
9 changes: 4 additions & 5 deletions examples/macropad_tone_keypad_extended.py
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
"""

from rainbowio import colorwheel

from adafruit_macropad import MacroPad

macropad = MacroPad()
@@ -79,11 +80,9 @@ def rgb_from_int(rgb):
playing_index = top_index

# There are no keys pressed.
else:
# If a tone was playing, stop it.
if playing_index is not None:
macropad.stop_tone()
playing_index = None
elif playing_index is not None:
macropad.stop_tone()
playing_index = None

# If a key was pressed or released, update the pixels for the pressed keys.
if update_pixels:
109 changes: 109 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT

target-version = "py38"
line-length = 100

[lint]
preview = true
select = ["I", "PL", "UP"]

extend-select = [
"D419", # empty-docstring
"E501", # line-too-long
"W291", # trailing-whitespace
"PLC0414", # useless-import-alias
"PLC2401", # non-ascii-name
"PLC2801", # unnecessary-dunder-call
"PLC3002", # unnecessary-direct-lambda-call
"E999", # syntax-error
"PLE0101", # return-in-init
"F706", # return-outside-function
"F704", # yield-outside-function
"PLE0116", # continue-in-finally
"PLE0117", # nonlocal-without-binding
"PLE0241", # duplicate-bases
"PLE0302", # unexpected-special-method-signature
"PLE0604", # invalid-all-object
"PLE0605", # invalid-all-format
"PLE0643", # potential-index-error
"PLE0704", # misplaced-bare-raise
"PLE1141", # dict-iter-missing-items
"PLE1142", # await-outside-async
"PLE1205", # logging-too-many-args
"PLE1206", # logging-too-few-args
"PLE1307", # bad-string-format-type
"PLE1310", # bad-str-strip-call
"PLE1507", # invalid-envvar-value
"PLE2502", # bidirectional-unicode
"PLE2510", # invalid-character-backspace
"PLE2512", # invalid-character-sub
"PLE2513", # invalid-character-esc
"PLE2514", # invalid-character-nul
"PLE2515", # invalid-character-zero-width-space
"PLR0124", # comparison-with-itself
"PLR0202", # no-classmethod-decorator
"PLR0203", # no-staticmethod-decorator
"UP004", # useless-object-inheritance
"PLR0206", # property-with-parameters
"PLR0904", # too-many-public-methods
"PLR0911", # too-many-return-statements
"PLR0912", # too-many-branches
"PLR0913", # too-many-arguments
"PLR0914", # too-many-locals
"PLR0915", # too-many-statements
"PLR0916", # too-many-boolean-expressions
"PLR1702", # too-many-nested-blocks
"PLR1704", # redefined-argument-from-local
"PLR1711", # useless-return
"C416", # unnecessary-comprehension
"PLR1733", # unnecessary-dict-index-lookup
"PLR1736", # unnecessary-list-index-lookup

# ruff reports this rule is unstable
#"PLR6301", # no-self-use

"PLW0108", # unnecessary-lambda
"PLW0120", # useless-else-on-loop
"PLW0127", # self-assigning-variable
"PLW0129", # assert-on-string-literal
"B033", # duplicate-value
"PLW0131", # named-expr-without-context
"PLW0245", # super-without-brackets
"PLW0406", # import-self
"PLW0602", # global-variable-not-assigned
"PLW0603", # global-statement
"PLW0604", # global-at-module-level

# fails on the try: import typing used by libraries
#"F401", # unused-import

"F841", # unused-variable
"E722", # bare-except
"PLW0711", # binary-op-exception
"PLW1501", # bad-open-mode
"PLW1508", # invalid-envvar-default
"PLW1509", # subprocess-popen-preexec-fn
"PLW2101", # useless-with-lock
"PLW3301", # nested-min-max
]

ignore = [
"PLR2004", # magic-value-comparison
"UP030", # format literals
"PLW1514", # unspecified-encoding
"PLR0913", # too-many-arguments
"PLR0915", # too-many-statements
"PLR0917", # too-many-positional-arguments
"PLR0904", # too-many-public-methods
"PLR0912", # too-many-branches
"PLR0916", # too-many-boolean-expressions
"PLR6301", # could-be-static no-self-use
"PLC0415", # import outside toplevel
"PLC2701", # private import
"PLW0603", # global statement
]

[format]
line-ending = "lf"