From 53b190e3f836516250dc5e1e33cda01a45efa181 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sat, 16 Dec 2023 11:47:03 -0600 Subject: [PATCH 01/13] GridLayout cell contains --- .../layouts/grid_layout.py | 49 +++++++++++++++++++ docs/conf.py | 1 + 2 files changed, 50 insertions(+) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index df87eae..eee392d 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -406,9 +406,21 @@ def get_cell(self, cell_coordinates: Tuple[int, int]) -> displayio.Group: :return: the displayio content object at those coordinates """ for index, cell in enumerate(self._cell_content_list): + # exact location 1x1 cell if cell["grid_position"] == cell_coordinates: return self._cell_content_list[index]["content"] + # multi-spanning cell, any size bigger than 1x1 + if ( + cell["grid_position"][0] + <= cell_coordinates[0] + < cell["grid_position"][0] + cell["cell_size"][0] + and cell["grid_position"][1] + <= cell_coordinates[1] + < cell["grid_position"][1] + cell["cell_size"][1] + ): + return self._cell_content_list[index]["content"] + raise KeyError( "GridLayout does not contain cell at coordinates {}".format( cell_coordinates @@ -425,3 +437,40 @@ def cell_size_pixels(self) -> Tuple[int, int]: pixels of a 1x1 cell in the GridLayout """ return (self._width // self.grid_size[0], self._height // self.grid_size[1]) + + @property + def width(self) -> int: + """ + The width in pixels of the GridLayout. + """ + return self._width + + @property + def height(self) -> int: + """ + The width in pixels of the GridLayout. + """ + return self._height + + def which_cell_contains( + self, pixel_location: Union[Tuple[int, int], List[int]] + ) -> Optional[tuple]: + """ + Given a pixel x,y coordinate returns the location of the cell + that contains the coordinate. + + :param pixel_location: x,y pixel coordinate as a tuple or list + :returns: cell coordinates x,y tuple or None if the pixel coordinates are + outside the bounds of the GridLayout + """ + cell_size = self.cell_size_pixels + if ( + not self.x <= pixel_location[0] < self.x + self.width + or not self.y <= pixel_location[1] < self.y + self.height + ): + return None + + cell_x_coord = (pixel_location[0] - self.x) // cell_size[0] + cell_y_coord = (pixel_location[1] - self.y) // cell_size[1] + + return cell_x_coord, cell_y_coord diff --git a/docs/conf.py b/docs/conf.py index 964e471..3d12838 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,6 +32,7 @@ # autodoc module docs will fail to generate with a warning. autodoc_mock_imports = [ "vectorio", + "terminalio", "bitmaptools", ] From 4b0f993ff57eb0c04e67ae49e8fb6d7efe595696 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sat, 16 Dec 2023 11:51:22 -0600 Subject: [PATCH 02/13] fix docstring --- adafruit_displayio_layout/layouts/grid_layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index eee392d..b57ad24 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -448,7 +448,7 @@ def width(self) -> int: @property def height(self) -> int: """ - The width in pixels of the GridLayout. + The height in pixels of the GridLayout. """ return self._height From 873672f83bcb1e60ab7cbf8ac1b8d9f149bc9a28 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 26 Dec 2023 15:07:16 -0600 Subject: [PATCH 03/13] public layout_content. Don't add and remove lines many times unecessarily. --- .../layouts/grid_layout.py | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index b57ad24..d43608a 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -111,8 +111,13 @@ def __init__( ): self.cell_padding = 1 + def layout_cells(self): + self._layout_cells() + def _layout_cells(self) -> None: # pylint: disable=too-many-locals, too-many-branches, too-many-statements + for line_obj in self._divider_lines: + self.remove(line_obj["rect"]) for cell in self._cell_content_list: if cell["content"] not in self: grid_size_x = self.grid_size[0] @@ -359,15 +364,16 @@ def _layout_cells(self) -> None: } ) - for line_obj in self._divider_lines: - self.append(line_obj["rect"]) + for line_obj in self._divider_lines: + self.append(line_obj["rect"]) def add_content( - self, - cell_content: displayio.Group, - grid_position: Tuple[int, int], - cell_size: Tuple[int, int], - cell_anchor_point: Optional[Tuple[float, ...]] = None, + self, + cell_content: displayio.Group, + grid_position: Tuple[int, int], + cell_size: Tuple[int, int], + cell_anchor_point: Optional[Tuple[float, ...]] = None, + layout_cells=True ) -> None: """Add a child to the grid. @@ -395,7 +401,8 @@ def add_content( "cell_size": cell_size, } self._cell_content_list.append(sub_view_obj) - self._layout_cells() + if layout_cells: + self._layout_cells() def get_cell(self, cell_coordinates: Tuple[int, int]) -> displayio.Group: """ From 67f8bc959090076bc53b427745b5426bc452d6fd Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 26 Dec 2023 17:48:35 -0600 Subject: [PATCH 04/13] public layout_content. Don't add and remove lines many times unecessarily. --- adafruit_displayio_layout/layouts/grid_layout.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index b57ad24..27dc5db 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -111,8 +111,14 @@ def __init__( ): self.cell_padding = 1 + def layout_cells(self): + """render the grid with all cell content and dividers""" + self._layout_cells() + def _layout_cells(self) -> None: # pylint: disable=too-many-locals, too-many-branches, too-many-statements + for line_obj in self._divider_lines: + self.remove(line_obj["rect"]) for cell in self._cell_content_list: if cell["content"] not in self: grid_size_x = self.grid_size[0] @@ -359,8 +365,8 @@ def _layout_cells(self) -> None: } ) - for line_obj in self._divider_lines: - self.append(line_obj["rect"]) + for line_obj in self._divider_lines: + self.append(line_obj["rect"]) def add_content( self, @@ -368,6 +374,7 @@ def add_content( grid_position: Tuple[int, int], cell_size: Tuple[int, int], cell_anchor_point: Optional[Tuple[float, ...]] = None, + layout_cells=True, ) -> None: """Add a child to the grid. @@ -395,7 +402,8 @@ def add_content( "cell_size": cell_size, } self._cell_content_list.append(sub_view_obj) - self._layout_cells() + if layout_cells: + self._layout_cells() def get_cell(self, cell_coordinates: Tuple[int, int]) -> displayio.Group: """ From baeccd1eed05556d690d5e5eed5a346ee8346c30 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 16 Jan 2024 15:46:40 -0600 Subject: [PATCH 05/13] fix extra divider line removal --- adafruit_displayio_layout/layouts/grid_layout.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index 27dc5db..fd06895 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -303,9 +303,6 @@ def _layout_cells(self) -> None: x=_right_line_loc_x, ) - for line_obj in self._divider_lines: - self.remove(line_obj["rect"]) - """ Only use bottom divider lines on the bottom row. All other rows rely on top divder lines of the row beneath them. From c5441369e34873d4bc6dfa1b7e5d78d5ad5cac50 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 7 Oct 2024 09:24:05 -0500 Subject: [PATCH 06/13] remove deprecated get_html_theme_path() call Signed-off-by: foamyguy --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 3d12838..a314186 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -118,7 +118,6 @@ import sphinx_rtd_theme html_theme = "sphinx_rtd_theme" -html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."] # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, From 40b1812db0fd1d359e70b9215ece75aa9a78e635 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 14 Nov 2024 16:14:45 -0600 Subject: [PATCH 07/13] adding linear_layout --- .../layouts/linear_layout.py | 151 ++++++++++++++++++ ...isplayio_layout_linearlayout_simpletest.py | 37 +++++ 2 files changed, 188 insertions(+) create mode 100644 adafruit_displayio_layout/layouts/linear_layout.py create mode 100644 examples/displayio_layout_linearlayout_simpletest.py diff --git a/adafruit_displayio_layout/layouts/linear_layout.py b/adafruit_displayio_layout/layouts/linear_layout.py new file mode 100644 index 0000000..be48f70 --- /dev/null +++ b/adafruit_displayio_layout/layouts/linear_layout.py @@ -0,0 +1,151 @@ +# SPDX-FileCopyrightText: Copyright (c) 2021 Tim Cocks +# +# SPDX-License-Identifier: MIT +""" +`grid_layout` +================================================================================ + +A layout that organizes cells into a vertical or horizontal line. + + +* Author(s): Tim Cocks + +Implementation Notes +-------------------- + +**Hardware:** + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://github.com/adafruit/circuitpython/releases + +""" + +from adafruit_displayio_layout.widgets.widget import Widget + + +class LinearLayout(Widget): + """ + LinearLayout holds multiple content elements and arranges + them in a line either horizontally or vertically. + """ + + VERTICAL_ORIENTATION = 1 + HORIZONTAL_ORIENTATION = 2 + + def __init__( + self, + x, + y, + orientation=VERTICAL_ORIENTATION, + padding=0, + ): + """ + :param int x: The horizontal position of the layout + :param int y: The vertical position of the layout + :param int orientation: The orientation of the layout. Must be VERTICAL_ORIENTATION + or HORIZONTAL_ORIENTATION + :param int padding: The padding between items in the layout + """ + + super().__init__(x=x, y=y, width=1, height=1) + + self.x = x + self.y = y + self.padding = padding + if orientation not in [self.VERTICAL_ORIENTATION, self.HORIZONTAL_ORIENTATION]: + raise ValueError( + "Orientation must be either LinearLayout.VERTICAL_ORIENTATION" + " or LinearLayout.HORIZONTAL_ORIENTATION" + ) + + self.orientation = orientation + self._content_list = [] + self._prev_content_end = 0 + + def add_content(self, content): + """Add a child to the linear layout. + + :param content: the content to add to the linear layout e.g. label, button, etc... + Group subclasses that have width and height properties can be used. + + :return: None""" + + self._content_list.append(content) + self.append(content) + self._layout() + + def _layout(self): + # pylint: disable=too-many-branches, protected-access + self._prev_content_end = 0 + + for _, content in enumerate(self._content_list): + if not hasattr(content, "anchor_point"): + if self.orientation == self.VERTICAL_ORIENTATION: + content.y = self._prev_content_end + try: + self._prev_content_end = ( + self._prev_content_end + content.height + self.padding + ) + except AttributeError as error: + print(error) + try: + self._prev_content_end = ( + self._prev_content_end + content._height + self.padding + ) + except AttributeError as inner_error: + print(inner_error) + + else: + content.x = self._prev_content_end + if not hasattr(content, "tile_width"): + self._prev_content_end = ( + content.x + content.width + (self.padding * 2) + ) + else: + self._prev_content_end = ( + content.x + + (content.width * content.tile_width) + + (self.padding * 2) + ) + else: # use anchor point + content.anchor_point = ( + 0, + content.anchor_point[1] if content.anchor_point is not None else 0, + ) + if self.orientation == self.VERTICAL_ORIENTATION: + content.anchored_position = (0, self._prev_content_end) + # self._prev_content_end = content.y + content.height + if not hasattr(content, "bounding_box"): + self._prev_content_end = ( + self._prev_content_end + content.height + self.padding + ) + else: + self._prev_content_end = ( + self._prev_content_end + + (content.bounding_box[3] * content.scale) + + self.padding + ) + + else: + original_achored_pos_y = ( + content.anchored_position[1] + if content.anchored_position is not None + else 0 + ) + + content.anchored_position = ( + self._prev_content_end, + original_achored_pos_y, + ) + if not hasattr(content, "bounding_box"): + self._prev_content_end = ( + self._prev_content_end + content.width + self.padding + ) + else: + self._prev_content_end = ( + self._prev_content_end + + (content.bounding_box[2] * content.scale) + + self.padding + ) diff --git a/examples/displayio_layout_linearlayout_simpletest.py b/examples/displayio_layout_linearlayout_simpletest.py new file mode 100644 index 0000000..4090561 --- /dev/null +++ b/examples/displayio_layout_linearlayout_simpletest.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2024 Tim C, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT +""" +Illustrates usage of LinearLayout to display a text label to the right of +an icon. +""" +import adafruit_imageload +import board +import displayio +import terminalio +from adafruit_display_text import label +from adafruit_displayio_layout.layouts.linear_layout import LinearLayout + +# use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.) +# see guide for setting up external displays (TFT / OLED breakouts, RGB matrices, etc.) +# https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-and-display-bus +display = board.DISPLAY + +# Make the display context +main_group = displayio.Group() +display.root_group = main_group + +layout = LinearLayout( + x=10, y=10, padding=4, orientation=LinearLayout.HORIZONTAL_ORIENTATION +) + +lbl = label.Label(terminalio.FONT, scale=4, x=0, y=0, text="Hello") + +icon, icon_palette = adafruit_imageload.load("icons/Play_48x48_small.bmp") +icon_tile_grid = displayio.TileGrid(icon, pixel_shader=icon_palette) +layout.add_content(icon_tile_grid) +layout.add_content(lbl) + +main_group.append(layout) +while True: + pass From 5ab4c305be0f50269dda186197a9b788eda9821d Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 14 Nov 2024 16:22:38 -0600 Subject: [PATCH 08/13] fix docstring --- adafruit_displayio_layout/layouts/linear_layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_displayio_layout/layouts/linear_layout.py b/adafruit_displayio_layout/layouts/linear_layout.py index be48f70..3bcd6cb 100644 --- a/adafruit_displayio_layout/layouts/linear_layout.py +++ b/adafruit_displayio_layout/layouts/linear_layout.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: MIT """ -`grid_layout` +`linear_layout` ================================================================================ A layout that organizes cells into a vertical or horizontal line. From a89687597e929bcb65c6ae1c5ae5cea3d0179b80 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 14 Jan 2025 11:32:34 -0600 Subject: [PATCH 09/13] add sphinx configuration to rtd.yaml Signed-off-by: foamyguy --- .readthedocs.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index c8e145a..3ed8fb5 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,6 +8,9 @@ # Required version: 2 +sphinx: + configuration: docs/conf.py + build: os: ubuntu-20.04 tools: From fe5de40916d96e7c9cbc7c4e52c754572c921e1a Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 24 Feb 2025 17:27:35 -0600 Subject: [PATCH 10/13] use ruff and remove 8x displayio code --- .gitattributes | 11 + .pre-commit-config.yaml | 43 +- .pylintrc | 399 ------------------ README.rst | 6 +- .../layouts/grid_layout.py | 29 +- .../layouts/linear_layout.py | 15 +- .../layouts/page_layout.py | 30 +- .../layouts/tab_layout.py | 34 +- .../widgets/cartesian.py | 100 ++--- adafruit_displayio_layout/widgets/control.py | 2 - adafruit_displayio_layout/widgets/easing.py | 6 +- .../widgets/flip_input.py | 170 +++----- .../widgets/icon_animated.py | 29 +- .../widgets/icon_widget.py | 15 +- .../widgets/switch_round.py | 39 +- adafruit_displayio_layout/widgets/widget.py | 2 - docs/api.rst | 3 + docs/conf.py | 8 +- ...isplayio_layout_cartesian_advanced_test.py | 1 + .../displayio_layout_cartesian_lineplot.py | 2 + .../displayio_layout_cartesian_simpletest.py | 2 + .../displayio_layout_flip_input_simpletest.py | 10 +- ...playio_layout_grid_layout_get_cell_test.py | 10 +- .../displayio_layout_gridlayout_dividers.py | 10 +- ...ut_gridlayout_pygame_display_simpletest.py | 10 +- .../displayio_layout_gridlayout_simpletest.py | 10 +- ...splayio_layout_icon_animated_simpletest.py | 9 +- ...isplayio_layout_linearlayout_simpletest.py | 6 +- ...splayio_layout_page_layout_advancedtest.py | 17 +- ...displayio_layout_page_layout_simpletest.py | 9 +- ...ayio_layout_pygame_display_switch_round.py | 3 +- examples/displayio_layout_simpletest.py | 10 +- examples/displayio_layout_switch_multiple.py | 4 +- .../displayio_layout_switch_simpletest.py | 4 +- .../displayio_layout_tab_layout_simpletest.py | 17 +- .../displayio_layout_tab_layout_touchtest.py | 10 +- .../displayio_layout_hotplug_rtc.py | 62 ++- .../displayio_layout_hotplug_temp_sensor.py | 74 ++-- ruff.toml | 101 +++++ 39 files changed, 403 insertions(+), 919 deletions(-) create mode 100644 .gitattributes delete mode 100644 .pylintrc create mode 100644 ruff.toml 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 70ade69..ff19dde 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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 diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index f945e92..0000000 --- a/.pylintrc +++ /dev/null @@ -1,399 +0,0 @@ -# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries -# -# SPDX-License-Identifier: Unlicense - -[MASTER] - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-whitelist= - -# Add files or directories to the ignore-list. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the ignore-list. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. -jobs=1 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins=pylint.extensions.no_self_use - -# Pickle collected data for later comparisons. -persistent=yes - -# Specify a configuration file. -#rcfile= - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -# disable=import-error,raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,deprecated-str-translate-call -disable=raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,import-error,pointless-string-statement,unspecified-encoding - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable= - - -[REPORTS] - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -#msg-template= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio).You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages -reports=no - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -# notes=FIXME,XXX,TODO -notes=FIXME,XXX - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules=board - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb - -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,future.builtins - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -# expected-line-ending-format= -expected-line-ending-format=LF - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=100 - -# Maximum number of lines in a module -max-module-lines=1000 - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=yes - -# Minimum lines number of a similarity. -min-similarity-lines=12 - - -[BASIC] - -# Regular expression matching correct argument names -argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct attribute names -attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression matching correct class names -# class-rgx=[A-Z_][a-zA-Z0-9]+$ -class-rgx=[A-Z_][a-zA-Z0-9_]+$ - -# Regular expression matching correct constant names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Regular expression matching correct function names -function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Good variable names which should always be accepted, separated by a comma -# good-names=i,j,k,ex,Run,_ -good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_ - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Regular expression matching correct method names -method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty - -# Regular expression matching correct variable names -variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - - -[IMPORTS] - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=optparse,tkinter.tix - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Maximum number of attributes for a class (see R0902). -# max-attributes=7 -max-attributes=11 - -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of statements in function / method body -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=1 - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=builtins.Exception diff --git a/README.rst b/README.rst index a797fcd..b9628db 100644 --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ Introduction :target: https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout/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 CircuitPython helper library for displayio layouts and widgets. diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index fd06895..5d2be9b 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -22,6 +22,7 @@ https://github.com/adafruit/circuitpython/releases """ + try: # Used only for typing from typing import Any, List, Optional, Tuple, Union @@ -29,6 +30,7 @@ pass import math + import displayio from vectorio import Rectangle @@ -58,8 +60,6 @@ class GridLayout(displayio.Group): """ - # pylint: disable=too-many-arguments - # pylint: disable=too-many-instance-attributes def __init__( self, x: int, @@ -106,9 +106,7 @@ def __init__( self.v_divider_line_cols.append(_x) # use at least 1 padding so that content is inside the divider lines - if cell_padding == 0 and ( - divider_lines or h_divider_line_rows or v_divider_line_cols - ): + if cell_padding == 0 and (divider_lines or h_divider_line_rows or v_divider_line_cols): self.cell_padding = 1 def layout_cells(self): @@ -116,7 +114,6 @@ def layout_cells(self): self._layout_cells() def _layout_cells(self) -> None: - # pylint: disable=too-many-locals, too-many-branches, too-many-statements for line_obj in self._divider_lines: self.remove(line_obj["rect"]) for cell in self._cell_content_list: @@ -310,11 +307,8 @@ def _layout_cells(self) -> None: areas larger than 1x1 cells. For 1x1 cells this will equal zero and not change anything. """ - if ( - grid_position_y + content_cell_size_y - 1 - ) == grid_size_y - 1 and ( - (grid_position_y + content_cell_size_y - 1) + 1 - in self.h_divider_line_rows + if (grid_position_y + content_cell_size_y - 1) == grid_size_y - 1 and ( + (grid_position_y + content_cell_size_y - 1) + 1 in self.h_divider_line_rows ): self._divider_lines.append( { @@ -350,11 +344,8 @@ def _layout_cells(self) -> None: areas larger than 1x1 cells. For 1x1 cells this will equal zero and not change anything. """ - if ( - grid_position_x + content_cell_size_x - 1 - ) == grid_size_x - 1 and ( - (grid_position_x + content_cell_size_x - 1) + 1 - in self.v_divider_line_cols + if (grid_position_x + content_cell_size_x - 1) == grid_size_x - 1 and ( + (grid_position_x + content_cell_size_x - 1) + 1 in self.v_divider_line_cols ): self._divider_lines.append( { @@ -426,11 +417,7 @@ def get_cell(self, cell_coordinates: Tuple[int, int]) -> displayio.Group: ): return self._cell_content_list[index]["content"] - raise KeyError( - "GridLayout does not contain cell at coordinates {}".format( - cell_coordinates - ) - ) + raise KeyError(f"GridLayout does not contain cell at coordinates {cell_coordinates}") @property def cell_size_pixels(self) -> Tuple[int, int]: diff --git a/adafruit_displayio_layout/layouts/linear_layout.py b/adafruit_displayio_layout/layouts/linear_layout.py index 3bcd6cb..9815300 100644 --- a/adafruit_displayio_layout/layouts/linear_layout.py +++ b/adafruit_displayio_layout/layouts/linear_layout.py @@ -54,7 +54,7 @@ def __init__( self.x = x self.y = y self.padding = padding - if orientation not in [self.VERTICAL_ORIENTATION, self.HORIZONTAL_ORIENTATION]: + if orientation not in {self.VERTICAL_ORIENTATION, self.HORIZONTAL_ORIENTATION}: raise ValueError( "Orientation must be either LinearLayout.VERTICAL_ORIENTATION" " or LinearLayout.HORIZONTAL_ORIENTATION" @@ -77,7 +77,6 @@ def add_content(self, content): self._layout() def _layout(self): - # pylint: disable=too-many-branches, protected-access self._prev_content_end = 0 for _, content in enumerate(self._content_list): @@ -100,14 +99,10 @@ def _layout(self): else: content.x = self._prev_content_end if not hasattr(content, "tile_width"): - self._prev_content_end = ( - content.x + content.width + (self.padding * 2) - ) + self._prev_content_end = content.x + content.width + (self.padding * 2) else: self._prev_content_end = ( - content.x - + (content.width * content.tile_width) - + (self.padding * 2) + content.x + (content.width * content.tile_width) + (self.padding * 2) ) else: # use anchor point content.anchor_point = ( @@ -130,9 +125,7 @@ def _layout(self): else: original_achored_pos_y = ( - content.anchored_position[1] - if content.anchored_position is not None - else 0 + content.anchored_position[1] if content.anchored_position is not None else 0 ) content.anchored_position = ( diff --git a/adafruit_displayio_layout/layouts/page_layout.py b/adafruit_displayio_layout/layouts/page_layout.py index 040ccbd..8e69c63 100644 --- a/adafruit_displayio_layout/layouts/page_layout.py +++ b/adafruit_displayio_layout/layouts/page_layout.py @@ -22,9 +22,9 @@ https://github.com/adafruit/circuitpython/releases """ + try: # Used only for typing - # pylint: disable=unused-import from typing import Tuple except ImportError: @@ -90,16 +90,12 @@ def _check_args(self, page_name, page_index): raise AttributeError("Must pass either page_name or page_index") if page_index is not None and page_name is not None: - raise AttributeError( - "Must pass either page_name or page_index only one or the other" - ) + raise AttributeError("Must pass either page_name or page_index only one or the other") if page_index is not None: if page_index >= len(self.page_content_list): raise KeyError( - "KeyError at index {} in list length {}".format( - page_index, len(self.page_content_list) - ), + f"KeyError at index {page_index} in list length {len(self.page_content_list)}", ) if page_name is not None: @@ -110,7 +106,7 @@ def _check_args(self, page_name, page_index): _found = True if not _found: - raise KeyError("Page with name {} not found".format(page_name)) + raise KeyError(f"Page with name {page_name} not found") def get_page(self, page_name=None, page_index=None): """ @@ -133,9 +129,7 @@ def get_page(self, page_name=None, page_index=None): return cell raise KeyError( - "PageLayout does not contain page: {}".format( - page_index if page_index else page_name - ) + f"PageLayout does not contain page: {page_index if page_index else page_name}" ) def show_page(self, page_name=None, page_index=None): @@ -205,11 +199,10 @@ def next_page(self, loop=True): if self._cur_showing_index + 1 < len(self.page_content_list): self.show_page(page_index=self._cur_showing_index + 1) + elif not loop: + print("No more pages") else: - if not loop: - print("No more pages") - else: - self.show_page(page_index=0) + self.show_page(page_index=0) def previous_page(self, loop=True): """ @@ -219,8 +212,7 @@ def previous_page(self, loop=True): """ if self._cur_showing_index - 1 >= 0: self.show_page(page_index=self._cur_showing_index - 1) + elif not loop: + print("No more pages") else: - if not loop: - print("No more pages") - else: - self.show_page(page_index=len(self.page_content_list) - 1) + self.show_page(page_index=len(self.page_content_list) - 1) diff --git a/adafruit_displayio_layout/layouts/tab_layout.py b/adafruit_displayio_layout/layouts/tab_layout.py index e63f021..ac5875d 100644 --- a/adafruit_displayio_layout/layouts/tab_layout.py +++ b/adafruit_displayio_layout/layouts/tab_layout.py @@ -22,19 +22,22 @@ https://github.com/adafruit/circuitpython/releases """ + try: - from typing import Optional, Union, Tuple - from fontio import BuiltinFont + from typing import Optional, Tuple, Union + from adafruit_bitmap_font.bdf import BDF from adafruit_bitmap_font.pcf import PCF + from fontio import BuiltinFont except ImportError: pass -import terminalio -import displayio import adafruit_imageload +import displayio +import terminalio from adafruit_display_text.bitmap_label import Label from adafruit_imageload.tilegrid_inflator import inflate_tilegrid + from adafruit_displayio_layout.layouts.page_layout import PageLayout __version__ = "0.0.0+auto.0" @@ -68,8 +71,6 @@ class TabLayout(displayio.Group): :param int tab_count: How many tabs to draw in the layout. Positive whole numbers are valid. """ - # pylint: disable=too-many-instance-attributes, too-many-arguments, invalid-name, too-many-branches - def __init__( self, x: int = 0, @@ -86,8 +87,7 @@ def __init__( tab_count: int = None, ): if display is None: - # pylint: disable=import-outside-toplevel - import board + import board # noqa: PLC0415, non-top-level-import if hasattr(board, "DISPLAY"): display = board.DISPLAY @@ -100,9 +100,7 @@ def __init__( super().__init__(x=x, y=y) self.tab_count = tab_count - self._active_bmp, self._active_palette = adafruit_imageload.load( - showing_tab_spritesheet - ) + self._active_bmp, self._active_palette = adafruit_imageload.load(showing_tab_spritesheet) self._inactive_bmp, self._inactive_palette = adafruit_imageload.load( inactive_tab_spritesheet ) @@ -121,9 +119,7 @@ def __init__( for index in inactive_tab_transparent_indexes: self._inactive_palette.make_transparent(index) else: - raise AttributeError( - "inactive_tab_transparent_indexes must be int or tuple" - ) + raise AttributeError("inactive_tab_transparent_indexes must be int or tuple") self.tab_height = self._active_bmp.height self.display = display @@ -147,8 +143,7 @@ def _draw_tabs(self): bmp_obj=self._inactive_bmp, bmp_palette=self._inactive_palette, target_size=( - (self.display.width // self.tab_count) - // (self._active_bmp.width // 3), + (self.display.width // self.tab_count) // (self._active_bmp.width // 3), 3, ), ) @@ -165,8 +160,7 @@ def _draw_tabs(self): _tab_label.anchor_point = (0.5, 0.5) _tab_label.anchored_position = ( - _tab_tilegrid.x - + ((_tab_tilegrid.width * _tab_tilegrid.tile_width) // 2), + _tab_tilegrid.x + ((_tab_tilegrid.width * _tab_tilegrid.tile_width) // 2), (_tab_tilegrid.height * _tab_tilegrid.tile_height) // 2, ) _new_tab_group.append(_tab_label) @@ -282,8 +276,6 @@ def handle_touch_events(self, touch_event): if touch_event: if 0 <= touch_event[1] <= self.tab_height: - touched_tab_index = touch_event[0] // ( - self.display.width // self.tab_count - ) + touched_tab_index = touch_event[0] // (self.display.width // self.tab_count) print(f"{touch_event[0]} - {touched_tab_index}") self.showing_page_index = touched_tab_index diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index bcb11dc..21bbdc8 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -21,13 +21,11 @@ """ -# pylint: disable=too-many-lines, too-many-instance-attributes, too-many-arguments -# pylint: disable=too-many-locals, too-many-statements - import displayio import terminalio -from adafruit_display_text import bitmap_label import vectorio +from adafruit_display_text import bitmap_label + from adafruit_displayio_layout.widgets.widget import Widget try: @@ -229,28 +227,20 @@ def __init__( self._valuey = self.height / 100 self._factory = 100 / (self._yrange[1] - self._yrange[0]) - self._tick_bitmap = displayio.Bitmap( - self._tick_line_thickness, self._tick_line_height, 3 - ) + self._tick_bitmap = displayio.Bitmap(self._tick_line_thickness, self._tick_line_height, 3) self._tick_bitmap.fill(1) self._subticks = subticks axesx_height = ( - 2 - + self._axes_line_thickness - + self._font_height - + self._tick_line_height // 2 + 2 + self._axes_line_thickness + self._font_height + self._tick_line_height // 2 ) self._axesx_bitmap = displayio.Bitmap(self.width, axesx_height, 4) self._axesx_bitmap.fill(0) self._axesy_width = ( - 2 - + self._axes_line_thickness - + self._font_width - + self._tick_line_height // 2 + 2 + self._axes_line_thickness + self._font_width + self._tick_line_height // 2 ) self._axesy_bitmap = displayio.Bitmap(self._axesy_width, self.height, 4) @@ -408,20 +398,14 @@ def _draw_ticks(self) -> None: self._font, color=self._font_color, text=text_tick, - x=-shift_label_x - - self._axes_line_thickness - - self._tick_line_height - - 2, + x=-shift_label_x - self._axes_line_thickness - self._tick_line_height - 2, y=0 + self.height - text_dist, ) self.append(tick_text) bitmaptools.fill_region( self._axesy_bitmap, - self._axesy_width - - self._axes_line_thickness - - self._tick_line_height - - 1, + self._axesy_width - self._axes_line_thickness - self._tick_line_height - 1, text_dist, self._axesy_width - self._axes_line_thickness - 1, text_dist + self._tick_line_thickness, @@ -453,9 +437,7 @@ def _draw_pointers(self, x: int, y: int) -> None: self.append(self._pointer) def _calc_local_xy(self, x: int, y: int) -> Tuple[int, int]: - local_x = ( - int((x - self._xrange[0]) * self._factorx * self._valuex) + self._nudge_x - ) + local_x = int((x - self._xrange[0]) * self._factorx * self._valuex) + self._nudge_x # details on `+ (self.height - 1)` : # the bitmap is set to self.width & self.height # but we are only allowed to draw to pixels 0..height-1 and 0..width-1 @@ -473,9 +455,7 @@ def _check_local_y_in_range(self, local_y: int) -> bool: return 0 <= local_y < self.height def _check_local_xy_in_range(self, local_x: int, local_y: int) -> bool: - return self._check_local_x_in_range(local_x) and self._check_local_y_in_range( - local_y - ) + return self._check_local_x_in_range(local_x) and self._check_local_y_in_range(local_y) def _check_x_in_range(self, x: int) -> bool: return self._xrange[0] <= x <= self._xrange[1] @@ -498,30 +478,16 @@ def _add_point(self, x: int, y: int) -> None: if self._verbose: print("") print( - "xy: ({: >4}, {: >4}) " - "_xrange: ({: >4}, {: >4}) " - "_yrange: ({: >4}, {: >4}) " - "".format( - x, - y, - self._xrange[0], - self._xrange[1], - self._yrange[0], - self._yrange[1], - ) + f"xy: ({x: >4}, {y: >4}) " + f"_xrange: ({self._xrange[0]: >4}, {self._xrange[1]: >4}) " + f"_yrange: ({self._yrange[0]: >4}, {self._yrange[1]: >4}) " + "" ) print( - "local_*: ({: >4}, {: >4}) " - " width: ({: >4}, {: >4}) " - " height: ({: >4}, {: >4}) " - "".format( - local_x, - local_y, - 0, - self.width, - 0, - self.height, - ) + f"local_*: ({local_x: >4}, {local_y: >4}) " + f" width: ({0: >4}, {self.width: >4}) " + f" height: ({0: >4}, {self.height: >4}) " + "" ) if self._check_xy_in_range(x, y): if self._check_local_xy_in_range(local_x, local_y): @@ -536,44 +502,28 @@ def _add_point(self, x: int, y: int) -> None: if not self._check_local_x_in_range(local_x): raise ValueError( "local_x out of range: " - "local_x:{: >4}; _xrange({: >4}, {: >4})" - "".format( - local_x, - 0, - self.width, - ) + f"local_x:{local_x: >4}; _xrange({0: >4}, {self.width: >4})" + "" ) if not self._check_local_y_in_range(local_y): raise ValueError( "local_y out of range: " - "local_y:{: >4}; _yrange({: >4}, {: >4})" - "".format( - local_y, - 0, - self.height, - ) + f"local_y:{local_y: >4}; _yrange({0: >4}, {self.height: >4})" + "" ) else: # for better error messages we check in detail what failed... if not self._check_x_in_range(x): raise ValueError( "x out of range: " - "x:{: >4}; xrange({: >4}, {: >4})" - "".format( - x, - self._xrange[0], - self._xrange[1], - ) + f"x:{x: >4}; xrange({self._xrange[0]: >4}, {self._xrange[1]: >4})" + "" ) if not self._check_y_in_range(y): raise ValueError( "y out of range: " - "y:{: >4}; yrange({: >4}, {: >4})" - "".format( - y, - self._yrange[0], - self._yrange[1], - ) + f"y:{y: >4}; yrange({self._yrange[0]: >4}, {self._yrange[1]: >4})" + "" ) def update_pointer(self, x: int, y: int) -> None: diff --git a/adafruit_displayio_layout/widgets/control.py b/adafruit_displayio_layout/widgets/control.py index f9e5a2b..464804e 100644 --- a/adafruit_displayio_layout/widgets/control.py +++ b/adafruit_displayio_layout/widgets/control.py @@ -30,8 +30,6 @@ __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout.git" -# pylint: disable=unsubscriptable-object, unnecessary-pass - class Control: """A Control class for responsive elements, including touch response functions for displays. diff --git a/adafruit_displayio_layout/widgets/easing.py b/adafruit_displayio_layout/widgets/easing.py index 9a1e9a9..db2d2d0 100644 --- a/adafruit_displayio_layout/widgets/easing.py +++ b/adafruit_displayio_layout/widgets/easing.py @@ -75,7 +75,6 @@ import math - __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout.git" @@ -285,7 +284,7 @@ def exponential_easeinout(pos: float) -> float: """ Easing function for animations: Exponential Ease In & Out """ - if pos in (0.0, 1.0): + if pos in {0.0, 1.0}: return pos if pos < 0.5: return 0.5 * math.pow(2, (20 * pos) - 10) @@ -318,8 +317,7 @@ def elastic_easeinout(pos: float) -> float: if pos < 0.5: return 0.5 * math.sin(13 * math.pi * pos) * math.pow(2, 10 * ((2 * pos) - 1)) return 0.5 * ( - math.sin(-13 * math.pi / 2 * ((2 * pos - 1) + 1)) * pow(2, -10 * (2 * pos - 1)) - + 2 + math.sin(-13 * math.pi / 2 * ((2 * pos - 1) + 1)) * pow(2, -10 * (2 * pos - 1)) + 2 ) diff --git a/adafruit_displayio_layout/widgets/flip_input.py b/adafruit_displayio_layout/widgets/flip_input.py index 1474225..cbdae52 100644 --- a/adafruit_displayio_layout/widgets/flip_input.py +++ b/adafruit_displayio_layout/widgets/flip_input.py @@ -23,20 +23,18 @@ import gc import time -import displayio -from terminalio import FONT +import displayio from adafruit_display_shapes.triangle import Triangle - from adafruit_display_text import bitmap_label -from adafruit_displayio_layout.widgets.widget import Widget -from adafruit_displayio_layout.widgets.control import Control +from terminalio import FONT -# pylint: disable=reimported +from adafruit_displayio_layout.widgets.control import Control # select the two "easing" functions to use for animations from adafruit_displayio_layout.widgets.easing import back_easeinout as easein from adafruit_displayio_layout.widgets.easing import back_easeinout as easeout +from adafruit_displayio_layout.widgets.widget import Widget try: from typing import Any, List, Optional, Tuple @@ -48,10 +46,6 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout.git" -# pylint: disable=too-many-arguments, too-many-branches, too-many-statements -# pylint: disable=too-many-locals, too-many-instance-attributes - - class FlipInput(Widget, Control): """A flip style input selector. The value changes based on touch inputs on the two halves of the indicator with optional arrows added. @@ -121,7 +115,6 @@ def __init__( # initialize the Control superclass - # pylint: disable=bad-super-call super(Control, self).__init__() self.value_list = value_list @@ -157,18 +150,14 @@ def __init__( for i, character in enumerate(this_value): glyph = self._font.get_glyph(ord(character)) - if ( - i == 0 - ): # if it's the first character in the string, check the left value + if i == 0: # if it's the first character in the string, check the left value if left is None: left = glyph.dx else: left = min(left, glyph.dx) if right is None: - right = max( - xposition + glyph.dx + glyph.width, xposition + glyph.shift_x - ) + right = max(xposition + glyph.dx + glyph.width, xposition + glyph.shift_x) else: right = max( right, @@ -189,12 +178,7 @@ def __init__( xposition = xposition + glyph.shift_x # Something is wrong if left, right, top, or bottom are still None here - assert ( - right is not None - and left is not None - and top is not None - and bottom is not None - ) + assert right is not None and left is not None and top is not None and bottom is not None self._bounding_box = [ 0, @@ -226,10 +210,7 @@ def __init__( if horizontal: # horizontal orientation, add arrow padding to x-dimension and # alt_padding to y-dimension self.touch_boundary = ( - self._bounding_box[0] - - self._arrow_gap - - arrow_height - - self._arrow_touch_padding, + self._bounding_box[0] - self._arrow_gap - arrow_height - self._arrow_touch_padding, self._bounding_box[1] - self._alt_touch_padding, self._bounding_box[2] + 2 * (self._arrow_gap + arrow_height + self._arrow_touch_padding), @@ -239,10 +220,7 @@ def __init__( # alt_padding to x-dimension self.touch_boundary = ( self._bounding_box[0] - self._alt_touch_padding, - self._bounding_box[1] - - self._arrow_gap - - arrow_height - - self._arrow_touch_padding, + self._bounding_box[1] - self._arrow_gap - arrow_height - self._arrow_touch_padding, self._bounding_box[2] + 2 * self._alt_touch_padding, self._bounding_box[3] + 2 * (self._arrow_gap + arrow_height + self._arrow_touch_padding), @@ -263,11 +241,7 @@ def __init__( if (arrow_color is not None) or (arrow_outline is not None): if horizontal: # horizontal orientation, add left and right arrows - if ( - (arrow_width is not None) - and (arrow_height is not None) - and (arrow_width > 0) - ): + if (arrow_width is not None) and (arrow_height is not None) and (arrow_width > 0): mid_point_y = self._bounding_box[1] + self._bounding_box[3] // 2 self.append( Triangle( @@ -284,13 +258,9 @@ def __init__( self.append( Triangle( - self._bounding_box[0] - + self._bounding_box[2] - + self._arrow_gap, + self._bounding_box[0] + self._bounding_box[2] + self._arrow_gap, mid_point_y - arrow_height // 2, - self._bounding_box[0] - + self._bounding_box[2] - + self._arrow_gap, + self._bounding_box[0] + self._bounding_box[2] + self._arrow_gap, mid_point_y + arrow_height // 2, self._bounding_box[0] + self._bounding_box[2] @@ -301,44 +271,35 @@ def __init__( outline=arrow_outline, ) ) - else: # vertical orientation, add upper and lower arrows - if ( - (arrow_height is not None) - and (arrow_width is not None) - and (arrow_height > 0) - ): - mid_point_x = self._bounding_box[0] + self._bounding_box[2] // 2 - self.append( - Triangle( - mid_point_x - arrow_width // 2, - self._bounding_box[1] - self._arrow_gap, - mid_point_x + arrow_width // 2, - self._bounding_box[1] - self._arrow_gap, - mid_point_x, - self._bounding_box[1] - self._arrow_gap - arrow_height, - fill=arrow_color, - outline=arrow_outline, - ) + elif (arrow_height is not None) and (arrow_width is not None) and (arrow_height > 0): + mid_point_x = self._bounding_box[0] + self._bounding_box[2] // 2 + self.append( + Triangle( + mid_point_x - arrow_width // 2, + self._bounding_box[1] - self._arrow_gap, + mid_point_x + arrow_width // 2, + self._bounding_box[1] - self._arrow_gap, + mid_point_x, + self._bounding_box[1] - self._arrow_gap - arrow_height, + fill=arrow_color, + outline=arrow_outline, ) - self.append( - Triangle( - mid_point_x - arrow_width // 2, - self._bounding_box[1] - + self._bounding_box[3] - + self._arrow_gap, - mid_point_x + arrow_width // 2, - self._bounding_box[1] - + self._bounding_box[3] - + self._arrow_gap, - mid_point_x, - self._bounding_box[1] - + self._bounding_box[3] - + self._arrow_gap - + arrow_height, - fill=arrow_color, - outline=arrow_outline, - ) + ) + self.append( + Triangle( + mid_point_x - arrow_width // 2, + self._bounding_box[1] + self._bounding_box[3] + self._arrow_gap, + mid_point_x + arrow_width // 2, + self._bounding_box[1] + self._bounding_box[3] + self._arrow_gap, + mid_point_x, + self._bounding_box[1] + + self._bounding_box[3] + + self._arrow_gap + + arrow_height, + fill=arrow_color, + outline=arrow_outline, ) + ) # Draw function to update the current value def _update_value(self, new_value: int, animate: bool = True) -> None: @@ -370,9 +331,7 @@ def _update_value(self, new_value: int, animate: bool = True) -> None: palette = displayio.Palette(2) palette.make_transparent(0) palette[1] = self._color - animation_tilegrid = displayio.TileGrid( - animation_bitmap, pixel_shader=palette - ) + animation_tilegrid = displayio.TileGrid(animation_bitmap, pixel_shader=palette) # add bitmap to the animation_group self._animation_group.append(animation_tilegrid) @@ -452,9 +411,7 @@ def contains( # offsetting for self.x and self.y before calling the Control superclass function # ###### - touch_x = ( - touch_point[0] - self.x - ) # adjust touch position for the local position + touch_x = touch_point[0] - self.x # adjust touch position for the local position touch_y = touch_point[1] - self.y return super().contains((touch_x, touch_y, 0)) @@ -475,29 +432,22 @@ def selected(self, touch_point: Tuple[int, int, Optional[int]]) -> None: self.value = self.value - 1 elif ( - (t_b[0] + t_b[2] // 2) - <= (touch_point[0] - self.x) - <= (t_b[0] + t_b[2]) + (t_b[0] + t_b[2] // 2) <= (touch_point[0] - self.x) <= (t_b[0] + t_b[2]) ): # in right half of touch_boundary self.value = self.value + 1 - else: - if ( - t_b[1] <= (touch_point[1] - self.y) < (t_b[1] + t_b[3] // 2) - ): # in upper half of touch_boundary - self.value = self.value + 1 + elif ( + t_b[1] <= (touch_point[1] - self.y) < (t_b[1] + t_b[3] // 2) + ): # in upper half of touch_boundary + self.value = self.value + 1 - elif ( - (t_b[1] + t_b[3] // 2) - <= (touch_point[1] - self.y) - <= (t_b[1] + t_b[3]) - ): # in lower half of touch_boundary - self.value = self.value - 1 + elif ( + (t_b[1] + t_b[3] // 2) <= (touch_point[1] - self.y) <= (t_b[1] + t_b[3]) + ): # in lower half of touch_boundary + self.value = self.value - 1 self._pressed = True # update the state variable - self._last_pressed = ( - time.monotonic() - ) # value changed, so update cool_down timer + self._last_pressed = time.monotonic() # value changed, so update cool_down timer def released(self) -> None: """Response function when the Control is released. Resets the state variables @@ -525,9 +475,7 @@ def value( try: new_value = self.value_list.index(new_value) except ValueError: - print( - 'ValueError: Value "{}" not found in value_list.'.format(new_value) - ) + print(f'ValueError: Value "{new_value}" not found in value_list.') return None new_value = new_value % len(self.value_list) # Update the value @@ -590,9 +538,6 @@ def _draw_position( ) -# pylint: disable=invalid-name - - # _blit_constrained: Copies bitmaps with constraints to the dimensions def _blit_constrained( target: displayio.Bitmap, @@ -633,12 +578,7 @@ def _blit_constrained( if y2 > source.height: y2 = source.height - if ( - (x > target.width) - or (y > target.height) - or (x1 > source.width) - or (y1 > source.height) - ): + if (x > target.width) or (y > target.height) or (x1 > source.width) or (y1 > source.height): return target.blit(x, y, source, x1=x1, y1=y1, x2=x2, y2=y2) @@ -683,9 +623,7 @@ def _animate_bitmap( this_time = time.monotonic() target_position = ( start_position - + (end_position - start_position) - * (this_time - start_time) - / animation_time + + (end_position - start_position) * (this_time - start_time) / animation_time ) display.auto_refresh = False diff --git a/adafruit_displayio_layout/widgets/icon_animated.py b/adafruit_displayio_layout/widgets/icon_animated.py index 2e5db2f..2e43821 100644 --- a/adafruit_displayio_layout/widgets/icon_animated.py +++ b/adafruit_displayio_layout/widgets/icon_animated.py @@ -21,19 +21,23 @@ https://github.com/adafruit/circuitpython/releases """ + import gc import time from math import pi -import bitmaptools -from displayio import TileGrid, Bitmap, Palette + import adafruit_imageload -from adafruit_displayio_layout.widgets.icon_widget import IconWidget -from adafruit_displayio_layout.widgets.easing import quadratic_easeout as easein +import bitmaptools +from displayio import Bitmap, Palette, TileGrid + from adafruit_displayio_layout.widgets.easing import quadratic_easein as easeout +from adafruit_displayio_layout.widgets.easing import quadratic_easeout as easein +from adafruit_displayio_layout.widgets.icon_widget import IconWidget try: from typing import Any, Optional, Tuple - from displayio import Display # pylint: disable=ungrouped-imports + + from busdisplay import BusDisplay except ImportError: pass @@ -43,7 +47,6 @@ class IconAnimated(IconWidget): - """ An animated touch enabled widget that holds an icon image loaded with OnDiskBitmap and a text label centered beneath it. Includes optional @@ -76,9 +79,6 @@ class IconAnimated(IconWidget): :type anchored_position: Tuple[int, int] """ - # pylint: disable=bad-super-call, too-many-instance-attributes, too-many-locals - # pylint: disable=too-many-arguments, unused-argument - display = None # The other Class variables are created in Class method `init_class`: # max_scale, bitmap_buffer, palette_buffer @@ -86,7 +86,7 @@ class IconAnimated(IconWidget): @classmethod def init_class( cls, - display: Optional[Display], + display: Optional[BusDisplay], max_scale: float = 1.5, max_icon_size: Tuple[int, int] = (80, 80), max_color_depth: int = 256, @@ -168,9 +168,8 @@ def __init__( if scale > self.__class__.max_scale: print( "Warning - IconAnimated: max_scale is constrained by value of " - "IconAnimated.max_scale set by IconAnimated.init_class(): {}".format( - self.__class__.max_scale - ) + "IconAnimated.max_scale set by " + f"IconAnimated.init_class(): {self.__class__.max_scale}" ) self._scale = max(0, min(scale, self.__class__.max_scale)) @@ -233,9 +232,7 @@ def zoom_animation(self, touch_point: Tuple[int, int, Optional[int]]) -> None: ) # blit the image into the center of the zoom_bitmap # place zoom_bitmap at same location as image - animation_tilegrid = TileGrid( - animation_bitmap, pixel_shader=animation_palette - ) + animation_tilegrid = TileGrid(animation_bitmap, pixel_shader=animation_palette) animation_tilegrid.x = -(animation_bitmap.width - _image.width) // 2 animation_tilegrid.y = -(animation_bitmap.height - _image.height) // 2 diff --git a/adafruit_displayio_layout/widgets/icon_widget.py b/adafruit_displayio_layout/widgets/icon_widget.py index 318d1c6..2a262cc 100644 --- a/adafruit_displayio_layout/widgets/icon_widget.py +++ b/adafruit_displayio_layout/widgets/icon_widget.py @@ -22,11 +22,11 @@ """ - -import terminalio -from displayio import TileGrid, OnDiskBitmap import adafruit_imageload +import terminalio from adafruit_display_text import bitmap_label +from displayio import OnDiskBitmap, TileGrid + from adafruit_displayio_layout.widgets.control import Control from adafruit_displayio_layout.widgets.widget import Widget @@ -41,7 +41,6 @@ class IconWidget(Widget, Control): - """ A touch enabled widget that holds an icon image loaded with adafruit_imageload and a text label centered beneath it. @@ -63,8 +62,6 @@ class IconWidget(Widget, Control): :type anchored_position: Tuple[int, int] """ - # pylint: disable=too-many-arguments - def __init__( self, label_text: str, @@ -72,7 +69,7 @@ def __init__( on_disk: bool = False, transparent_index: Optional[int] = None, label_background: Optional[int] = None, - **kwargs: Any + **kwargs: Any, ) -> None: super().__init__(**kwargs) @@ -120,9 +117,7 @@ def contains( :return: Boolean """ - touch_x = ( - touch_point[0] - self.x - ) # adjust touch position for the local position + touch_x = touch_point[0] - self.x # adjust touch position for the local position touch_y = touch_point[1] - self.y return super().contains((touch_x, touch_y, 0)) diff --git a/adafruit_displayio_layout/widgets/switch_round.py b/adafruit_displayio_layout/widgets/switch_round.py index e583b18..8ce0320 100644 --- a/adafruit_displayio_layout/widgets/switch_round.py +++ b/adafruit_displayio_layout/widgets/switch_round.py @@ -35,14 +35,16 @@ # import time + from adafruit_display_shapes.circle import Circle -from adafruit_display_shapes.roundrect import RoundRect from adafruit_display_shapes.rect import Rect -from adafruit_displayio_layout.widgets.widget import Widget +from adafruit_display_shapes.roundrect import RoundRect + from adafruit_displayio_layout.widgets.control import Control # modify the "easing" function that is imported to change the switch animation behaviour from adafruit_displayio_layout.widgets.easing import back_easeinout as easing +from adafruit_displayio_layout.widgets.widget import Widget try: from typing import Any, Optional, Tuple, Union @@ -55,7 +57,6 @@ class SwitchRound(Widget, Control): - """ .. note:: Jump directly to: @@ -419,9 +420,6 @@ class functions. The `Widget` class handles the overall sizing and positioning """ - # pylint: disable=too-many-instance-attributes, too-many-arguments, too-many-locals - # pylint: disable=too-many-branches, too-many-statements - def __init__( self, x: int = 0, @@ -469,7 +467,6 @@ def __init__( # initialize the Control superclass - # pylint: disable=bad-super-call super(Control, self).__init__() self._horizontal = horizontal @@ -698,9 +695,7 @@ def _draw_position(self, position: float) -> None: position = easing(position) # Get the position offset from the motion function - x_offset, y_offset, _ = self._get_offset_position( - position - ) # ignore angle_offset + x_offset, y_offset, _ = self._get_offset_position(position) # ignore angle_offset # Update the switch and text x- and y-positions self._switch_circle.x = self._switch_initial_x + x_offset @@ -711,9 +706,7 @@ def _draw_position(self, position: float) -> None: self._text_1.y = self._text_1_initial_y + y_offset # Set the color to the correct fade - self._switch_circle.fill = _color_fade( - self._fill_color_off, self._fill_color_on, position - ) + self._switch_circle.fill = _color_fade(self._fill_color_off, self._fill_color_on, position) self._switch_circle.outline = _color_fade( self._outline_color_off, self._outline_color_on, position ) @@ -774,9 +767,7 @@ def _animate_switch(self) -> None: elapsed_time = self._animation_time if self._value: - position = ( - 1 - (elapsed_time) / self._animation_time - ) # fraction from 0 to 1 + position = 1 - (elapsed_time) / self._animation_time # fraction from 0 to 1 else: # fraction from 0 to 1 position = (elapsed_time) / self._animation_time @@ -789,9 +780,7 @@ def _animate_switch(self) -> None: if (position >= 1) and not self._value: self._value = True break - if ( - position <= 0 - ) and self._value: # ensures that the final position is drawn + if (position <= 0) and self._value: # ensures that the final position is drawn self._value = False break @@ -807,9 +796,7 @@ def selected(self, touch_point: Tuple[int, int, Optional[int]]) -> None: self._animate_switch() # show the animation and switch the self._value - touch_x = ( - touch_point[0] - self.x - ) # adjust touch position for the local position + touch_x = touch_point[0] - self.x # adjust touch position for the local position touch_y = touch_point[1] - self.y # Call the parent's .selected function in case there is any work up there. @@ -827,9 +814,7 @@ def contains( :return: Boolean """ - touch_x = ( - touch_point[0] - self.x - ) # adjust touch position for the local position + touch_x = touch_point[0] - self.x # adjust touch position for the local position touch_y = touch_point[1] - self.y return super().contains((touch_x, touch_y, 0)) @@ -945,7 +930,5 @@ def _color_fade( faded_color = [0, 0, 0] for i in range(3): - faded_color[i] = start_color[i] - int( - (start_color[i] - end_color[i]) * fraction - ) + faded_color[i] = start_color[i] - int((start_color[i] - end_color[i]) * fraction) return tuple(faded_color) diff --git a/adafruit_displayio_layout/widgets/widget.py b/adafruit_displayio_layout/widgets/widget.py index 7a376f1..2e6bd8d 100644 --- a/adafruit_displayio_layout/widgets/widget.py +++ b/adafruit_displayio_layout/widgets/widget.py @@ -33,8 +33,6 @@ __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout.git" -# pylint: disable=too-many-arguments - class Widget(displayio.Group): """ diff --git a/docs/api.rst b/docs/api.rst index a707e30..0cddc93 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -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_displayio_layout.layouts.grid_layout :members: :private-members: diff --git a/docs/conf.py b/docs/conf.py index a314186..a0e4431 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -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("..")) @@ -55,9 +53,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 + " Tim Cocks" author = "Tim Cocks" diff --git a/examples/displayio_layout_cartesian_advanced_test.py b/examples/displayio_layout_cartesian_advanced_test.py index e10a765..3acda2e 100644 --- a/examples/displayio_layout_cartesian_advanced_test.py +++ b/examples/displayio_layout_cartesian_advanced_test.py @@ -10,6 +10,7 @@ import board import displayio import terminalio + from adafruit_displayio_layout.widgets.cartesian import Cartesian # Fonts used for the Dial tick labels diff --git a/examples/displayio_layout_cartesian_lineplot.py b/examples/displayio_layout_cartesian_lineplot.py index 14683a0..54ac442 100644 --- a/examples/displayio_layout_cartesian_lineplot.py +++ b/examples/displayio_layout_cartesian_lineplot.py @@ -7,8 +7,10 @@ """ import time + import board import displayio + from adafruit_displayio_layout.widgets.cartesian import Cartesian # create the display on the PyPortal or Clue or PyBadge(for example) diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py index e859380..ba1353c 100644 --- a/examples/displayio_layout_cartesian_simpletest.py +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -7,9 +7,11 @@ """ import time + import board import displayio import terminalio + from adafruit_displayio_layout.widgets.cartesian import Cartesian # Fonts used for the Dial tick labels diff --git a/examples/displayio_layout_flip_input_simpletest.py b/examples/displayio_layout_flip_input_simpletest.py index c51c00d..c6c3ce0 100755 --- a/examples/displayio_layout_flip_input_simpletest.py +++ b/examples/displayio_layout_flip_input_simpletest.py @@ -6,13 +6,13 @@ This is a basic demonstration of a FlipInput widget. """ -# pylint: disable=invalid-name - import time + +import adafruit_touchscreen import board import displayio -import adafruit_touchscreen from adafruit_bitmap_font import bitmap_font + from adafruit_displayio_layout.widgets.flip_input import FlipInput display = board.DISPLAY # create the display on the PyPortal, @@ -62,7 +62,7 @@ anchor_point=[0.0, 0.0], anchored_position=[220, 40], color=0xFF2222, # reddish orange color - value_list=["{0:02d}".format(x) for x in range(1, 31 + 1)], + value_list=[f"{x:02d}" for x in range(1, 31 + 1)], # use a list of strings from 01 through 31 # use the {0:02d} format string to always use two digits (e.g. '03') font_scale=5, @@ -75,7 +75,7 @@ anchor_point=[0.5, 1.0], anchored_position=[320 // 2, 240 - 10], color=0xFF2222, # reddish orange color - value_list=["{}".format(x) for x in range(1985, 2022, 1)], + value_list=[f"{x}" for x in range(1985, 2022, 1)], # use a list with values of stringsfrom 1985 to 2022 font=my_font, horizontal=True, # use horizontal arrows diff --git a/examples/displayio_layout_grid_layout_get_cell_test.py b/examples/displayio_layout_grid_layout_get_cell_test.py index 9e6d674..06ccfd0 100644 --- a/examples/displayio_layout_grid_layout_get_cell_test.py +++ b/examples/displayio_layout_grid_layout_get_cell_test.py @@ -5,10 +5,12 @@ Make green and purple rectangles and then update the color and text values of the labels using the get_cell() function. """ + import board import displayio import terminalio from adafruit_display_text import label + from adafruit_displayio_layout.layouts.grid_layout import GridLayout # use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.) @@ -31,15 +33,11 @@ _labels = [] _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077) ) layout.add_content(_labels[0], grid_position=(0, 0), cell_size=(1, 1)) _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700) ) layout.add_content(_labels[1], grid_position=(1, 0), cell_size=(1, 1)) _labels.append(label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello")) diff --git a/examples/displayio_layout_gridlayout_dividers.py b/examples/displayio_layout_gridlayout_dividers.py index d7cefab..34e47b9 100644 --- a/examples/displayio_layout_gridlayout_dividers.py +++ b/examples/displayio_layout_gridlayout_dividers.py @@ -4,10 +4,12 @@ """ Illustrate how to use divider lines with GridLayout """ + import board import displayio import terminalio from adafruit_display_text import label + from adafruit_displayio_layout.layouts.grid_layout import GridLayout # use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.) @@ -31,15 +33,11 @@ _labels = [] _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077) ) layout.add_content(_labels[0], grid_position=(0, 0), cell_size=(1, 1)) _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700) ) layout.add_content(_labels[1], grid_position=(1, 0), cell_size=(1, 1)) _labels.append(label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello")) diff --git a/examples/displayio_layout_gridlayout_pygame_display_simpletest.py b/examples/displayio_layout_gridlayout_pygame_display_simpletest.py index 15fa6d9..f0a5623 100644 --- a/examples/displayio_layout_gridlayout_pygame_display_simpletest.py +++ b/examples/displayio_layout_gridlayout_pygame_display_simpletest.py @@ -7,12 +7,12 @@ Requires: https://github.com/FoamyGuy/Blinka_Displayio_PyGameDisplay """ + import displayio import terminalio from adafruit_display_text import label from blinka_displayio_pygamedisplay import PyGameDisplay - # Make the display context. Change size if you want from adafruit_displayio_layout.layouts.grid_layout import GridLayout @@ -31,15 +31,11 @@ _labels = [] _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077) ) layout.add_content(_labels[0], grid_position=(0, 0), cell_size=(1, 1)) _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700) ) layout.add_content(_labels[1], grid_position=(1, 0), cell_size=(1, 1)) _labels.append(label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello")) diff --git a/examples/displayio_layout_gridlayout_simpletest.py b/examples/displayio_layout_gridlayout_simpletest.py index 0816dd7..2d0b3ad 100644 --- a/examples/displayio_layout_gridlayout_simpletest.py +++ b/examples/displayio_layout_gridlayout_simpletest.py @@ -5,10 +5,12 @@ Make green and purple rectangles and a "Hello World" label. """ + import board import displayio import terminalio from adafruit_display_text import label + from adafruit_displayio_layout.layouts.grid_layout import GridLayout # use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.) @@ -31,15 +33,11 @@ _labels = [] _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077) ) layout.add_content(_labels[0], grid_position=(0, 0), cell_size=(1, 1)) _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700) ) layout.add_content(_labels[1], grid_position=(1, 0), cell_size=(1, 1)) _labels.append(label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello")) diff --git a/examples/displayio_layout_icon_animated_simpletest.py b/examples/displayio_layout_icon_animated_simpletest.py index c8cb37a..3ec9851 100644 --- a/examples/displayio_layout_icon_animated_simpletest.py +++ b/examples/displayio_layout_icon_animated_simpletest.py @@ -4,10 +4,13 @@ """ Creates two animated icons with touch response: zoom and shrink animations. """ + import time + +import adafruit_touchscreen import board import displayio -import adafruit_touchscreen + from adafruit_displayio_layout.widgets.icon_animated import IconAnimated display = board.DISPLAY @@ -22,9 +25,7 @@ ) -IconAnimated.init_class( - display, max_scale=1.5, max_icon_size=(48, 48), max_color_depth=255 -) +IconAnimated.init_class(display, max_scale=1.5, max_icon_size=(48, 48), max_color_depth=255) icon_zoom = IconAnimated( "Zoom", diff --git a/examples/displayio_layout_linearlayout_simpletest.py b/examples/displayio_layout_linearlayout_simpletest.py index 4090561..1925330 100644 --- a/examples/displayio_layout_linearlayout_simpletest.py +++ b/examples/displayio_layout_linearlayout_simpletest.py @@ -5,11 +5,13 @@ Illustrates usage of LinearLayout to display a text label to the right of an icon. """ + import adafruit_imageload import board import displayio import terminalio from adafruit_display_text import label + from adafruit_displayio_layout.layouts.linear_layout import LinearLayout # use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.) @@ -21,9 +23,7 @@ main_group = displayio.Group() display.root_group = main_group -layout = LinearLayout( - x=10, y=10, padding=4, orientation=LinearLayout.HORIZONTAL_ORIENTATION -) +layout = LinearLayout(x=10, y=10, padding=4, orientation=LinearLayout.HORIZONTAL_ORIENTATION) lbl = label.Label(terminalio.FONT, scale=4, x=0, y=0, text="Hello") diff --git a/examples/displayio_layout_page_layout_advancedtest.py b/examples/displayio_layout_page_layout_advancedtest.py index 9a6bde8..7dbdca7 100644 --- a/examples/displayio_layout_page_layout_advancedtest.py +++ b/examples/displayio_layout_page_layout_advancedtest.py @@ -4,14 +4,17 @@ """ Make a PageLayout and illustrate all of it's features """ + import time -import displayio + import board +import displayio import terminalio -from adafruit_display_text.bitmap_label import Label -from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.circle import Circle +from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.triangle import Triangle +from adafruit_display_text.bitmap_label import Label + from adafruit_displayio_layout.layouts.page_layout import PageLayout # built-in display @@ -77,22 +80,22 @@ # change page with function by name test_page_layout.show_page(page_name="page_3") -print("showing page index:{}".format(test_page_layout.showing_page_index)) +print(f"showing page index:{test_page_layout.showing_page_index}") time.sleep(1) # change page with function by index test_page_layout.show_page(page_index=0) -print("showing page name: {}".format(test_page_layout.showing_page_name)) +print(f"showing page name: {test_page_layout.showing_page_name}") time.sleep(1) # change page by updating the page name property test_page_layout.showing_page_name = "page_3" -print("showing page index: {}".format(test_page_layout.showing_page_index)) +print(f"showing page index: {test_page_layout.showing_page_index}") time.sleep(1) # change page by updating the page index property test_page_layout.showing_page_index = 1 -print("showing page name: {}".format(test_page_layout.showing_page_name)) +print(f"showing page name: {test_page_layout.showing_page_name}") time.sleep(5) another_text = Label( diff --git a/examples/displayio_layout_page_layout_simpletest.py b/examples/displayio_layout_page_layout_simpletest.py index b11c02c..74e3120 100644 --- a/examples/displayio_layout_page_layout_simpletest.py +++ b/examples/displayio_layout_page_layout_simpletest.py @@ -4,13 +4,16 @@ """ Make a PageLayout with two pages and change between them. """ + import time -import displayio + import board +import displayio import terminalio -from adafruit_display_text.bitmap_label import Label -from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.circle import Circle +from adafruit_display_shapes.rect import Rect +from adafruit_display_text.bitmap_label import Label + from adafruit_displayio_layout.layouts.page_layout import PageLayout # built-in display diff --git a/examples/displayio_layout_pygame_display_switch_round.py b/examples/displayio_layout_pygame_display_switch_round.py index c21111b..c85f241 100644 --- a/examples/displayio_layout_pygame_display_switch_round.py +++ b/examples/displayio_layout_pygame_display_switch_round.py @@ -7,11 +7,12 @@ Requires: https://github.com/FoamyGuy/Blinka_Displayio_PyGameDisplay """ + import displayio import pygame from blinka_displayio_pygamedisplay import PyGameDisplay -from adafruit_displayio_layout.widgets.switch_round import SwitchRound as Switch +from adafruit_displayio_layout.widgets.switch_round import SwitchRound as Switch # Make the display context. Change size if you want display = PyGameDisplay(width=320, height=240) diff --git a/examples/displayio_layout_simpletest.py b/examples/displayio_layout_simpletest.py index 16b3bb4..2b79736 100644 --- a/examples/displayio_layout_simpletest.py +++ b/examples/displayio_layout_simpletest.py @@ -7,10 +7,12 @@ Make green and purple rectangles and a "Hello World" label. """ + import board import displayio import terminalio from adafruit_display_text import label + from adafruit_displayio_layout.layouts.grid_layout import GridLayout # use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.) @@ -33,15 +35,11 @@ _labels = [] _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello", background_color=0x770077) ) layout.add_content(_labels[0], grid_position=(0, 0), cell_size=(1, 1)) _labels.append( - label.Label( - terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700 - ) + label.Label(terminalio.FONT, scale=2, x=0, y=0, text="World", background_color=0x007700) ) layout.add_content(_labels[1], grid_position=(1, 0), cell_size=(1, 1)) _labels.append(label.Label(terminalio.FONT, scale=2, x=0, y=0, text="Hello")) diff --git a/examples/displayio_layout_switch_multiple.py b/examples/displayio_layout_switch_multiple.py index 6cb1bab..5f8a2ce 100755 --- a/examples/displayio_layout_switch_multiple.py +++ b/examples/displayio_layout_switch_multiple.py @@ -6,9 +6,11 @@ """ import time + +import adafruit_touchscreen import board import displayio -import adafruit_touchscreen + from adafruit_displayio_layout.widgets.switch_round import SwitchRound as Switch display = board.DISPLAY diff --git a/examples/displayio_layout_switch_simpletest.py b/examples/displayio_layout_switch_simpletest.py index a9cfbc8..432c1e0 100644 --- a/examples/displayio_layout_switch_simpletest.py +++ b/examples/displayio_layout_switch_simpletest.py @@ -6,9 +6,11 @@ """ import time + +import adafruit_touchscreen import board import displayio -import adafruit_touchscreen + from adafruit_displayio_layout.widgets.switch_round import SwitchRound as Switch display = board.DISPLAY diff --git a/examples/displayio_layout_tab_layout_simpletest.py b/examples/displayio_layout_tab_layout_simpletest.py index 188cd75..c8c73b4 100644 --- a/examples/displayio_layout_tab_layout_simpletest.py +++ b/examples/displayio_layout_tab_layout_simpletest.py @@ -4,14 +4,17 @@ """ Make a TabLayout and illustrate the most basic features and usage. """ + import time -import displayio + import board +import displayio import terminalio -from adafruit_display_text.bitmap_label import Label -from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.circle import Circle +from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.triangle import Triangle +from adafruit_display_text.bitmap_label import Label + from adafruit_displayio_layout.layouts.tab_layout import TabLayout CHANGE_DELAY = 1.0 # Seconds to wait before auto-advancing to the next tab @@ -108,22 +111,22 @@ # change page with function by name test_page_layout.show_page(page_name="Thr") -print("showing page index:{}".format(test_page_layout.showing_page_index)) +print(f"showing page index:{test_page_layout.showing_page_index}") time.sleep(1) # change page with function by index test_page_layout.show_page(page_index=0) -print("showing page name: {}".format(test_page_layout.showing_page_name)) +print(f"showing page name: {test_page_layout.showing_page_name}") time.sleep(1) # change page by updating the page name property test_page_layout.showing_page_name = "Thr" -print("showing page index: {}".format(test_page_layout.showing_page_index)) +print(f"showing page index: {test_page_layout.showing_page_index}") time.sleep(1) # change page by updating the page index property test_page_layout.showing_page_index = 1 -print("showing page name: {}".format(test_page_layout.showing_page_name)) +print(f"showing page name: {test_page_layout.showing_page_name}") time.sleep(5) another_text = Label( diff --git a/examples/displayio_layout_tab_layout_touchtest.py b/examples/displayio_layout_tab_layout_touchtest.py index e8fe6ee..a58db70 100644 --- a/examples/displayio_layout_tab_layout_touchtest.py +++ b/examples/displayio_layout_tab_layout_touchtest.py @@ -4,14 +4,16 @@ """ Make a TabLayout change tabs with the touchscreen """ -import displayio + +import adafruit_touchscreen import board +import displayio import terminalio -import adafruit_touchscreen -from adafruit_display_text.bitmap_label import Label -from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.circle import Circle +from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.triangle import Triangle +from adafruit_display_text.bitmap_label import Label + from adafruit_displayio_layout.layouts.tab_layout import TabLayout # built-in display diff --git a/examples/hotplug_sensor_examples/displayio_layout_hotplug_rtc.py b/examples/hotplug_sensor_examples/displayio_layout_hotplug_rtc.py index 041bbcf..1268b53 100644 --- a/examples/hotplug_sensor_examples/displayio_layout_hotplug_rtc.py +++ b/examples/hotplug_sensor_examples/displayio_layout_hotplug_rtc.py @@ -6,16 +6,18 @@ """ import time -import displayio + +import adafruit_tmp117 import board +import displayio import terminalio -import adafruit_tmp117 -from adafruit_ds3231 import DS3231 -from adafruit_display_text.bitmap_label import Label -from adafruit_display_shapes.rect import Rect +from adafruit_bitmap_font import bitmap_font from adafruit_display_shapes.circle import Circle +from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.triangle import Triangle -from adafruit_bitmap_font import bitmap_font +from adafruit_display_text.bitmap_label import Label +from adafruit_ds3231 import DS3231 + from adafruit_displayio_layout.layouts.tab_layout import TabLayout # +-------------------------------------------------------+ @@ -89,13 +91,9 @@ def write(self, s, value): # key: {}".format(s, n)) self.g_vars[n] = value else: - raise KeyError( - "variable '{:" ">20s}' not found in self.gVars_rDict".format(s) - ) + raise KeyError("variable '{:" ">20s}' not found in self.gVars_rDict".format(s)) else: - raise TypeError( - "myVars.write(): param s expected str, {} received".format(type(s)) - ) + raise TypeError(f"myVars.write(): param s expected str, {type(s)} received") def read(self, s): RetVal = None @@ -135,8 +133,7 @@ def clean(self): def list(self): for i in range(0, len(self.g_vars) - 1): print( - "self.g_vars['{:" - ">20s}'] = {}".format( + "self.g_vars['{:" ">20s}'] = {}".format( self.gVarsDict[i], self.g_vars[i] if i in self.g_vars else "None" ) ) @@ -358,22 +355,22 @@ def list(self): # change page with function by name test_page_layout.show_page(page_name=pages[2]) -print("showing page index:{}".format(test_page_layout.showing_page_index)) +print(f"showing page index:{test_page_layout.showing_page_index}") time.sleep(1) # change page with function by index test_page_layout.show_page(page_index=0) -print("showing page name: {}".format(test_page_layout.showing_page_name)) +print(f"showing page name: {test_page_layout.showing_page_name}") time.sleep(1) # change page by updating the page name property test_page_layout.showing_page_name = pages[2] -print("showing page index: {}".format(test_page_layout.showing_page_index)) +print(f"showing page index: {test_page_layout.showing_page_index}") time.sleep(1) # change page by updating the page index property test_page_layout.showing_page_index = 1 -print("showing page name: {}".format(test_page_layout.showing_page_name)) +print(f"showing page name: {test_page_layout.showing_page_name}") time.sleep(5) """ @@ -471,12 +468,8 @@ def get_temp(): temp = myVars.read("temp_sensor").temperature if myVars.read("temp_in_fahrenheit"): temp = (temp * 1.8) + 32 - t = "{:5.2f} ".format(temp) + myVars.read("t1") - if ( - myVars.read("my_debug") - and temp is not None - and not myVars.read("temp_in_REPL") - ): + t = f"{temp:5.2f} " + myVars.read("t1") + if myVars.read("my_debug") and temp is not None and not myVars.read("temp_in_REPL"): myVars.write("temp_in_REPL", True) print("get_temp(): {} {}".format(myVars.read("t0"), t)) if showing_page_idx == 3: # show temperature on most right Tab page @@ -485,7 +478,7 @@ def get_temp(): "old_temp" ): # Only update if there is a change in temperature myVars.write("old_temp", temp) - t = "{:5.2f} ".format(temp) + myVars.read("t1") + t = f"{temp:5.2f} " + myVars.read("t1") pge4_lbl.text = "" pge4_lbl2.text = myVars.read("t0") pge4_lbl3.text = t @@ -500,20 +493,13 @@ def get_temp(): print("Temperature sensor has disconnected") t = "" myVars.write("temp_sensor", None) - pge4_lbl.text = myVars.read( - "pge4_lbl_dflt" - ) # clean the line (eventually: t2) + pge4_lbl.text = myVars.read("pge4_lbl_dflt") # clean the line (eventually: t2) pge4_lbl2.text = "" pge4_lbl3.text = "" return RetVal -""" - Function called by get_dt() - Created to repair pylint error R0912: Too many branches (13/12) -""" - yy = 0 mo = 1 dd = 2 @@ -562,14 +548,14 @@ def handle_dt(dt): if myVars.read("c_secs") != myVars.read("o_secs"): myVars.write("o_secs", myVars.read("c_secs")) - sDT3 = s + "{} {}".format(sDT, sDT2) + sDT3 = s + f"{sDT} {sDT2}" print(sDT3) pge3_lbl3.text = sDT2 if myVars.read("my_debug"): - print("pge3_lbl.text = {}".format(pge3_lbl.text)) - print("pge3_lbl2.text = {}".format(pge3_lbl2.text)) - print("pge3_lbl3.text = {}".format(pge3_lbl3.text)) + print(f"pge3_lbl.text = {pge3_lbl.text}") + print(f"pge3_lbl2.text = {pge3_lbl2.text}") + print(f"pge3_lbl3.text = {pge3_lbl3.text}") RetVal = True # Return from here with a False but don't set the pge3_lbl to default. @@ -627,7 +613,7 @@ def main(): cnt = 0 while True: try: - print("Loop nr: {:03d}".format(cnt)) + print(f"Loop nr: {cnt:03d}") # print("main(): type(rtc) object = ", type(myVars.read("rtc"))) if myVars.read("rtc") is not None: get_dt() diff --git a/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py b/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py index 6ec1cb1..81cd23d 100644 --- a/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py +++ b/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py @@ -9,26 +9,28 @@ However, when the flag 'use_ntp' is set, the DS3231 will not be used instead the NTP class from adafruit_ntp.py will be used. """ + import time + +import adafruit_tmp117 +import adafruit_touchscreen import board import busio import displayio +import neopixel import terminalio -import adafruit_tmp117 +from adafruit_bitmap_font import bitmap_font +from adafruit_display_shapes.circle import Circle +from adafruit_display_shapes.rect import Rect +from adafruit_display_shapes.triangle import Triangle +from adafruit_display_text.bitmap_label import Label from adafruit_ds3231 import DS3231 -from digitalio import DigitalInOut -import neopixel -import adafruit_touchscreen from adafruit_esp32spi import adafruit_esp32spi from adafruit_ntp import NTP from adafruit_pyportal import PyPortal -from adafruit_display_text.bitmap_label import Label -from adafruit_display_shapes.rect import Rect -from adafruit_display_shapes.circle import Circle -from adafruit_display_shapes.triangle import Triangle -from adafruit_bitmap_font import bitmap_font -from adafruit_displayio_layout.layouts.tab_layout import TabLayout +from digitalio import DigitalInOut +from adafruit_displayio_layout.layouts.tab_layout import TabLayout # +-------------------------------------------------------+ # | Definition for variables in the past defined as global| @@ -115,13 +117,9 @@ def write(self, s, value): # key: {}".format(s, n)) self.g_vars[n] = value else: - raise KeyError( - "variable '{:" ">20s}' not found in self.gVars_rDict".format(s) - ) + raise KeyError("variable '{:" ">20s}' not found in self.gVars_rDict".format(s)) else: - raise TypeError( - "myVars.write(): param s expected str, {} received".format(type(s)) - ) + raise TypeError(f"myVars.write(): param s expected str, {type(s)} received") def read(self, s): RetVal = None @@ -168,8 +166,7 @@ def clean(self): def list(self): for i in range(0, len(self.g_vars) - 1): print( - "self.g_vars['{:" - ">20s}'] = {}".format( + "self.g_vars['{:" ">20s}'] = {}".format( self.gVarsDict[i], self.g_vars[i] if i in self.g_vars else "None" ) ) @@ -337,10 +334,7 @@ def list(self): print("Please wait...") if myVars.read("my_debug"): print("My IP address is", esp.pretty_ip(esp.ip_address)) - print( - "IP lookup adafruit.com: %s" - % esp.pretty_ip(esp.get_host_by_name("adafruit.com")) - ) + print("IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com"))) print("Ping google.com: %d ms" % esp.ping("google.com")) @@ -368,7 +362,7 @@ def refresh_from_NTP(): # (defined in secrets.h) ntp_current_time = time.time() if myVars.read("my_debug"): - print("Seconds since Jan 1, 1970: {} seconds".format(ntp_current_time)) + print(f"Seconds since Jan 1, 1970: {ntp_current_time} seconds") # Convert the current time in seconds since Jan 1, 1970 to a struct_time myVars.write("default_dt", time.localtime(ntp_current_time)) @@ -761,33 +755,22 @@ def get_temp(): print("Temperature sensor has disconnected") t = "" myVars.write("temp_sensor", None) - pge4_lbl.text = myVars.read( - "pge4_lbl_dflt" - ) # clean the line (eventually: t2) + pge4_lbl.text = myVars.read("pge4_lbl_dflt") # clean the line (eventually: t2) pge4_lbl2.text = "Sensor disconnected." pge4_lbl3.text = "Check wiring." return RetVal -# Moved these six definitions outside handle_dt() -# to correct pylint error 'too many variables' dt_ridxs = {"yy": 0, "mo": 1, "dd": 2, "hh": 3, "mm": 4, "ss": 5} # print("dict dt_ridxs =", dt_ridxs.keys()) -""" Function called by get_dt() - Created to repair pylint error R0912: Too many branches (13/12)""" - - def handle_dt(dt): my_debug = myVars.read("my_debug") RetVal = False s = "Date/time: " sYY = str(dt[dt_ridxs["yy"]]) # was: str(dt[yy]) - # print("dt_ridxs["mo"] = ", dt_ridxs["mo"]) - # modified mo because plynt error R0914 'Too many local variables' - # mo = dt_ridxs["mo"] dd = dt_ridxs["dd"] hh = dt_ridxs["hh"] mm = dt_ridxs["mm"] @@ -831,14 +814,14 @@ def handle_dt(dt): if myVars.read("c_secs") != myVars.read("o_secs"): myVars.write("o_secs", myVars.read("c_secs")) - sDT3 = s + "{} {}".format(sDT, sDT2) + sDT3 = s + f"{sDT} {sDT2}" print(sDT3) pge3_lbl3.text = sDT2 if my_debug: - print("pge3_lbl.text = {}".format(pge3_lbl.text)) - print("pge3_lbl2.text = {}".format(pge3_lbl2.text)) - print("pge3_lbl3.text = {}".format(pge3_lbl3.text)) + print(f"pge3_lbl.text = {pge3_lbl.text}") + print(f"pge3_lbl2.text = {pge3_lbl2.text}") + print(f"pge3_lbl3.text = {pge3_lbl3.text}") RetVal = True # Return from here with a False but don't set the pge3_lbl to default. @@ -898,11 +881,6 @@ def hms_to_cnt(): return (dt.tm_hour * 3600) + (dt.tm_min * 60) + dt.tm_sec -""" Created this function to correct pylint errors: - 'Too many branches' R0912 and - 'Too many statements' R0915""" - - def ck_next_NTP_sync(): s_cnt = myVars.read("s_cnt") c_cnt = hms_to_cnt() # set current count (seconds) @@ -917,9 +895,7 @@ def ck_next_NTP_sync(): myVars.write("s_cnt", hms_to_cnt()) # --- five minutes count down calculations #1 --- if my_debug: - print( - TAG + "five_min = {}, s_cnt = {}, c_cnt = {}".format(five_min, s_cnt, c_cnt) - ) + print(TAG + f"five_min = {five_min}, s_cnt = {s_cnt}, c_cnt = {c_cnt}") print(TAG + "c_elapsed = ", c_elapsed) # --- five minutes count down calculations #2 --- @@ -928,7 +904,7 @@ def ck_next_NTP_sync(): myVars.write("five_min_cnt", five_min) # remember count mm2 = five_min // 60 ss2 = five_min - (mm2 * 60) - t2 = "{:02d}:{:02d}".format(mm2, ss2) + t2 = f"{mm2:02d}:{ss2:02d}" t0 = t1 + t2 + t3 print(t0) pge3_lbl4.text = t0 @@ -973,7 +949,7 @@ def main(): if otp and ntp_refresh: refresh_from_NTP() # first re-synchronize internal clock from NTP server if get_dt(): - print("Loop nr: {:03d}".format(cnt)) + print(f"Loop nr: {cnt:03d}") else: connect_rtc() if myVars.read("temp_sensor") is not None: diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..5a5dbf0 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,101 @@ +# 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 + "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 + "PLR0912", # too-many-branches + "PLR0913", # too-many-arguments + "PLR0914", # too-many-locals + "PLR0915", # too-many-statements + "PLR0917", # too-many-positional-arguments + +] + +[format] +line-ending = "lf" From 7a6bc24462e4e72c3b0942a89ac6f3e239bee573 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 24 Feb 2025 18:24:19 -0600 Subject: [PATCH 11/13] use plus between f-strings --- adafruit_displayio_layout/widgets/cartesian.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 21bbdc8..50ca8a3 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -479,15 +479,14 @@ def _add_point(self, x: int, y: int) -> None: print("") print( f"xy: ({x: >4}, {y: >4}) " - f"_xrange: ({self._xrange[0]: >4}, {self._xrange[1]: >4}) " - f"_yrange: ({self._yrange[0]: >4}, {self._yrange[1]: >4}) " + + f"_xrange: ({self._xrange[0]: >4}, {self._xrange[1]: >4}) " + + f"_yrange: ({self._yrange[0]: >4}, {self._yrange[1]: >4}) " "" ) print( f"local_*: ({local_x: >4}, {local_y: >4}) " - f" width: ({0: >4}, {self.width: >4}) " - f" height: ({0: >4}, {self.height: >4}) " - "" + + f" width: ({0: >4}, {self.width: >4}) " + + f" height: ({0: >4}, {self.height: >4}) " ) if self._check_xy_in_range(x, y): if self._check_local_xy_in_range(local_x, local_y): From 2f031fc9e3eb2e56f7d38d969c76e689ddd97fb1 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Thu, 27 Feb 2025 15:38:32 -0800 Subject: [PATCH 12/13] Remove secrets usage --- .../displayio_layout_hotplug_temp_sensor.py | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py b/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py index 81cd23d..7c2a0dd 100644 --- a/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py +++ b/examples/hotplug_sensor_examples/displayio_layout_hotplug_temp_sensor.py @@ -11,6 +11,7 @@ """ import time +from os import getenv import adafruit_tmp117 import adafruit_touchscreen @@ -275,7 +276,7 @@ def list(self): ) else: print("\nTabLayout test with I2C Temperature sensor and I2C Realtime clock") -print("Add your WiFi SSID, WiFi password and Timezone in file: secrets.h\n") +print("Add your WiFi SSID, WiFi password and Timezone in file: settings.toml\n") if myVars.read("my_debug"): while not i2c.try_lock(): @@ -303,13 +304,9 @@ def list(self): # NOTE: there is also the board.SD_CARD_DETECT pin (33)(but I don't know yet how to interface it) #### -# you'll need to pass in an io username and key -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get WiFi details, ensure these are setup in settings.toml +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") if myVars.read("my_debug"): if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: @@ -320,13 +317,13 @@ def list(self): for ap in esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"])) -# Get our username, key and desired timezone -location = secrets.get("timezone", None) +# Get our desired timezone +location = getenv("timezone", None) print("\nConnecting to AP...") while not esp.is_connected: try: - esp.connect_AP(secrets["ssid"], secrets["password"]) + esp.connect_AP(ssid, password) except RuntimeError as e: print("could not connect to AP, retrying: ", e) continue @@ -359,7 +356,7 @@ def refresh_from_NTP(): myVars.write("online_time_present", True) myVars.write("ntp_refresh", False) # Get the current time in seconds since Jan 1, 1970 and correct it for local timezone - # (defined in secrets.h) + # (defined in settings.toml) ntp_current_time = time.time() if myVars.read("my_debug"): print(f"Seconds since Jan 1, 1970: {ntp_current_time} seconds") @@ -377,9 +374,9 @@ def refresh_from_NTP(): # Initialize the NTP object ntp = NTP(esp) - location = secrets.get("timezone", location) + location = getenv("timezone", location) if myVars.read("my_debug"): - print("location (from secrets.h) = ", location) + print(f"location (from settings.toml) = {location}") if location == "Europe/Lisbon": if myVars.read("my_debug"): print("Using timezone Europe/Lisbon") From 746b1886b58dd4ef10ac369a7f59c4db7ad886ec Mon Sep 17 00:00:00 2001 From: foamyguy Date: Wed, 2 Apr 2025 10:14:02 -0500 Subject: [PATCH 13/13] add pop_content, rename get_cell to get_content --- .../layouts/grid_layout.py | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/adafruit_displayio_layout/layouts/grid_layout.py b/adafruit_displayio_layout/layouts/grid_layout.py index 5d2be9b..957cb91 100644 --- a/adafruit_displayio_layout/layouts/grid_layout.py +++ b/adafruit_displayio_layout/layouts/grid_layout.py @@ -393,31 +393,63 @@ def add_content( if layout_cells: self._layout_cells() - def get_cell(self, cell_coordinates: Tuple[int, int]) -> displayio.Group: + def get_content(self, grid_position: Tuple[int, int]) -> displayio.Group: """ - Return a cells content based on the cell_coordinates. Raises + Return a cells content based on the grid_position. Raises KeyError if coordinates were not found in the GridLayout. - :param tuple cell_coordinates: the coordinates to lookup in the grid + :param tuple grid_position: the coordinates to lookup in the grid :return: the displayio content object at those coordinates """ for index, cell in enumerate(self._cell_content_list): # exact location 1x1 cell - if cell["grid_position"] == cell_coordinates: + if cell["grid_position"] == grid_position: return self._cell_content_list[index]["content"] # multi-spanning cell, any size bigger than 1x1 if ( cell["grid_position"][0] - <= cell_coordinates[0] + <= grid_position[0] < cell["grid_position"][0] + cell["cell_size"][0] and cell["grid_position"][1] - <= cell_coordinates[1] + <= grid_position[1] < cell["grid_position"][1] + cell["cell_size"][1] ): return self._cell_content_list[index]["content"] - raise KeyError(f"GridLayout does not contain cell at coordinates {cell_coordinates}") + raise KeyError(f"GridLayout does not contain content at coordinates {grid_position}") + + def pop_content(self, grid_position: Tuple[int, int]) -> None: + """ + Remove and return a cells content based on the grid_position. Raises + KeyError if coordinates were not found in the GridLayout. + + :param tuple grid_position: the coordinates to lookup in the grid + :return: the displayio content object at those coordinates + """ + for index, cell in enumerate(self._cell_content_list): + # exact location 1x1 cell + if cell["grid_position"] == grid_position: + _found = self._cell_content_list.pop(index) + self._layout_cells() + self.remove(_found["content"]) + return _found["content"] + + # multi-spanning cell, any size bigger than 1x1 + if ( + cell["grid_position"][0] + <= grid_position[0] + < cell["grid_position"][0] + cell["cell_size"][0] + and cell["grid_position"][1] + <= grid_position[1] + < cell["grid_position"][1] + cell["cell_size"][1] + ): + _found = self._cell_content_list.pop(index) + self._layout_cells() + self.remove(_found["content"]) + return _found["content"] + + raise KeyError(f"GridLayout does not contain content at coordinates {grid_position}") @property def cell_size_pixels(self) -> Tuple[int, int]: