diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..21c125c --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 374676d..f27b786 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,42 +1,22 @@ # SPDX-FileCopyrightText: 2020 Diego Elio Pettenò +# SPDX-FileCopyrightText: 2024 Justin Myers # # 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: v3.3.1 + - 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 diff --git a/README.rst b/README.rst index 7828bef..f88b195 100644 --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ Introduction :target: https://github.com/adafruit/Adafruit_CircuitPython_Display_Button/actions :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://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json + :target: https://github.com/astral-sh/ruff + :alt: Code Style: Ruff UI Buttons for displayio diff --git a/adafruit_button/__init__.py b/adafruit_button/__init__.py index 2fa5ba8..f521f2e 100644 --- a/adafruit_button/__init__.py +++ b/adafruit_button/__init__.py @@ -20,4 +20,5 @@ https://github.com/adafruit/circuitpython/releases """ + from adafruit_button.button import Button diff --git a/adafruit_button/button.py b/adafruit_button/button.py index 1ab13f0..2e2f3ec 100644 --- a/adafruit_button/button.py +++ b/adafruit_button/button.py @@ -22,15 +22,17 @@ """ -from micropython import const from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.roundrect import RoundRect +from micropython import const + from adafruit_button.button_base import ButtonBase, _check_color try: - from typing import Optional, Union, Tuple - from fontio import FontProtocol + from typing import Optional, Tuple, Union + from displayio import Group + from fontio import FontProtocol except ImportError: pass @@ -39,7 +41,6 @@ class Button(ButtonBase): - # pylint: disable=too-many-instance-attributes, too-many-locals """Helper class for creating UI buttons for ``displayio``. Provides the following buttons: RECT: A rectangular button. SHAWDOWRECT adds a drop shadow. @@ -100,9 +101,7 @@ def _create_body(self) -> None: outline=self._outline_color, ) elif self.style == Button.SHADOWRECT: - self.shadow = Rect( - 2, 2, self.width - 2, self.height - 2, fill=self.outline_color - ) + self.shadow = Rect(2, 2, self.width - 2, self.height - 2, fill=self.outline_color) self.body = Rect( 0, 0, @@ -137,7 +136,7 @@ def _create_body(self) -> None: SHADOWRECT = const(2) SHADOWROUNDRECT = const(3) - def __init__( + def __init__( # noqa: PLR0913 Too many arguments self, *, x: int, @@ -154,7 +153,7 @@ def __init__( selected_fill: Optional[Union[int, Tuple[int, int, int]]] = None, selected_outline: Optional[Union[int, Tuple[int, int, int]]] = None, selected_label: Optional[Union[int, Tuple[int, int, int]]] = None, - label_scale: Optional[int] = 1 + label_scale: Optional[int] = 1, ): super().__init__( x=x, diff --git a/adafruit_button/button_base.py b/adafruit_button/button_base.py index d118d04..ce54eee 100644 --- a/adafruit_button/button_base.py +++ b/adafruit_button/button_base.py @@ -21,12 +21,14 @@ https://github.com/adafruit/circuitpython/releases """ + +import terminalio from adafruit_display_text.bitmap_label import Label from displayio import Group -import terminalio try: - from typing import Optional, Union, Tuple + from typing import Optional, Tuple, Union + from fontio import FontProtocol except ImportError: pass @@ -41,7 +43,6 @@ def _check_color(color: Optional[Union[int, tuple[int, int, int]]]) -> int: class ButtonBase(Group): - # pylint: disable=too-many-instance-attributes """Superclass for creating UI buttons for ``displayio``. :param int x: The x position of the button. @@ -60,7 +61,7 @@ class ButtonBase(Group): :param Optional[int] label_scale: The scale factor used for the label. Defaults to 1. """ - def __init__( + def __init__( # noqa: PLR0913 Too many arguments self, *, x: int, @@ -109,10 +110,8 @@ def label(self, newtext: str) -> None: dims[2] *= self._label.scale dims[3] *= self._label.scale if dims[2] >= self.width or dims[3] >= self.height: - while len(self._label.text) > 1 and ( - dims[2] >= self.width or dims[3] >= self.height - ): - self._label.text = "{}.".format(self._label.text[:-2]) + while len(self._label.text) > 1 and (dims[2] >= self.width or dims[3] >= self.height): + self._label.text = f"{self._label.text[:-2]}." dims = list(self._label.bounding_box) dims[2] *= self._label.scale dims[3] *= self._label.scale @@ -120,9 +119,7 @@ def label(self, newtext: str) -> None: raise RuntimeError("Button not large enough for label") self._label.x = (self.width - dims[2]) // 2 self._label.y = self.height // 2 - self._label.color = ( - self._label_color if not self.selected else self._selected_label - ) + self._label.color = self._label_color if not self.selected else self._selected_label self.append(self._label) if (self.selected_label is None) and (self._label_color is not None): diff --git a/adafruit_button/sprite_button.py b/adafruit_button/sprite_button.py index 337466a..4ca220f 100644 --- a/adafruit_button/sprite_button.py +++ b/adafruit_button/sprite_button.py @@ -21,12 +21,15 @@ https://github.com/adafruit/circuitpython/releases """ -from adafruit_imageload.tilegrid_inflator import inflate_tilegrid + from adafruit_imageload import load +from adafruit_imageload.tilegrid_inflator import inflate_tilegrid + from adafruit_button.button_base import ButtonBase try: - from typing import Optional, Union, Tuple + from typing import Optional, Tuple, Union + from fontio import FontProtocol except ImportError: pass @@ -56,7 +59,7 @@ class SpriteButton(ButtonBase): :param Optional[int] label_scale: The scale multiplier of the button label. Defaults to 1. """ - def __init__( + def __init__( # noqa: PLR0913 Too many arguments self, *, x: int, @@ -71,7 +74,7 @@ def __init__( bmp_path: str = None, selected_bmp_path: Optional[str] = None, transparent_index: Optional[Union[int, Tuple]] = None, - label_scale: Optional[int] = 1 + label_scale: Optional[int] = 1, ): if bmp_path is None: raise ValueError("Please supply bmp_path. It cannot be None.") diff --git a/docs/conf.py b/docs/conf.py index 56878d6..d657c39 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,12 +1,10 @@ -# -*- coding: utf-8 -*- - # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries # # SPDX-License-Identifier: MIT +import datetime import os import sys -import datetime sys.path.insert(0, os.path.abspath("..")) @@ -48,9 +46,7 @@ creation_year = "2019" 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 + " Limor Fried" author = "Limor Fried" diff --git a/examples/display_button_color_properties.py b/examples/display_button_color_properties.py index d8bf92f..9ad73a0 100644 --- a/examples/display_button_color_properties.py +++ b/examples/display_button_color_properties.py @@ -6,10 +6,11 @@ properties after the button has been initialized. """ +import adafruit_touchscreen import board import displayio import terminalio -import adafruit_touchscreen + from adafruit_button import Button # use built in display (MagTag, PyPortal, PyGamer, PyBadge, CLUE, etc.) diff --git a/examples/display_button_customfont.py b/examples/display_button_customfont.py index 189af96..eb6a3ae 100644 --- a/examples/display_button_customfont.py +++ b/examples/display_button_customfont.py @@ -5,10 +5,12 @@ """ import os + +import adafruit_touchscreen import board import displayio from adafruit_bitmap_font import bitmap_font -import adafruit_touchscreen + from adafruit_button import Button # use built in display (MagTag, PyPortal, PyGamer, PyBadge, CLUE, etc.) diff --git a/examples/display_button_simpletest.py b/examples/display_button_simpletest.py index fa388f3..f8d8546 100644 --- a/examples/display_button_simpletest.py +++ b/examples/display_button_simpletest.py @@ -4,10 +4,11 @@ Simple button example. """ +import adafruit_touchscreen import board import displayio import terminalio -import adafruit_touchscreen + from adafruit_button import Button # use built in display (MagTag, PyPortal, PyGamer, PyBadge, CLUE, etc.) diff --git a/examples/display_button_soundboard.py b/examples/display_button_soundboard.py index 2fd0bad..ef52c8a 100644 --- a/examples/display_button_soundboard.py +++ b/examples/display_button_soundboard.py @@ -5,7 +5,9 @@ """ import time + from adafruit_pyportal import PyPortal + from adafruit_button import Button SHOW_BUTTONS = False diff --git a/examples/display_button_spritebutton_simpletest.py b/examples/display_button_spritebutton_simpletest.py index 838ed30..1836d67 100644 --- a/examples/display_button_spritebutton_simpletest.py +++ b/examples/display_button_spritebutton_simpletest.py @@ -1,10 +1,12 @@ # SPDX-FileCopyrightText: 2022 Tim Cocks for Adafruit Industries # SPDX-License-Identifier: MIT import time + +import adafruit_touchscreen import board import displayio -import adafruit_touchscreen import terminalio + from adafruit_button.sprite_button import SpriteButton # These pins are used as both analog and digital! XL, XR and YU must be analog diff --git a/examples/display_button_spritebutton_tft_featherwing_simpletest.py b/examples/display_button_spritebutton_tft_featherwing_simpletest.py index bac2cf7..006fd51 100644 --- a/examples/display_button_spritebutton_tft_featherwing_simpletest.py +++ b/examples/display_button_spritebutton_tft_featherwing_simpletest.py @@ -1,12 +1,14 @@ # SPDX-FileCopyrightText: 2024 DJDevon3 # SPDX-License-Identifier: MIT import time -import displayio -import terminalio + +import adafruit_stmpe610 # TFT Featherwing V1 touch driver import board import digitalio +import displayio +import terminalio from adafruit_hx8357 import HX8357 # TFT Featherwing display driver -import adafruit_stmpe610 # TFT Featherwing V1 touch driver + from adafruit_button.sprite_button import SpriteButton # 3.5" TFT Featherwing is 480x320 diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..db37c83 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,99 @@ +# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +target-version = "py38" +line-length = 100 + +[lint] +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 + +] + +[format] +line-ending = "lf"