From 2a55ac7baf076e69cd98e4fb3926643dd7a721f5 Mon Sep 17 00:00:00 2001 From: Martijn Pieters Date: Fri, 20 Sep 2024 11:28:17 +0100 Subject: [PATCH] Address review feedback & some missed Incompletes --- stubs/qrcode/qrcode/LUT.pyi | 4 ++- stubs/qrcode/qrcode/image/pil.pyi | 5 +-- stubs/qrcode/qrcode/image/pure.pyi | 5 +-- stubs/qrcode/qrcode/image/styledpil.pyi | 9 ++--- .../qrcode/qrcode/image/styles/colormasks.pyi | 12 +++---- stubs/qrcode/qrcode/main.pyi | 12 +++++-- stubs/qrcode/qrcode/util.pyi | 34 +++++++++---------- 7 files changed, 46 insertions(+), 35 deletions(-) diff --git a/stubs/qrcode/qrcode/LUT.pyi b/stubs/qrcode/qrcode/LUT.pyi index 273608163b04..2e7f6fa4dd4e 100644 --- a/stubs/qrcode/qrcode/LUT.pyi +++ b/stubs/qrcode/qrcode/LUT.pyi @@ -1 +1,3 @@ -rsPoly_LUT: dict[int, list[int]] +from typing import Final + +rsPoly_LUT: Final[dict[int, list[int]]] diff --git a/stubs/qrcode/qrcode/image/pil.pyi b/stubs/qrcode/qrcode/image/pil.pyi index 96d364d9d08a..66413cb30f7f 100644 --- a/stubs/qrcode/qrcode/image/pil.pyi +++ b/stubs/qrcode/qrcode/image/pil.pyi @@ -1,4 +1,5 @@ -from typing import IO, Any, Literal +from pathlib import Path +from typing import Any, Literal from PIL import Image @@ -15,7 +16,7 @@ class PilImage(base.BaseImage): # kwargs are passed on to PIL.Image.save, which also accepts arbitrary keyword arguments. def save( # type: ignore[override] self, - stream: IO[bytes], + stream: str | bytes | Path | Image._Writeable, format: str | None = None, *, kind: str | None = None, diff --git a/stubs/qrcode/qrcode/image/pure.pyi b/stubs/qrcode/qrcode/image/pure.pyi index 198597fc0c8f..ec5df707f02f 100644 --- a/stubs/qrcode/qrcode/image/pure.pyi +++ b/stubs/qrcode/qrcode/image/pure.pyi @@ -1,5 +1,6 @@ +from _typeshed import SupportsWrite from collections.abc import Generator -from typing import IO, Any, Literal +from typing import Any, Literal from typing_extensions import TypeAlias from . import base @@ -15,7 +16,7 @@ class PyPNGImage(base.BaseImage): def new_image(self, **kwargs: Any) -> _Writer: ... def get_image(self, **kwargs: Any) -> _Writer: ... def drawrect(self, row: int, col: int) -> None: ... - def save(self, stream: IO[bytes], kind: str | None = None) -> None: ... + def save(self, stream: SupportsWrite[bytes], kind: str | None = None) -> None: ... def rows_iter(self) -> Generator[list[int], Any, None]: ... def border_rows_iter(self) -> Generator[list[int], Any, None]: ... diff --git a/stubs/qrcode/qrcode/image/styledpil.pyi b/stubs/qrcode/qrcode/image/styledpil.pyi index 749c48e56b6d..256bdc6fa7c5 100644 --- a/stubs/qrcode/qrcode/image/styledpil.pyi +++ b/stubs/qrcode/qrcode/image/styledpil.pyi @@ -1,5 +1,6 @@ -from _typeshed import StrOrBytesPath -from typing import IO, Any, Literal +from _typeshed import SupportsRead +from pathlib import Path +from typing import Any, Literal from PIL import Image @@ -30,7 +31,7 @@ class StyledPilImage(base.BaseImageWithDrawer): module_drawer: QRModuleDrawer | str | None = None, eye_drawer: QRModuleDrawer | str | None = None, color_mask: QRColorMask = ..., - embeded_image_path: StrOrBytesPath | IO[bytes] | None = None, + embeded_image_path: str | bytes | Path | SupportsRead[bytes] | None = None, embeded_image: Image.Image | None = None, embeded_image_resample: Image.Resampling = ..., **kwargs: Any, @@ -42,7 +43,7 @@ class StyledPilImage(base.BaseImageWithDrawer): # kwargs are passed on to PIL.Image.save, which also accepts arbitrary keyword arguments. def save( # type: ignore[override] self, - stream: IO[bytes], + stream: str | bytes | Path | Image._Writeable, format: str | None = None, *, kind: str | None = None, diff --git a/stubs/qrcode/qrcode/image/styles/colormasks.pyi b/stubs/qrcode/qrcode/image/styles/colormasks.pyi index fef80800934c..8fdd08621f4f 100644 --- a/stubs/qrcode/qrcode/image/styles/colormasks.pyi +++ b/stubs/qrcode/qrcode/image/styles/colormasks.pyi @@ -1,5 +1,5 @@ -from _typeshed import Incomplete, StrOrBytesPath -from typing import IO +from _typeshed import SupportsRead +from pathlib import Path from PIL import Image @@ -46,18 +46,18 @@ class HorizontalGradiantColorMask(QRColorMask): ) -> None: ... class VerticalGradiantColorMask(QRColorMask): - top_color: Incomplete - bottom_color: Incomplete + top_color: Ink + bottom_color: Ink def __init__( self, back_color: Ink = (255, 255, 255), top_color: Ink = (0, 0, 0), bottom_color: Ink = (0, 0, 255) ) -> None: ... class ImageColorMask(QRColorMask): - color_img: Incomplete + color_img: Ink def __init__( self, back_color: Ink = (255, 255, 255), - color_mask_path: StrOrBytesPath | IO[bytes] | None = None, + color_mask_path: str | bytes | Path | SupportsRead[bytes] | None = None, color_mask_image: Image.Image | None = None, ) -> None: ... paint_color: Ink diff --git a/stubs/qrcode/qrcode/main.pyi b/stubs/qrcode/qrcode/main.pyi index b985e745a8ff..09a7b7a16eca 100644 --- a/stubs/qrcode/qrcode/main.pyi +++ b/stubs/qrcode/qrcode/main.pyi @@ -1,6 +1,6 @@ from _typeshed import ConvertibleToInt from collections.abc import Sequence -from typing import Any, Generic, NamedTuple, TextIO, TypeVar, overload +from typing import Any, Generic, NamedTuple, Protocol, TypeVar, overload, type_check_only from typing_extensions import TypeAlias from ._types import ErrorCorrect, MaskPattern @@ -54,6 +54,12 @@ class ActiveWithNeighbors(NamedTuple): GenericImage = TypeVar("GenericImage", bound=BaseImage) # noqa: Y001 GenericImageLocal = TypeVar("GenericImageLocal", bound=BaseImage) # noqa: Y001 +@type_check_only +class _TTYWriter(Protocol): + def isatty(self) -> bool: ... + def write(self, s: str, /) -> object: ... + def flush(self) -> object: ... + class QRCode(Generic[GenericImage]): modules: ModulesType error_correction: ErrorCorrect @@ -109,8 +115,8 @@ class QRCode(Generic[GenericImage]): def setup_position_probe_pattern(self, row: int, col: int) -> None: ... def best_fit(self, start: int | None = None) -> int: ... def best_mask_pattern(self) -> int: ... - def print_tty(self, out: TextIO | None = None) -> None: ... - def print_ascii(self, out: TextIO | None = None, tty: bool = False, invert: bool = False) -> None: ... + def print_tty(self, out: _TTYWriter | None = None) -> None: ... + def print_ascii(self, out: _TTYWriter | None = None, tty: bool = False, invert: bool = False) -> None: ... # kwargs are passed on to the specific image factory used, and in turn passed through to # their make_image method. @overload diff --git a/stubs/qrcode/qrcode/util.pyi b/stubs/qrcode/qrcode/util.pyi index 8a423121e20d..df4832c5d11d 100644 --- a/stubs/qrcode/qrcode/util.pyi +++ b/stubs/qrcode/qrcode/util.pyi @@ -6,27 +6,27 @@ from typing_extensions import TypeAlias from ._types import ErrorCorrect, MaskPattern from .base import RSBlock as RSBlock -MODE_NUMBER: Final = 1 -MODE_ALPHA_NUM: Final = 2 -MODE_8BIT_BYTE: Final = 4 -MODE_KANJI: Final = 8 +MODE_NUMBER: Final[int] = 1 +MODE_ALPHA_NUM: Final[int] = 2 +MODE_8BIT_BYTE: Final[int] = 4 +MODE_KANJI: Final[int] = 8 _MODE: TypeAlias = Literal[1, 2, 4, 8] -MODE_SIZE_SMALL: dict[_MODE, int] -MODE_SIZE_MEDIUM: dict[_MODE, int] -MODE_SIZE_LARGE: dict[_MODE, int] +MODE_SIZE_SMALL: Final[dict[_MODE, int]] +MODE_SIZE_MEDIUM: Final[dict[_MODE, int]] +MODE_SIZE_LARGE: Final[dict[_MODE, int]] -ALPHA_NUM: bytes -RE_ALPHA_NUM: Pattern[bytes] -NUMBER_LENGTH: dict[int, int] -PATTERN_POSITION_TABLE: list[list[int]] -G15: int -G18: int -G15_MASK: int -PAD0: int -PAD1: int -BIT_LIMIT_TABLE: list[list[int]] +ALPHA_NUM: Final[bytes] +RE_ALPHA_NUM: Final[Pattern[bytes]] +NUMBER_LENGTH: Final[dict[int, int]] +PATTERN_POSITION_TABLE: Final[list[list[int]]] +G15: Final[int] +G18: Final[int] +G15_MASK: Final[int] +PAD0: Final[int] +PAD1: Final[int] +BIT_LIMIT_TABLE: Final[list[list[int]]] # In the implementation, MODE_KANJI is not accepted in all places _SupportedMode: TypeAlias = Literal[1, 2, 4]