chg: [typing] Make Mypy Happy Again.

This commit is contained in:
Cédric Bonhomme 2025-06-22 12:03:30 +02:00
parent 21004219fa
commit 18fd8a8a49
No known key found for this signature in database
GPG key ID: A1CB94DE57B7A70D
5 changed files with 43 additions and 21 deletions

View file

@ -21,7 +21,7 @@ repos:
additional_dependencies:
- flake8-bugbear
- flake8-implicit-str-concat
args: ["--max-line-length=125"]
args: ["--max-line-length=125", "--ignore=E203"]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:

View file

@ -73,7 +73,7 @@ optional = true
[tool.mypy]
python_version = "3.12"
python_version = "3.13"
check_untyped_defs = true
ignore_errors = false
ignore_missing_imports = true
@ -87,7 +87,12 @@ warn_unreachable = true
show_error_context = true
pretty = true
exclude = "build|dist|docs|stegano.egg-info"
exclude = "build|dist|docs"
[tool.isort]
profile = "black"
[tool.flake8]
ignore = ["E203"]

View file

@ -23,7 +23,7 @@ __date__ = "$Date: 2010/10/01 $"
__revision__ = "$Date: 2017/02/06 $"
__license__ = "GPLv3"
from typing import IO, Union
from typing import IO, Union, cast
from stegano import tools
@ -40,13 +40,17 @@ def hide(input_image: Union[str, IO[bytes]], message: str):
assert message_length != 0, "message message_length is zero"
assert message_length < 255, "message is too long"
img = tools.open_image(input_image)
# Ensure image mode is RGB
if img.mode != "RGB":
img = img.convert("RGB")
# Use a copy of image to hide the text in
encoded = img.copy()
width, height = img.size
index = 0
for row in range(height):
for col in range(width):
(r, g, b) = img.getpixel((col, row))
pixel = cast(tuple[int, int, int], img.getpixel((col, row)))
r, g, b = pixel
# first value is message_length of message
if row == 0 and col == 0 and index < message_length:
asc = message_length
@ -70,12 +74,16 @@ def reveal(input_image: Union[str, IO[bytes]]):
The red value of the first pixel is used for message_length of string.
"""
img = tools.open_image(input_image)
# Ensure image mode is RGB
if img.mode != "RGB":
img = img.convert("RGB")
width, height = img.size
message = ""
index = 0
for row in range(height):
for col in range(width):
r, g, b = img.getpixel((col, row))
pixel = cast(tuple[int, int, int], img.getpixel((col, row)))
r, g, b = pixel
# First pixel r value is length of message
if row == 0 and col == 0:
message_length = r

View file

@ -23,6 +23,8 @@ __date__ = "$Date: 2010/10/01 $"
__revision__ = "$Date: 2019/06/06 $"
__license__ = "GPLv3"
from typing import cast
from PIL import Image
@ -34,7 +36,7 @@ def steganalyse(img: Image.Image) -> Image.Image:
width, height = img.size
for row in range(height):
for col in range(width):
if pixel := img.getpixel((col, row)):
if pixel := cast(tuple[int, int, int], img.getpixel((col, row))):
r, g, b = pixel[0:3]
else:
raise Exception("Error during steganlysis.")

View file

@ -26,7 +26,7 @@ __license__ = "GPLv3"
import base64
import itertools
from functools import reduce
from typing import IO, List, Union
from typing import IO, List, Union, cast
from PIL import Image
@ -101,11 +101,12 @@ def base642binary(b64_fname: str) -> bytes:
return base64.b64decode(b64_fname)
def open_image(fname_or_instance: Union[str, IO[bytes]]):
"""Opens a Image and returns it.
def open_image(fname_or_instance: Union[str, IO[bytes], Image.Image]) -> Image.Image:
"""Opens an image and returns it.
:param fname_or_instance: Can either be the location of the image as a
string or the Image.Image instance itself.
:param fname_or_instance: Can be a path to the image (str),
a file-like object (IO[bytes]),
or a PIL Image instance.
"""
if isinstance(fname_or_instance, Image.Image):
return fname_or_instance
@ -157,8 +158,15 @@ class Hider:
return True if self._index + 3 <= self._len_message_bits else False
def encode_pixel(self, coordinate: tuple):
# Get the colour component.
r, g, b, *a = self.encoded_image.getpixel(coordinate)
# Determine expected pixel format based on mode
if self.encoded_image.mode == "RGBA":
r, g, b, *a = cast(
tuple[int, int, int, int], self.encoded_image.getpixel(coordinate)
)
else:
r, g, b, *a = cast(
tuple[int, int, int], self.encoded_image.getpixel(coordinate)
)
# Change the Least Significant Bit of each colour component.
r = setlsb(r, self._message_bits[self._index])
@ -190,8 +198,11 @@ class Revealer:
self.close_file = close_file
def decode_pixel(self, coordinate: tuple):
# pixel = [r, g, b] or [r,g,b,a]
pixel = self.encoded_image.getpixel(coordinate)
# Tell mypy that this will be a 3- or 4-tuple of ints
pixel = cast(
tuple[int, int, int] | tuple[int, int, int, int],
self.encoded_image.getpixel(coordinate),
)
if self.encoded_image.mode == "RGBA":
pixel = pixel[:3] # ignore the alpha
@ -211,13 +222,9 @@ class Revealer:
raise IndexError("Impossible to detect message.")
if len(self._bitab) - len(str(self._limit)) - 1 == self._limit:
self.secret_message = "".join(self._bitab)[
len(str(self._limit)) + 1 : # noqa: E203
]
self.secret_message = "".join(self._bitab)[len(str(self._limit)) + 1 :]
if self.close_file:
self.encoded_image.close()
return True
else:
return False