Skip to content

Commit

Permalink
Merge pull request #60 from matt-land/add-typing
Browse files Browse the repository at this point in the history
Add types for #56 Missing type annotations
  • Loading branch information
FoamyGuy authored May 9, 2022
2 parents 7c18538 + aaf9590 commit 154bcae
Show file tree
Hide file tree
Showing 18 changed files with 375 additions and 102 deletions.
3 changes: 1 addition & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,7 @@ ignore-docstrings=yes
ignore-imports=yes

# Minimum lines number of a similarity.
min-similarity-lines=4

min-similarity-lines=14

[BASIC]

Expand Down
27 changes: 24 additions & 3 deletions adafruit_imageload/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: 2018 Scott Shawcroft for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Matt Land
#
# SPDX-License-Identifier: MIT

Expand All @@ -8,22 +9,42 @@
Load pixel values (indices or colors) into a bitmap and colors into a palette.
* Author(s): Scott Shawcroft
* Author(s): Scott Shawcroft, Matt Land
"""
# pylint: disable=import-outside-toplevel

try:
from typing import (
Tuple,
Iterator,
Optional,
List,
Iterable,
Union,
)
from io import BufferedReader
from displayio import Palette, Bitmap
from .displayio_types import PaletteConstructor, BitmapConstructor
except ImportError:
pass

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"


def load(file_or_filename, *, bitmap=None, palette=None):
def load(
file_or_filename: Union[str, BufferedReader],
*,
bitmap: Optional[BitmapConstructor] = None,
palette: Optional[PaletteConstructor] = None
) -> Tuple[Bitmap, Optional[Palette]]:
"""Load pixel values (indices or colors) into a bitmap and colors into a palette.
bitmap is the desired type. It must take width, height and color_depth in the constructor. It
must also have a _load_row method to load a row's worth of pixel data.
palette is the desired pallete type. The constructor should take the number of colors and
palette is the desired palette type. The constructor should take the number of colors and
support assignment to indices via [].
"""
if not bitmap or not palette:
Expand Down
18 changes: 16 additions & 2 deletions adafruit_imageload/bmp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: 2018 Scott Shawcroft for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Matt Land
#
# SPDX-License-Identifier: MIT

Expand All @@ -8,16 +9,29 @@
Load pixel values (indices or colors) into a bitmap and colors into a palette from a BMP file.
* Author(s): Scott Shawcroft
* Author(s): Scott Shawcroft, Matt Land
"""
# pylint: disable=import-outside-toplevel

try:
from typing import Tuple, Optional, Set, List
from io import BufferedReader
from displayio import Palette, Bitmap
from ..displayio_types import PaletteConstructor, BitmapConstructor
except ImportError:
pass

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"


def load(file, *, bitmap=None, palette=None):
def load(
file: BufferedReader,
*,
bitmap: BitmapConstructor = None,
palette: PaletteConstructor = None
) -> Tuple[Bitmap, Optional[Palette]]:
"""Loads a bmp image from the open ``file``.
Returns tuple of bitmap object and palette object.
Expand Down
51 changes: 34 additions & 17 deletions adafruit_imageload/bmp/indexed.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: 2018 Scott Shawcroft for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Matt Land
#
# SPDX-License-Identifier: MIT

Expand All @@ -8,33 +9,43 @@
Load pixel values (indices or colors) into a bitmap and colors into a palette from an indexed BMP.
* Author(s): Scott Shawcroft
* Author(s): Scott Shawcroft, Matt Land
"""

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"

import sys

try:
from typing import Tuple, Optional
from io import BufferedReader
from displayio import Palette, Bitmap
from ..displayio_types import PaletteConstructor, BitmapConstructor
except ImportError:
pass

try:
from bitmaptools import readinto as _bitmap_readinto
except ImportError:
_bitmap_readinto = None # pylint: disable=invalid-name
_bitmap_readinto = None # pylint: disable=invalid-name # type: Callable


__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"


def load(
file,
width,
height,
data_start,
colors,
color_depth,
compression,
file: BufferedReader,
width: int,
height: int,
data_start: int,
colors: int,
color_depth: int,
compression: int,
*,
bitmap=None,
palette=None
):
bitmap: BitmapConstructor = None,
palette: PaletteConstructor = None,
) -> Tuple[Bitmap, Optional[Palette]]:
"""Loads indexed bitmap data into bitmap and palette objects.
:param file file: The open bmp file
Expand All @@ -46,7 +57,7 @@ def load(
:param int compression: 0 - none, 1 - 8bit RLE, 2 - 4bit RLE"""
# pylint: disable=too-many-arguments,too-many-locals,too-many-branches
if palette:
palette = palette(colors)
palette = palette(colors) # type: Palette

