From e94214fc5782612585b152263d5da474439a8fa7 Mon Sep 17 00:00:00 2001 From: Isaac Benitez Date: Mon, 6 Jun 2022 21:06:02 -0700 Subject: [PATCH 1/4] Added Type Annotations --- adafruit_bitmap_font/bdf.py | 21 ++++++++++++------- adafruit_bitmap_font/bitmap_font.py | 24 +++++++++++++--------- adafruit_bitmap_font/glyph_cache.py | 12 ++++++++--- adafruit_bitmap_font/pcf.py | 32 +++++++++++++++++------------ adafruit_bitmap_font/ttf.py | 7 ++++--- 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/adafruit_bitmap_font/bdf.py b/adafruit_bitmap_font/bdf.py index e6c7e3d..9b791ce 100644 --- a/adafruit_bitmap_font/bdf.py +++ b/adafruit_bitmap_font/bdf.py @@ -22,8 +22,15 @@ """ +try: + from typing import Union, Optional, Tuple +except ImportError: + pass + import gc +from io import FileIO from fontio import Glyph +from displayio import Bitmap from .glyph_cache import GlyphCache __version__ = "0.0.0-auto.0" @@ -33,7 +40,7 @@ class BDF(GlyphCache): """Loads glyphs from a BDF file in the given bitmap_class.""" - def __init__(self, f, bitmap_class): + def __init__(self, f: FileIO, bitmap_class: Bitmap) -> None: super().__init__() self.file = f self.name = f @@ -50,7 +57,7 @@ def __init__(self, f, bitmap_class): self._descent = None @property - def descent(self): + def descent(self) -> Optional[int]: """The number of pixels below the baseline of a typical descender""" if self._descent is None: self.file.seek(0) @@ -66,7 +73,7 @@ def descent(self): return self._descent @property - def ascent(self): + def ascent(self) -> Optional[int]: """The number of pixels above the baseline of a typical ascender""" if self._ascent is None: self.file.seek(0) @@ -81,7 +88,7 @@ def ascent(self): return self._ascent - def _verify_bounding_box(self): + def _verify_bounding_box(self) -> None: """Private function to verify FOUNTBOUNDINGBOX parameter This function will parse the first 10 lines of the font source file to verify the value or raise an exception in case is not found @@ -105,15 +112,15 @@ def _verify_bounding_box(self): "Source file does not have the FOUNTBOUNDINGBOX parameter" ) from error - def _readline_file(self): + def _readline_file(self) -> str: line = self.file.readline() return str(line, "utf-8") - def get_bounding_box(self): + def get_bounding_box(self) -> Tuple[int, int, int, int]: """Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset""" return self._boundingbox - def load_glyphs(self, code_points): + def load_glyphs(self, code_points: Union[int, str, set]) -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals metadata = True character = False diff --git a/adafruit_bitmap_font/bitmap_font.py b/adafruit_bitmap_font/bitmap_font.py index e014311..231772c 100644 --- a/adafruit_bitmap_font/bitmap_font.py +++ b/adafruit_bitmap_font/bitmap_font.py @@ -22,30 +22,34 @@ """ +try: + from typing import Optional, Union +except ImportError: + pass + +from displayio import Bitmap +from . import bdf +from . import pcf +from . import ttf + __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font.git" -def load_font(filename, bitmap=None): +def load_font( + filename: str, bitmap: Optional[Bitmap] = None +) -> Union[bdf.BDF, pcf.PCF, ttf.TTF, None]: """Loads a font file. Returns None if unsupported.""" # pylint: disable=import-outside-toplevel, consider-using-with if not bitmap: - import displayio - - bitmap = displayio.Bitmap + bitmap = Bitmap font_file = open(filename, "rb") first_four = font_file.read(4) if filename.endswith("bdf") and first_four == b"STAR": - from . import bdf - return bdf.BDF(font_file, bitmap) if filename.endswith("pcf") and first_four == b"\x01fcp": - from . import pcf - return pcf.PCF(font_file, bitmap) if filename.endswith("ttf") and first_four == b"\x00\x01\x00\x00": - from . import ttf - return ttf.TTF(font_file, bitmap) raise ValueError("Unknown magic number %r" % first_four) diff --git a/adafruit_bitmap_font/glyph_cache.py b/adafruit_bitmap_font/glyph_cache.py index 9267ef3..17c618f 100644 --- a/adafruit_bitmap_font/glyph_cache.py +++ b/adafruit_bitmap_font/glyph_cache.py @@ -22,7 +22,13 @@ """ +try: + from typing import Union, Optional +except ImportError: + pass + import gc +from fontio import Glyph __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font.git" @@ -31,13 +37,13 @@ class GlyphCache: """Caches glyphs loaded by a subclass.""" - def __init__(self): + def __init__(self) -> None: self._glyphs = {} - def load_glyphs(self, code_points): + def load_glyphs(self, code_points: Union[int, str, set]) -> None: """Loads displayio.Glyph objects into the GlyphCache from the font.""" - def get_glyph(self, code_point): + def get_glyph(self, code_point: int) -> Optional[Glyph]: """Returns a displayio.Glyph for the given code point or None is unsupported.""" if code_point in self._glyphs: return self._glyphs[code_point] diff --git a/adafruit_bitmap_font/pcf.py b/adafruit_bitmap_font/pcf.py index 3964cc1..72fa89d 100644 --- a/adafruit_bitmap_font/pcf.py +++ b/adafruit_bitmap_font/pcf.py @@ -22,12 +22,18 @@ """ +try: + from typing import Union, Generator +except ImportError: + pass + from collections import namedtuple import gc import struct +from io import FileIO from micropython import const - from fontio import Glyph +from displayio import Bitmap as displayioBitmap from .glyph_cache import GlyphCache try: @@ -96,7 +102,7 @@ class PCF(GlyphCache): """Loads glyphs from a PCF file in the given bitmap_class.""" - def __init__(self, f, bitmap_class): + def __init__(self, f: FileIO, bitmap_class: displayioBitmap) -> None: super().__init__() self.file = f self.name = f @@ -133,27 +139,27 @@ def __init__(self, f, bitmap_class): ) @property - def ascent(self): + def ascent(self) -> int: """The number of pixels above the baseline of a typical ascender""" return self._ascent @property - def descent(self): + def descent(self) -> int: """The number of pixels below the baseline of a typical descender""" return self._descent - def get_bounding_box(self): + def get_bounding_box(self) -> tuple: """Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset""" return self._bounding_box - def _read(self, format_): + def _read(self, format_: str) -> tuple: size = struct.calcsize(format_) if size != len(self.buffer): self.buffer = bytearray(size) self.file.readinto(self.buffer) return struct.unpack_from(format_, self.buffer) - def _seek_table(self, table): + def _seek_table(self, table: dict) -> int: self.file.seek(table.offset) (format_,) = self._read(" Encoding: encoding = self.tables[_PCF_BDF_ENCODINGS] self._seek_table(encoding) return Encoding(*self._read(">hhhhh")) - def _read_bitmap_table(self): + def _read_bitmap_table(self) -> Bitmap: bitmaps = self.tables[_PCF_BITMAPS] format_ = self._seek_table(bitmaps) @@ -177,7 +183,7 @@ def _read_bitmap_table(self): bitmap_sizes = self._read(">4I") return Bitmap(glyph_count, bitmap_sizes[format_ & 3]) - def _read_metrics(self, compressed_metrics): + def _read_metrics(self, compressed_metrics: bool) -> Metrics: if compressed_metrics: ( left_side_bearing, @@ -210,7 +216,7 @@ def _read_metrics(self, compressed_metrics): attributes, ) - def _read_accelerator_tables(self): + def _read_accelerator_tables(self) -> Accelerators: # pylint: disable=too-many-locals accelerators = self.tables.get(_PCF_BDF_ACCELERATORS) if not accelerators: @@ -260,7 +266,7 @@ def _read_accelerator_tables(self): ink_maxbounds, ) - def _read_properties(self): + def _read_properties(self) -> Generator[tuple, None, None]: property_table_offset = self.tables[_PCF_PROPERTIES]["offset"] self.file.seek(property_table_offset) (format_,) = self._read(" None: # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals if isinstance(code_points, int): code_points = (code_points,) diff --git a/adafruit_bitmap_font/ttf.py b/adafruit_bitmap_font/ttf.py index 54c81fa..987cc17 100644 --- a/adafruit_bitmap_font/ttf.py +++ b/adafruit_bitmap_font/ttf.py @@ -6,19 +6,20 @@ # Remove the above when TTF is actually supported. import struct - +from io import FileIO +from displayio import Bitmap # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html class TTF: - def __init__(self, f, bitmap): + def __init__(self, f: FileIO, bitmap: Bitmap) -> None: f.seek(0) self.file = f self.characters = {} - def read(format): + def read(format: str) -> tuple: s = struct.calcsize(format) return struct.unpack_from(format, f.read(s)) From 7c47d9e405aa18ba03ca783bb06cf486154b22f6 Mon Sep 17 00:00:00 2001 From: Isaac Benitez Date: Mon, 6 Jun 2022 23:35:32 -0700 Subject: [PATCH 2/4] Added displayio to autodoc_mock_imports --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index c247e7b..99f7110 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -autodoc_mock_imports = ["fontio"] +autodoc_mock_imports = ["displayio", "fontio"] intersphinx_mapping = { From d3fbbca82eba22a0ab6767f78572a76f5e648026 Mon Sep 17 00:00:00 2001 From: Isaac Benitez Date: Wed, 8 Jun 2022 23:29:39 -0700 Subject: [PATCH 3/4] Updated type annotations --- adafruit_bitmap_font/bdf.py | 8 ++++---- adafruit_bitmap_font/bitmap_font.py | 23 +++++++++++++++-------- adafruit_bitmap_font/glyph_cache.py | 8 ++++---- adafruit_bitmap_font/pcf.py | 16 ++++++++-------- adafruit_bitmap_font/ttf.py | 11 ++++++++--- docs/conf.py | 2 +- requirements.txt | 1 + setup.py | 5 ++++- 8 files changed, 45 insertions(+), 29 deletions(-) diff --git a/adafruit_bitmap_font/bdf.py b/adafruit_bitmap_font/bdf.py index 9b791ce..36a2c0b 100644 --- a/adafruit_bitmap_font/bdf.py +++ b/adafruit_bitmap_font/bdf.py @@ -23,14 +23,14 @@ """ try: - from typing import Union, Optional, Tuple + from typing import Union, Optional, Tuple, Iterable + from io import FileIO + from displayio import Bitmap except ImportError: pass import gc -from io import FileIO from fontio import Glyph -from displayio import Bitmap from .glyph_cache import GlyphCache __version__ = "0.0.0-auto.0" @@ -120,7 +120,7 @@ def get_bounding_box(self) -> Tuple[int, int, int, int]: """Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset""" return self._boundingbox - def load_glyphs(self, code_points: Union[int, str, set]) -> None: + def load_glyphs(self, code_points: Union[int, str, Iterable]) -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals metadata = True character = False diff --git a/adafruit_bitmap_font/bitmap_font.py b/adafruit_bitmap_font/bitmap_font.py index 231772c..18ebca8 100644 --- a/adafruit_bitmap_font/bitmap_font.py +++ b/adafruit_bitmap_font/bitmap_font.py @@ -24,32 +24,39 @@ try: from typing import Optional, Union + from displayio import Bitmap + from . import bdf + from . import pcf + from . import ttf except ImportError: pass -from displayio import Bitmap -from . import bdf -from . import pcf -from . import ttf - __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font.git" def load_font( filename: str, bitmap: Optional[Bitmap] = None -) -> Union[bdf.BDF, pcf.PCF, ttf.TTF, None]: +) -> Union[bdf.BDF, pcf.PCF, ttf.TTF]: """Loads a font file. Returns None if unsupported.""" - # pylint: disable=import-outside-toplevel, consider-using-with + # pylint: disable=import-outside-toplevel, redefined-outer-name, consider-using-with if not bitmap: - bitmap = Bitmap + import displayio + + bitmap = displayio.Bitmap font_file = open(filename, "rb") first_four = font_file.read(4) if filename.endswith("bdf") and first_four == b"STAR": + from . import bdf + return bdf.BDF(font_file, bitmap) if filename.endswith("pcf") and first_four == b"\x01fcp": + from . import pcf + return pcf.PCF(font_file, bitmap) if filename.endswith("ttf") and first_four == b"\x00\x01\x00\x00": + from . import ttf + return ttf.TTF(font_file, bitmap) raise ValueError("Unknown magic number %r" % first_four) diff --git a/adafruit_bitmap_font/glyph_cache.py b/adafruit_bitmap_font/glyph_cache.py index 17c618f..7df2a88 100644 --- a/adafruit_bitmap_font/glyph_cache.py +++ b/adafruit_bitmap_font/glyph_cache.py @@ -23,12 +23,12 @@ """ try: - from typing import Union, Optional + from typing import Union, Iterable + from fontio import Glyph except ImportError: pass import gc -from fontio import Glyph __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font.git" @@ -40,10 +40,10 @@ class GlyphCache: def __init__(self) -> None: self._glyphs = {} - def load_glyphs(self, code_points: Union[int, str, set]) -> None: + def load_glyphs(self, code_points: Union[int, str, Iterable]) -> None: """Loads displayio.Glyph objects into the GlyphCache from the font.""" - def get_glyph(self, code_point: int) -> Optional[Glyph]: + def get_glyph(self, code_point: int) -> Glyph: """Returns a displayio.Glyph for the given code point or None is unsupported.""" if code_point in self._glyphs: return self._glyphs[code_point] diff --git a/adafruit_bitmap_font/pcf.py b/adafruit_bitmap_font/pcf.py index 72fa89d..991f962 100644 --- a/adafruit_bitmap_font/pcf.py +++ b/adafruit_bitmap_font/pcf.py @@ -23,17 +23,17 @@ """ try: - from typing import Union, Generator + from typing import Union, Tuple, Iterator, Iterable + from io import FileIO + from displayio import Bitmap as displayioBitmap except ImportError: pass from collections import namedtuple import gc import struct -from io import FileIO from micropython import const from fontio import Glyph -from displayio import Bitmap as displayioBitmap from .glyph_cache import GlyphCache try: @@ -148,18 +148,18 @@ def descent(self) -> int: """The number of pixels below the baseline of a typical descender""" return self._descent - def get_bounding_box(self) -> tuple: + def get_bounding_box(self) -> Tuple[int, int, int, int]: """Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset""" return self._bounding_box - def _read(self, format_: str) -> tuple: + def _read(self, format_: str) -> Tuple: size = struct.calcsize(format_) if size != len(self.buffer): self.buffer = bytearray(size) self.file.readinto(self.buffer) return struct.unpack_from(format_, self.buffer) - def _seek_table(self, table: dict) -> int: + def _seek_table(self, table: Table) -> int: self.file.seek(table.offset) (format_,) = self._read(" Accelerators: ink_maxbounds, ) - def _read_properties(self) -> Generator[tuple, None, None]: + def _read_properties(self) -> Iterator[Tuple[bytes, Union[bytes, int]]]: property_table_offset = self.tables[_PCF_PROPERTIES]["offset"] self.file.seek(property_table_offset) (format_,) = self._read(" Generator[tuple, None, None]: else: yield (string_map[name_offset], value) - def load_glyphs(self, code_points: Union[int, str, set]) -> None: + def load_glyphs(self, code_points: Union[int, str, Iterable]) -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals if isinstance(code_points, int): code_points = (code_points,) diff --git a/adafruit_bitmap_font/ttf.py b/adafruit_bitmap_font/ttf.py index 987cc17..807ac79 100644 --- a/adafruit_bitmap_font/ttf.py +++ b/adafruit_bitmap_font/ttf.py @@ -5,9 +5,14 @@ # pylint: skip-file # Remove the above when TTF is actually supported. +try: + from typing import Tuple + from io import FileIO + from displayio import Bitmap +except ImportError: + pass + import struct -from io import FileIO -from displayio import Bitmap # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html @@ -19,7 +24,7 @@ def __init__(self, f: FileIO, bitmap: Bitmap) -> None: self.characters = {} - def read(format: str) -> tuple: + def read(format: str) -> Tuple: s = struct.calcsize(format) return struct.unpack_from(format, f.read(s)) diff --git a/docs/conf.py b/docs/conf.py index 99f7110..c247e7b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -autodoc_mock_imports = ["displayio", "fontio"] +autodoc_mock_imports = ["fontio"] intersphinx_mapping = { diff --git a/requirements.txt b/requirements.txt index 17a850d..6f7d177 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ # SPDX-License-Identifier: Unlicense Adafruit-Blinka +Adafruit-Blinka-displayio diff --git a/setup.py b/setup.py index aab56c8..8d719c5 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,10 @@ # Author details author="Adafruit Industries", author_email="circuitpython@adafruit.com", - install_requires=["Adafruit-Blinka"], + install_requires=[ + "Adafruit-Blinka", + "Adafruit-Blinka-displayio", + ], # Choose your license license="MIT", # See https://pypi.python.org/pypi?%3Aaction=list_classifiers From 781b2d3780e25eb174b6b9fec8c034d0c542d6e3 Mon Sep 17 00:00:00 2001 From: Isaac Benitez Date: Thu, 9 Jun 2022 08:12:34 -0700 Subject: [PATCH 4/4] Corrected Iterable type annotations --- adafruit_bitmap_font/bdf.py | 2 +- adafruit_bitmap_font/glyph_cache.py | 2 +- adafruit_bitmap_font/pcf.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_bitmap_font/bdf.py b/adafruit_bitmap_font/bdf.py index 36a2c0b..52f2ac6 100644 --- a/adafruit_bitmap_font/bdf.py +++ b/adafruit_bitmap_font/bdf.py @@ -120,7 +120,7 @@ def get_bounding_box(self) -> Tuple[int, int, int, int]: """Return the maximum glyph size as a 4-tuple of: width, height, x_offset, y_offset""" return self._boundingbox - def load_glyphs(self, code_points: Union[int, str, Iterable]) -> None: + def load_glyphs(self, code_points: Union[int, str, Iterable[int]]) -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals metadata = True character = False diff --git a/adafruit_bitmap_font/glyph_cache.py b/adafruit_bitmap_font/glyph_cache.py index 7df2a88..072d379 100644 --- a/adafruit_bitmap_font/glyph_cache.py +++ b/adafruit_bitmap_font/glyph_cache.py @@ -40,7 +40,7 @@ class GlyphCache: def __init__(self) -> None: self._glyphs = {} - def load_glyphs(self, code_points: Union[int, str, Iterable]) -> None: + def load_glyphs(self, code_points: Union[int, str, Iterable[int]]) -> None: """Loads displayio.Glyph objects into the GlyphCache from the font.""" def get_glyph(self, code_point: int) -> Glyph: diff --git a/adafruit_bitmap_font/pcf.py b/adafruit_bitmap_font/pcf.py index 991f962..860ca09 100644 --- a/adafruit_bitmap_font/pcf.py +++ b/adafruit_bitmap_font/pcf.py @@ -297,7 +297,7 @@ def _read_properties(self) -> Iterator[Tuple[bytes, Union[bytes, int]]]: else: yield (string_map[name_offset], value) - def load_glyphs(self, code_points: Union[int, str, Iterable]) -> None: + def load_glyphs(self, code_points: Union[int, str, Iterable[int]]) -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals if isinstance(code_points, int): code_points = (code_points,)