Skip to content

Add types for #56 Missing type annotations #60

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

Merged
merged 2 commits into from
May 9, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@ _build
.idea
.vscode
*~

# virtualenv
Pipfile
Pipfile.lock
Makefile
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ repos:
types: [python]
args:
- --disable=consider-using-f-string
- --min-similarity-lines=14
exclude: "^(docs/|examples/|tests/|setup.py$)"
- id: pylint
name: pylint (example code)
Expand Down
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: 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: 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: 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: 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: 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: 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