Skip to content

Type annotations in Display_text label library as a sample test for pylint and CI verifications #123

New issue

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

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

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
9 changes: 5 additions & 4 deletions adafruit_display_text/bitmap_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def __init__(
) # the local_group will always stay in the self Group

self._font = font
self._text = text
self._text = " ".join(text.split("\t"))

# Create the two-color palette
self.palette = displayio.Palette(2)
Expand Down Expand Up @@ -204,7 +204,7 @@ def _reset_text(
text = self._text

if self._save_text: # text string will be saved
self._text = text
self._text = " ".join(text.split("\t"))
else:
self._text = None # save a None value since text string is not saved

Expand Down Expand Up @@ -239,7 +239,7 @@ def _reset_text(
loose_box_y,
loose_y_offset,
) = self._text_bounding_box(
text,
self._text,
self._font,
self._line_spacing,
) # calculate the box size for a tight and loose backgrounds
Expand All @@ -262,7 +262,7 @@ def _reset_text(
# Place the text into the Bitmap
self._place_text(
self.bitmap,
text,
self._text,
self._font,
self._line_spacing,
self._padding_left - x_offset,
Expand Down Expand Up @@ -632,6 +632,7 @@ def text(self):

@text.setter # Cannot set color or background color with text setter, use separate setter
def text(self, new_text):
new_text = " ".join(new_text.split("\t"))
self._reset_text(text=new_text, scale=self.scale)

@property
Expand Down
83 changes: 42 additions & 41 deletions adafruit_display_text/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
https://github.com/adafruit/circuitpython/releases

"""

from typing import Tuple
import displayio

__version__ = "0.0.0-auto.0"
Expand Down Expand Up @@ -70,30 +70,31 @@ def __init__(
self,
font,
*,
x=0,
y=0,
text="",
max_glyphs=None,
color=0xFFFFFF,
background_color=None,
line_spacing=1.25,
background_tight=False,
padding_top=0,
padding_bottom=0,
padding_left=0,
padding_right=0,
anchor_point=None,
anchored_position=None,
scale=1,
base_alignment=False,
x: int = 0,
y: int = 0,
text: str = "",
max_glyphs: int = None,
color: int = 0xFFFFFF,
background_color: int = None,
line_spacing: float = 1.25,
background_tight: bool = False,
padding_top: int = 0,
padding_bottom: int = 0,
padding_left: int = 0,
padding_right: int = 0,
anchor_point: Tuple[float, float] = None,
anchored_position: Tuple[int, int] = None,
scale: int = 1,
base_alignment: bool = False,
**kwargs
):
) -> None:
if not max_glyphs and not text:
raise RuntimeError("Please provide a max size, or initial text")
text = " ".join(text.split("\t"))
if not max_glyphs:
max_glyphs = len(text)
# add one to max_size for the background bitmap tileGrid

# add one to max_size for the background bitmap tileGrid
# instance the Group
# self Group will contain a single local_group which contains a Group (self.local_group)
# which contains a TileGrid
Expand Down Expand Up @@ -139,7 +140,7 @@ def __init__(
if (anchored_position is not None) and (anchor_point is not None):
self.anchored_position = anchored_position

def _create_background_box(self, lines, y_offset):
def _create_background_box(self, lines: int, y_offset: int) -> None:
"""Private Class function to create a background_box
:param lines: int number of lines
:param y_offset: int y pixel bottom coordinate for the background_box"""
Expand Down Expand Up @@ -181,7 +182,7 @@ def _create_background_box(self, lines, y_offset):

return tile_grid

def _get_ascent_descent(self):
def _get_ascent_descent(self) -> Tuple[int, int]:
""" Private function to calculate ascent and descent font values """
if hasattr(self.font, "ascent"):
return self.font.ascent, self.font.descent
Expand All @@ -202,10 +203,10 @@ def _get_ascent_descent(self):
descender_max = max(descender_max, -this_glyph.dy)
return ascender_max, descender_max

def _get_ascent(self):
def _get_ascent(self) -> int:
return self._get_ascent_descent()[0]

def _update_background_color(self, new_color):
def _update_background_color(self, new_color: int) -> None:
"""Private class function that allows updating the font box background color
:param new_color: int color as an RGB hex number."""

Expand Down Expand Up @@ -260,9 +261,8 @@ def _update_background_color(self, new_color):
self.local_group.pop(0)
self._added_background_tilegrid = False

def _update_text(
self, new_text
): # pylint: disable=too-many-locals ,too-many-branches, too-many-statements
def _update_text(self, new_text: str) -> None:
# pylint: disable=too-many-locals ,too-many-branches, too-many-statements
x = 0
y = 0
if self._added_background_tilegrid:
Expand Down Expand Up @@ -339,19 +339,19 @@ def _update_text(
self._update_background_color(self._background_color)

@property
def bounding_box(self):
def bounding_box(self) -> Tuple[int, int, int, int]:
"""An (x, y, w, h) tuple that completely covers all glyphs. The
first two numbers are offset from the x, y origin of this group"""
return tuple(self._boundingbox)

@property
def line_spacing(self):
def line_spacing(self) -> float:
"""The amount of space between lines of text, in multiples of the font's
bounding-box height. (E.g. 1.0 is the bounding-box height)"""
return self._line_spacing

@line_spacing.setter
def line_spacing(self, spacing):
def line_spacing(self, spacing: float) -> None:
self._line_spacing = spacing
self.text = self._text # redraw the box

Expand All @@ -361,7 +361,7 @@ def color(self):
return self.palette[1]

@color.setter
def color(self, new_color):
def color(self, new_color: int) -> None:
self._color = new_color
if new_color is not None:
self.palette[1] = new_color
Expand All @@ -371,21 +371,22 @@ def color(self, new_color):
self.palette.make_transparent(1)

@property
def background_color(self):
def background_color(self) -> int:
"""Color of the background as an RGB hex number."""
return self._background_color

@background_color.setter
def background_color(self, new_color):
def background_color(self, new_color: int) -> None:
self._update_background_color(new_color)

@property
def text(self):
def text(self) -> str:
"""Text to display."""
return self._text

@text.setter
def text(self, new_text):
def text(self, new_text: str) -> None:
new_text = " ".join(new_text.split("\t"))
try:
current_anchored_position = self.anchored_position
self._update_text(str(new_text))
Expand All @@ -394,12 +395,12 @@ def text(self, new_text):
raise RuntimeError("Text length exceeds max_glyphs") from run_error

@property
def scale(self):
def scale(self) -> int:
"""Set the scaling of the label, in integer values"""
return self.local_group.scale

@scale.setter
def scale(self, new_scale):
def scale(self, new_scale: int) -> None:
current_anchored_position = self.anchored_position
self.local_group.scale = new_scale
self.anchored_position = current_anchored_position
Expand All @@ -410,7 +411,7 @@ def font(self):
return self._font

@font.setter
def font(self, new_font):
def font(self, new_font) -> None:
old_text = self._text
current_anchored_position = self.anchored_position
self._text = ""
Expand All @@ -420,14 +421,14 @@ def font(self, new_font):
self.anchored_position = current_anchored_position

@property
def anchor_point(self):
def anchor_point(self) -> Tuple[float, float]:
"""Point that anchored_position moves relative to.
Tuple with decimal percentage of width and height.
(E.g. (0,0) is top left, (1.0, 0.5): is middle right.)"""
return self._anchor_point

@anchor_point.setter
def anchor_point(self, new_anchor_point):
def anchor_point(self, new_anchor_point: Tuple[float, float]) -> None:
if self._anchor_point is not None:
current_anchored_position = self.anchored_position
self._anchor_point = new_anchor_point
Expand All @@ -436,7 +437,7 @@ def anchor_point(self, new_anchor_point):
self._anchor_point = new_anchor_point

@property
def anchored_position(self):
def anchored_position(self) -> Tuple[int, int]:
"""Position relative to the anchor_point. Tuple containing x,y
pixel coordinates."""
if self._anchor_point is None:
Expand All @@ -455,7 +456,7 @@ def anchored_position(self):
)

@anchored_position.setter
def anchored_position(self, new_position):
def anchored_position(self, new_position: Tuple[int, int]) -> None:
if (self._anchor_point is None) or (new_position is None):
return # Note: anchor_point must be set before setting anchored_position
self.x = int(
Expand Down