file.seek(data_start - colors * 4)
for value in range(colors):
Expand All @@ -67,7 +78,7 @@ def load(

# convert unsigned int to signed int when height is negative
height = negative_height_check(height)
bitmap = bitmap(width, abs(height), colors)
bitmap = bitmap(width, abs(height), colors) # type: Bitmap
file.seek(data_start)
line_size = width // (8 // color_depth)
if width % (8 // color_depth) != 0:
Expand Down Expand Up @@ -122,7 +133,13 @@ def load(
return bitmap, palette


def decode_rle(bitmap, file, compression, y_range, width):
def decode_rle(
bitmap: Bitmap,
file: BufferedReader,
compression: int,
y_range: Tuple[int, int, int],
width: int,
) -> None:
"""Helper to decode RLE images"""
# pylint: disable=too-many-locals,too-many-nested-blocks,too-many-branches

Expand Down
5 changes: 4 additions & 1 deletion adafruit_imageload/bmp/negative_height_check.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# SPDX-FileCopyrightText: 2018 Scott Shawcroft for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Matt Land
#
# SPDX-License-Identifier: MIT

"""
Check for negative height on the BMP.
Seperated into it's own file to support builds
without longint.
* Author(s): Tim Cocks, Matt Land
"""


def negative_height_check(height):
def negative_height_check(height: int) -> int:
"""Check the height return modified if negative."""
if height > 0x7FFFFFFF:
return height - 4294967296
Expand Down
26 changes: 26 additions & 0 deletions adafruit_imageload/displayio_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# SPDX-FileCopyrightText: 2022 Matt Land
#
# SPDX-License-Identifier: MIT
"""
`adafruit_imageload.displayio_types`
====================================================
This is a utility file for type aliases.
https://mypy.readthedocs.io/en/stable/kinds_of_types.html#type-aliases
Type aliases contain compound declarations (used many places in the project) with a single
definition readable by humans.
* Author(s): Matt Land
"""
try:
from typing import Callable
from displayio import Palette, Bitmap

PaletteConstructor = Callable[[int], Palette]
BitmapConstructor = Callable[[int, int, int], Bitmap]
except ImportError:
pass

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"
44 changes: 31 additions & 13 deletions adafruit_imageload/gif.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: 2019 Radomir Dopieralski for Adafruit Industries
# SPDX-FileCopyrightText: 2022 Matt Land
#
# SPDX-License-Identifier: MIT

Expand All @@ -9,30 +10,45 @@
Load pixel values (indices or colors) into a bitmap and colors into a palette
from a GIF file.
* Author(s): Radomir Dopieralski
* Author(s): Radomir Dopieralski, Matt Land
"""

import struct

try:
from typing import Tuple, Iterator, Optional, List
from io import BufferedReader
from displayio import Palette, Bitmap
from .displayio_types import PaletteConstructor, BitmapConstructor
except ImportError:
pass

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"


def load(file, *, bitmap=None, palette=None):
def load(
file: BufferedReader,
*,
bitmap: BitmapConstructor,
palette: PaletteConstructor = None
) -> Tuple[Bitmap, Optional[Palette]]:
"""Loads a GIF image from the open ``file``.
Returns tuple of bitmap object and palette object.
:param BufferedReader file: The *.gif file being loaded
:param object bitmap: Type to store bitmap data. Must have API similar to `displayio.Bitmap`.
Will be skipped if None
:param object palette: Type to store the palette. Must have API similar to
`displayio.Palette`. Will be skipped if None"""
header = file.read(6)
if header not in {b"GIF87a", b"GIF89a"}:
raise ValueError("Not a GIF file")
width, height, flags, _, _ = struct.unpack("<HHBBB", file.read(7))
width, height, flags, _, _ = struct.unpack( # pylint: disable=no-member
"<HHBBB", file.read(7)
)
if (flags & 0x80) != 0:
palette_size = 1 << ((flags & 0x07) + 1)
palette_obj = palette(palette_size)
Expand All @@ -57,9 +73,11 @@ def load(file, *, bitmap=None, palette=None):
return bitmap_obj, palette_obj


def _read_frame(file, bitmap):
"""Read a signle frame and apply it to the bitmap."""
ddx, ddy, width, _, flags = struct.unpack("<HHHHB", file.read(9))
def _read_frame(file: BufferedReader, bitmap: Bitmap) -> None:
"""Read a single frame and apply it to the bitmap."""
ddx, ddy, width, _, flags = struct.unpack( # pylint: disable=no-member
"<HHHHB", file.read(9)
)
if (flags & 0x40) != 0:
raise NotImplementedError("Interlacing not supported")
if (flags & 0x80) != 0:
Expand All @@ -78,7 +96,7 @@ def _read_frame(file, bitmap):
y += 1


def _read_blockstream(file):
def _read_blockstream(file: BufferedReader) -> Iterator[int]:
"""Read a block from a file."""
while True:
size = file.read(1)[0]
Expand All @@ -95,21 +113,21 @@ class EndOfData(Exception):
class LZWDict:
"""A dictionary of LZW codes."""

def __init__(self, code_size):
def __init__(self, code_size: int) -> None:
self.code_size = code_size
self.clear_code = 1 << code_size
self.end_code = self.clear_code + 1
self.codes = []
self.last = None
self.codes = [] # type: List[bytes]
self.last = b""
self.clear()

def clear(self):
def clear(self) -> None:
"""Reset the dictionary to default codes."""
self.last = b""
self.code_len = self.code_size + 1
self.codes[:] = []

def decode(self, code):
def decode(self, code: int) -> bytes:
"""Decode a code."""
if code == self.clear_code:
self.clear()
Expand All @@ -133,7 +151,7 @@ def decode(self, code):
return value


def lzw_decode(data, code_size):
def lzw_decode(data: Iterator[int], code_size: int) -> Iterator[bytes]:
"""Decode LZW-compressed data."""
dictionary = LZWDict(code_size)
bit = 0
Expand Down
Loading

0 comments on commit 154bcae

Please sign in to comment.