Skip to content

Commit

Permalink
Fix support for python 3.8
Browse files Browse the repository at this point in the history
  • Loading branch information
laggykiller committed Mar 9, 2024
1 parent 406b581 commit c4a982d
Show file tree
Hide file tree
Showing 41 changed files with 234 additions and 315 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/check_and_fix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
id: extract_branch
- uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: '3.8'
- name: Install dependency
run: pip install ruff mypy isort pytest
- name: Update emoji.json
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "sticker-convert"
description = "Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, iMessage. Written in Python."
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.8"
license = {file = "LICENSE"}
keywords = ["telegram", "line", "tgs", "whatsapp", "kakao", "signal", "imessage", "wastickers"]
authors = [
Expand All @@ -17,6 +17,7 @@ classifiers = [
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ beautifulsoup4~=4.12.3
rookiepy~=0.3.6
imagequant~=1.1.1
memory-tempfile~=2.2.3
numpy~=1.26.4
numpy~=1.22.4
Pillow~=10.2.0
pyoxipng~=9.0.0
python-telegram-bot~=20.5
Expand Down
14 changes: 7 additions & 7 deletions scripts/opt-comp-experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from pathlib import Path
from tempfile import TemporaryDirectory
from threading import Thread
from typing import Any, Optional
from typing import Any, List, Optional, Tuple

import numpy
from apngasm_python._apngasm_python import APNGAsm, create_frame_from_rgba # type: ignore
Expand Down Expand Up @@ -80,15 +80,15 @@ def generate_random_png(res: int, out_f: Path) -> None:


def compress_worker(
work_queue: Queue[Optional[tuple[Path, Path, CompOption]]],
work_queue: Queue[Optional[Tuple[Path, Path, CompOption]]],
results_queue: Queue[
tuple[
Tuple[
bool,
int,
Optional[int],
Optional[int],
tuple[Optional[int], Optional[int]],
tuple[Optional[int], Optional[int]],
Tuple[Optional[int], Optional[int]],
Tuple[Optional[int], Optional[int]],
]
],
):
Expand Down Expand Up @@ -190,14 +190,14 @@ def main() -> None:
for i in itertools.product(fps_list, res_list, quality_list, color_list)
]

work_queue: Queue[Optional[tuple[Path, Path, CompOption]]] = Queue()
work_queue: Queue[Optional[Tuple[Path, Path, CompOption]]] = Queue()
results_queue: Queue[Any] = Queue()

Thread(
target=write_result, args=(csv_path, results_queue, len(combinations))
).start()

processes: list[Process] = []
processes: List[Process] = []
for _ in range(processes_max):
process = Process(
target=compress_worker, args=(work_queue, results_queue)
Expand Down
1 change: 1 addition & 0 deletions src/sticker-convert.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python3

from sticker_convert.__main__ import main

if __name__ == "__main__":
Expand Down
1 change: 1 addition & 0 deletions src/sticker_convert/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
"""sticker-convert"""


from sticker_convert.version import __version__ # noqa
2 changes: 2 additions & 0 deletions src/sticker_convert/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env python3


def main() -> None:
import multiprocessing
import sys
Expand Down
6 changes: 3 additions & 3 deletions src/sticker_convert/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from math import ceil
from multiprocessing import cpu_count
from pathlib import Path
from typing import Any
from typing import Any, Dict

from sticker_convert.definitions import CONFIG_DIR, DEFAULT_DIR, ROOT_DIR
from sticker_convert.job import Job
Expand All @@ -26,7 +26,7 @@ def __init__(self) -> None:

def cli(self) -> None:
try:
self.help: dict[str, dict[str, str]] = JsonManager.load_json(
self.help: Dict[str, Dict[str, str]] = JsonManager.load_json(
ROOT_DIR / "resources/help.json"
)
self.input_presets = JsonManager.load_json(
Expand Down Expand Up @@ -125,7 +125,7 @@ def cli(self) -> None:
"quantize_method",
)
flags_comp_bool = ("fake_vid",)
keyword_args: dict[str, Any]
keyword_args: Dict[str, Any]
for k, v in self.help["comp"].items():
if k in flags_comp_int:
keyword_args = {"type": int, "default": None}
Expand Down
100 changes: 43 additions & 57 deletions src/sticker_convert/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from math import ceil, floor
from pathlib import Path
from queue import Queue
from typing import TYPE_CHECKING, Any, Literal, Optional, Union, cast
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Tuple, Union, cast

import numpy as np
from PIL import Image
Expand All @@ -21,6 +21,12 @@
from sticker_convert.utils.media.format_verify import FormatVerify


CbQueueItemType = Union[
Tuple[str, Optional[Tuple[str]], Optional[Dict[str, str]]],
str,
None,
]

def rounding(value: float) -> Decimal:
return Decimal(value).quantize(0, ROUND_HALF_UP)

Expand Down Expand Up @@ -55,10 +61,10 @@ def get_step_value(

def useful_array(
plane: "VideoPlane", bytes_per_pixel: int = 1, dtype: str = "uint8"
) -> np.ndarray[Any, Any]:
) -> "np.ndarray[Any, Any]":
total_line_size = abs(plane.line_size)
useful_line_size = plane.width * bytes_per_pixel
arr: np.ndarray[Any, Any] = np.frombuffer(cast(bytes, plane), np.uint8)
arr: "np.ndarray[Any, Any]" = np.frombuffer(cast(bytes, plane), np.uint8)
if total_line_size != useful_line_size:
arr = arr.reshape(-1, total_line_size)[:, 0:useful_line_size].reshape(-1)
return arr.view(np.dtype(dtype))
Expand All @@ -80,19 +86,10 @@ class StickerConvert:

def __init__(
self,
in_f: Union[Path, tuple[Path, bytes]],
in_f: Union[Path, Tuple[Path, bytes]],
out_f: Path,
opt_comp: CompOption,
cb: Union[
Queue[
Union[
tuple[str, Optional[tuple[str]], Optional[dict[str, str]]],
str,
None,
]
],
Callback,
],
cb: "Union[Queue[CbQueueItemType], Callback]",
# cb_return: CallbackReturn
):
self.in_f: Union[bytes, Path]
Expand All @@ -107,7 +104,7 @@ def __init__(
self.in_f_path = in_f[0]
self.codec_info_orig = CodecInfo(in_f[1], Path(in_f[0]).suffix)

valid_formats: list[str] = []
valid_formats: List[str] = []
for i in opt_comp.get_format():
valid_formats.extend(i)

Expand All @@ -127,8 +124,8 @@ def __init__(
self.out_f_name: str = self.out_f.name

self.cb = cb
self.frames_raw: list[np.ndarray[Any, Any]] = []
self.frames_processed: list[np.ndarray[Any, Any]] = []
self.frames_raw: "List[np.ndarray[Any, Any]]" = []
self.frames_processed: "List[np.ndarray[Any, Any]]" = []
self.opt_comp: CompOption = opt_comp
if not self.opt_comp.steps:
self.opt_comp.steps = 1
Expand All @@ -150,27 +147,18 @@ def __init__(

@staticmethod
def convert(
in_f: Union[Path, tuple[Path, bytes]],
in_f: Union[Path, Tuple[Path, bytes]],
out_f: Path,
opt_comp: CompOption,
cb: Union[
Queue[
Union[
tuple[str, Optional[tuple[str]], Optional[dict[str, str]]],
str,
None,
]
],
Callback,
],
cb: "Union[Queue[CbQueueItemType], Callback]",
cb_return: CallbackReturn,
) -> tuple[bool, Path, Union[None, bytes, Path], int]:
) -> Tuple[bool, Path, Union[None, bytes, Path], int]:
sticker = StickerConvert(in_f, out_f, opt_comp, cb)
result = sticker._convert()
cb.put("update_bar")
return result

def _convert(self) -> tuple[bool, Path, Union[None, bytes, Path], int]:
def _convert(self) -> Tuple[bool, Path, Union[None, bytes, Path], int]:
result = self.check_if_compatible()
if result:
return self.compress_done(result)
Expand Down Expand Up @@ -287,8 +275,8 @@ def check_if_compatible(self) -> Optional[bytes]:
else:
return None

def generate_steps_list(self) -> list[tuple[Optional[int], ...]]:
steps_list: list[tuple[Optional[int], ...]] = []
def generate_steps_list(self) -> List[Tuple[Optional[int], ...]]:
steps_list: List[Tuple[Optional[int], ...]] = []
for step in range(self.opt_comp.steps, -1, -1):
steps_list.append(
(
Expand Down Expand Up @@ -342,7 +330,7 @@ def recompress(self, sign: str) -> None:

def compress_fail(
self,
) -> tuple[bool, Path, Union[None, bytes, Path], int]:
) -> Tuple[bool, Path, Union[None, bytes, Path], int]:
msg = self.MSG_FAIL_COMP.format(
self.in_f_name, self.out_f_name, self.size_max, self.size
)
Expand All @@ -352,7 +340,7 @@ def compress_fail(

def compress_done(
self, data: bytes, result_step: Optional[int] = None
) -> tuple[bool, Path, Union[None, bytes, Path], int]:
) -> Tuple[bool, Path, Union[None, bytes, Path], int]:
out_f: Union[None, bytes, Path]

if self.out_f.stem == "none":
Expand Down Expand Up @@ -431,7 +419,7 @@ def _frames_import_pyav(self) -> None:
height = frame.height
if frame.format.name == "yuv420p":
rgb_array = frame.to_ndarray(format="rgb24") # type: ignore
cast(np.ndarray[Any, Any], rgb_array)
cast("np.ndarray[Any, Any]", rgb_array)
rgba_array = np.dstack(
(
rgb_array,
Expand Down Expand Up @@ -472,11 +460,11 @@ def _frames_import_pyav(self) -> None:

yuv_array = yuv_array.astype(np.float32)
yuv_array[:, :, 0] = (
yuv_array[:, :, 0].clip(16, 235).astype(yuv_array.dtype)
yuv_array[:, :, 0].clip(16, 235).astype(yuv_array.dtype) # type: ignore
- 16
)
yuv_array[:, :, 1:] = (
yuv_array[:, :, 1:].clip(16, 240).astype(yuv_array.dtype)
yuv_array[:, :, 1:].clip(16, 240).astype(yuv_array.dtype) # type: ignore
- 128
)

Expand Down Expand Up @@ -524,9 +512,9 @@ def _frames_import_lottie(self) -> None:
anim.lottie_animation_destroy()

def frames_resize(
self, frames_in: list[np.ndarray[Any, Any]]
) -> list[np.ndarray[Any, Any]]:
frames_out: list[np.ndarray[Any, Any]] = []
self, frames_in: "List[np.ndarray[Any, Any]]"
) -> "List[np.ndarray[Any, Any]]":
frames_out: "List[np.ndarray[Any, Any]]" = []

resample: Literal[0, 1, 2, 3]
if self.opt_comp.scale_filter == "nearest":
Expand All @@ -544,22 +532,20 @@ def frames_resize(
with Image.fromarray(frame, "RGBA") as im: # type: ignore
width, height = im.size

if self.res_w is None:
self.res_w = width
if self.res_h is None:
self.res_h = height
if self.res_w is None:
self.res_w = width
if self.res_h is None:
self.res_h = height

if width > height:
width_new = self.res_w
height_new = height * self.res_w // width
else:
height_new = self.res_h
width_new = width * self.res_h // height
if width > height:
width_new = self.res_w
height_new = height * self.res_w // width
else:
height_new = self.res_h
width_new = width * self.res_h // height

with (
im.resize((width_new, height_new), resample=resample) as im_resized,
Image.new("RGBA", (self.res_w, self.res_h), (0, 0, 0, 0)) as im_new,
):
with im.resize((width_new, height_new), resample=resample) as im_resized:
with Image.new("RGBA", (self.res_w, self.res_h), (0, 0, 0, 0)) as im_new:
im_new.paste(
im_resized,
((self.res_w - width_new) // 2, (self.res_h - height_new) // 2),
Expand All @@ -569,16 +555,16 @@ def frames_resize(
return frames_out

def frames_drop(
self, frames_in: list[np.ndarray[Any, Any]]
) -> list[np.ndarray[Any, Any]]:
self, frames_in: "List[np.ndarray[Any, Any]]"
) -> "List[np.ndarray[Any, Any]]":
if (
not self.codec_info_orig.is_animated
or not self.fps
or len(self.frames_processed) == 1
):
return [frames_in[0]]

frames_out: list[np.ndarray[Any, Any]] = []
frames_out: "List[np.ndarray[Any, Any]]" = []

# fps_ratio: 1 frame in new anim equal to how many frame in old anim
# speed_ratio: How much to speed up / slow down
Expand Down
8 changes: 4 additions & 4 deletions src/sticker_convert/downloaders/download_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from pathlib import Path
from queue import Queue
from typing import Any, Optional, Union
from typing import Any, Dict, List, Optional, Tuple, Union

import requests

Expand All @@ -20,7 +20,7 @@ def __init__(
cb: Union[
Queue[
Union[
tuple[str, Optional[tuple[str]], Optional[dict[str, Any]]],
Tuple[str, Optional[Tuple[str]], Optional[Dict[str, Any]]],
str,
None,
]
Expand All @@ -35,7 +35,7 @@ def __init__(
self.cb: Union[
Queue[
Union[
tuple[str, Optional[tuple[str]], Optional[dict[str, Any]]],
Tuple[str, Optional[Tuple[str]], Optional[Dict[str, Any]]],
str,
None,
]
Expand All @@ -45,7 +45,7 @@ def __init__(
self.cb_return: CallbackReturn = cb_return

def download_multiple_files(
self, targets: list[tuple[str, Path]], retries: int = 3, **kwargs: Any
self, targets: List[Tuple[str, Path]], retries: int = 3, **kwargs: Any
):
# targets format: [(url1, dest2), (url2, dest2), ...]
self.cb.put(
Expand Down
Loading

0 comments on commit c4a982d

Please sign in to comment.