From 50c3950bb6998f7b0ac75fd9e0a86d5b6df570cf Mon Sep 17 00:00:00 2001 From: Martijn Pieters Date: Tue, 17 Sep 2024 20:50:54 +0100 Subject: [PATCH] Complete coverage for the qrcode package --- pyrightconfig.stricter.json | 1 - stubs/qrcode/@tests/stubtest_allowlist.txt | 13 ++- stubs/qrcode/METADATA.toml | 3 +- stubs/qrcode/qrcode/LUT.pyi | 4 +- stubs/qrcode/qrcode/__init__.pyi | 6 +- stubs/qrcode/qrcode/_types.pyi | 9 ++ stubs/qrcode/qrcode/base.pyi | 32 +++---- stubs/qrcode/qrcode/console_scripts.pyi | 12 +-- stubs/qrcode/qrcode/image/base.pyi | 51 ++++++----- stubs/qrcode/qrcode/image/pil.pyi | 21 +++-- stubs/qrcode/qrcode/image/pure.pyi | 24 ++--- stubs/qrcode/qrcode/image/styledpil.pyi | 49 +++++++---- .../qrcode/qrcode/image/styles/colormasks.pyi | 87 +++++++++---------- .../image/styles/moduledrawers/base.pyi | 14 +-- .../qrcode/image/styles/moduledrawers/pil.pyi | 85 +++++++++--------- .../qrcode/image/styles/moduledrawers/svg.pyi | 48 +++++----- stubs/qrcode/qrcode/image/svg.pyi | 57 ++++++++---- stubs/qrcode/qrcode/main.pyi | 67 +++++++------- stubs/qrcode/qrcode/release.pyi | 2 +- stubs/qrcode/qrcode/util.pyi | 72 +++++++-------- 20 files changed, 364 insertions(+), 293 deletions(-) create mode 100644 stubs/qrcode/qrcode/_types.pyi diff --git a/pyrightconfig.stricter.json b/pyrightconfig.stricter.json index 05e6455833a1..a3ea8b6478dc 100644 --- a/pyrightconfig.stricter.json +++ b/pyrightconfig.stricter.json @@ -87,7 +87,6 @@ "stubs/pywin32", "stubs/pyxdg", "stubs/PyYAML", - "stubs/qrcode", "stubs/redis", "stubs/reportlab", "stubs/requests", diff --git a/stubs/qrcode/@tests/stubtest_allowlist.txt b/stubs/qrcode/@tests/stubtest_allowlist.txt index 8010322e711b..e9bb12b1b78b 100644 --- a/stubs/qrcode/@tests/stubtest_allowlist.txt +++ b/stubs/qrcode/@tests/stubtest_allowlist.txt @@ -1,16 +1,23 @@ # Internal modules qrcode\.compat qrcode\.compat\..* -qrcode\.tests +qrcode.tests qrcode\.tests\..* +# Stub-only module +qrcode._types + # Parameter "data" has unhelpful default value, which creates a QR code with string "None". -qrcode\.make -qrcode\.main\.make +qrcode.make +qrcode.main.make # Stubtest hiccup: It doesn't recognize that the annotated type is a base # class of the default class assigned to the attribute. qrcode\.image\..*\.default_drawer_class +# The implementation sets this attribute to None on the class but instances +# always set this to a PIL image instance. +qrcode\.image\.styles\.moduledrawers\.(pil\.)?CircleModuleDrawer.circle + # Leaked loop counter qrcode.base.i diff --git a/stubs/qrcode/METADATA.toml b/stubs/qrcode/METADATA.toml index e6451e017d7b..74396fc21bfd 100644 --- a/stubs/qrcode/METADATA.toml +++ b/stubs/qrcode/METADATA.toml @@ -1,5 +1,6 @@ version = "7.4.*" upstream_repository = "https://github.com/lincolnloop/python-qrcode" +requires = ["types-Pillow>=9.1.0"] [tool.stubtest] -extras = ["lxml"] +extras = ["pil"] diff --git a/stubs/qrcode/qrcode/LUT.pyi b/stubs/qrcode/qrcode/LUT.pyi index 8d6b33556d80..273608163b04 100644 --- a/stubs/qrcode/qrcode/LUT.pyi +++ b/stubs/qrcode/qrcode/LUT.pyi @@ -1,3 +1 @@ -from _typeshed import Incomplete - -rsPoly_LUT: Incomplete +rsPoly_LUT: dict[int, list[int]] diff --git a/stubs/qrcode/qrcode/__init__.pyi b/stubs/qrcode/qrcode/__init__.pyi index 7022363a9885..d027006ca1c4 100644 --- a/stubs/qrcode/qrcode/__init__.pyi +++ b/stubs/qrcode/qrcode/__init__.pyi @@ -1,3 +1,5 @@ +from typing import Any + from qrcode import image as image from qrcode.constants import ( ERROR_CORRECT_H as ERROR_CORRECT_H, @@ -5,6 +7,6 @@ from qrcode.constants import ( ERROR_CORRECT_M as ERROR_CORRECT_M, ERROR_CORRECT_Q as ERROR_CORRECT_Q, ) -from qrcode.main import make as make +from qrcode.main import QRCode as QRCode, make as make -def run_example(data: str = "http://www.lincolnloop.com", *args, **kwargs) -> None: ... +def run_example(data: str = "http://www.lincolnloop.com", *args: Any, **kwargs: Any) -> None: ... diff --git a/stubs/qrcode/qrcode/_types.pyi b/stubs/qrcode/qrcode/_types.pyi new file mode 100644 index 000000000000..c41388e51bcf --- /dev/null +++ b/stubs/qrcode/qrcode/_types.pyi @@ -0,0 +1,9 @@ +# Type aliases used in this stub package +from typing import Literal +from typing_extensions import TypeAlias + +Box: TypeAlias = tuple[tuple[int, int], tuple[int, int]] +Ink: TypeAlias = tuple[int, int, int] | tuple[int, int, int, int] + +ErrorCorrect: TypeAlias = Literal[0, 1, 2, 3] +MaskPattern: TypeAlias = Literal[0, 1, 2, 3, 4, 5, 6, 7] diff --git a/stubs/qrcode/qrcode/base.pyi b/stubs/qrcode/qrcode/base.pyi index 04785f4a28b4..0b5cd8aa385f 100644 --- a/stubs/qrcode/qrcode/base.pyi +++ b/stubs/qrcode/qrcode/base.pyi @@ -1,25 +1,27 @@ -from _typeshed import Incomplete -from typing import NamedTuple +from collections.abc import Iterator +from typing import NamedTuple, SupportsIndex -EXP_TABLE: Incomplete -LOG_TABLE: Incomplete -RS_BLOCK_OFFSET: Incomplete -RS_BLOCK_TABLE: Incomplete +from ._types import ErrorCorrect -def glog(n): ... -def gexp(n): ... +EXP_TABLE: list[int] +LOG_TABLE: list[int] +RS_BLOCK_OFFSET: dict[ErrorCorrect, int] +RS_BLOCK_TABLE: tuple[tuple[int, int, int] | tuple[int, int, int, int, int, int], ...] + +def glog(n: int) -> int: ... +def gexp(n: int) -> int: ... class Polynomial: - num: Incomplete - def __init__(self, num, shift) -> None: ... - def __getitem__(self, index): ... - def __iter__(self): ... + num: list[int] + def __init__(self, num: list[int], shift: int) -> None: ... + def __getitem__(self, index: SupportsIndex) -> int: ... + def __iter__(self) -> Iterator[int]: ... def __len__(self) -> int: ... - def __mul__(self, other): ... - def __mod__(self, other): ... + def __mul__(self, other: Polynomial) -> Polynomial: ... + def __mod__(self, other: Polynomial) -> Polynomial: ... class RSBlock(NamedTuple): total_count: int data_count: int -def rs_blocks(version, error_correction): ... +def rs_blocks(version: int, error_correction: ErrorCorrect) -> list[RSBlock]: ... diff --git a/stubs/qrcode/qrcode/console_scripts.pyi b/stubs/qrcode/qrcode/console_scripts.pyi index ace65bac112d..44bc8d475a7e 100644 --- a/stubs/qrcode/qrcode/console_scripts.pyi +++ b/stubs/qrcode/qrcode/console_scripts.pyi @@ -1,12 +1,12 @@ -from _typeshed import Incomplete -from collections.abc import Iterable +from collections.abc import Iterable, Sequence -from qrcode.image.base import BaseImage, DrawerAliases as DrawerAliases +from ._types import ErrorCorrect +from .image.base import BaseImage, DrawerAliases as DrawerAliases -default_factories: Incomplete -error_correction: Incomplete +default_factories: dict[str, str] +error_correction: dict[str, ErrorCorrect] -def main(args: Incomplete | None = None) -> None: ... +def main(args: Sequence[str] | None = None) -> None: ... def get_factory(module: str) -> type[BaseImage]: ... def get_drawer_help() -> str: ... def commas(items: Iterable[str], joiner: str = "or") -> str: ... diff --git a/stubs/qrcode/qrcode/image/base.pyi b/stubs/qrcode/qrcode/image/base.pyi index 8fc2a6259a5d..e08371c0b299 100644 --- a/stubs/qrcode/qrcode/image/base.pyi +++ b/stubs/qrcode/qrcode/image/base.pyi @@ -1,10 +1,10 @@ import abc -from _typeshed import Incomplete -from typing import Any +from collections.abc import Callable +from typing import IO, Any from typing_extensions import TypeAlias -from qrcode.image.styles.moduledrawers.base import QRModuleDrawer -from qrcode.main import QRCode +from ..main import ModulesType, QRCode +from .styles.moduledrawers.base import QRModuleDrawer DrawerAliases: TypeAlias = dict[str, tuple[type[QRModuleDrawer], dict[str, Any]]] @@ -14,25 +14,27 @@ class BaseImage(metaclass=abc.ABCMeta): needs_context: bool needs_processing: bool needs_drawrect: bool - border: Incomplete - width: Incomplete - box_size: Incomplete - pixel_size: Incomplete - modules: Incomplete - def __init__(self, border, width, box_size, *args, **kwargs) -> None: ... + border: int + width: int + box_size: int + pixel_size: int + modules: list[list[bool | None]] + def __init__( + self, border: int, width: int, box_size: int, *args: Any, qrcode_modules: ModulesType | None, **kwargs: Any + ) -> None: ... @abc.abstractmethod - def drawrect(self, row, col): ... - def drawrect_context(self, row: int, col: int, qr: QRCode[Incomplete]): ... + def drawrect(self, row: int, col: int) -> None: ... + def drawrect_context(self, row: int, col: int, qr: QRCode[Any]) -> None: ... def process(self) -> None: ... @abc.abstractmethod - def save(self, stream, kind: Incomplete | None = None): ... - def pixel_box(self, row, col): ... + def save(self, stream: IO[bytes], kind: str | None = None) -> None: ... + def pixel_box(self, row: int, col: int) -> tuple[tuple[int, int], tuple[int, int]]: ... @abc.abstractmethod - def new_image(self, **kwargs) -> Any: ... + def new_image(self, **kwargs: Any) -> Any: ... def init_new_image(self) -> None: ... - def get_image(self, **kwargs): ... - def check_kind(self, kind, transform: Incomplete | None = None): ... - def is_eye(self, row: int, col: int): ... + def get_image(self, **kwargs: Any) -> Any: ... + def check_kind(self, kind: str | None, transform: Callable[[str | None], str | None] | None = None) -> str | None: ... + def is_eye(self, row: int, col: int) -> bool: ... class BaseImageWithDrawer(BaseImage, metaclass=abc.ABCMeta): default_drawer_class: type[QRModuleDrawer] @@ -43,8 +45,15 @@ class BaseImageWithDrawer(BaseImage, metaclass=abc.ABCMeta): module_drawer: QRModuleDrawer eye_drawer: QRModuleDrawer def __init__( - self, *args, module_drawer: QRModuleDrawer | str | None = None, eye_drawer: QRModuleDrawer | str | None = None, **kwargs + self, + border: int, + width: int, + box_size: int, + *args: Any, + module_drawer: QRModuleDrawer | str | None = None, + eye_drawer: QRModuleDrawer | str | None = None, + **kwargs: Any, ) -> None: ... def get_drawer(self, drawer: QRModuleDrawer | str | None) -> QRModuleDrawer | None: ... - def init_new_image(self): ... - def drawrect_context(self, row: int, col: int, qr: QRCode[Incomplete]): ... + def init_new_image(self) -> None: ... + def drawrect_context(self, row: int, col: int, qr: QRCode[Any]) -> None: ... diff --git a/stubs/qrcode/qrcode/image/pil.pyi b/stubs/qrcode/qrcode/image/pil.pyi index 3ae1e00cc0f8..873f4933c695 100644 --- a/stubs/qrcode/qrcode/image/pil.pyi +++ b/stubs/qrcode/qrcode/image/pil.pyi @@ -1,11 +1,14 @@ -from _typeshed import Incomplete +from typing import IO, Any, Literal -import qrcode.image.base +from PIL import Image -class PilImage(qrcode.image.base.BaseImage): - kind: str - fill_color: Incomplete - def new_image(self, **kwargs): ... - def drawrect(self, row, col) -> None: ... - def save(self, stream, format: Incomplete | None = None, **kwargs) -> None: ... # type: ignore[override] - def __getattr__(self, name): ... +from . import base + +class PilImage(base.BaseImage): + kind: Literal["PNG"] + fill_color: str + def new_image(self, *, back_color: str = "white", fill_color: str = "black", **kwargs: Any) -> Image.Image: ... + def get_image(self, **kwargs: Any) -> Image.Image: ... + def drawrect(self, row: int, col: int) -> None: ... + def save(self, stream: IO[bytes], format: str | None = None, *, kind: str | None = None, **kwargs: Any) -> None: ... # type: ignore[override] + def __getattr__(self, name: str) -> Any: ... diff --git a/stubs/qrcode/qrcode/image/pure.pyi b/stubs/qrcode/qrcode/image/pure.pyi index 36177abe178c..91348eee228c 100644 --- a/stubs/qrcode/qrcode/image/pure.pyi +++ b/stubs/qrcode/qrcode/image/pure.pyi @@ -1,16 +1,20 @@ -from _typeshed import Incomplete from collections.abc import Generator +from typing import IO, Any, Literal +from typing_extensions import TypeAlias -import qrcode.image.base +from . import base -class PyPNGImage(qrcode.image.base.BaseImage): +# png.Writer; no types available +_Writer: TypeAlias = Any + +class PyPNGImage(base.BaseImage): kind: str - allowed_kinds: Incomplete - needs_drawrect: bool - def new_image(self, **kwargs): ... - def drawrect(self, row, col) -> None: ... - def save(self, stream, kind: Incomplete | None = None) -> None: ... - def rows_iter(self) -> Generator[Incomplete, Incomplete, None]: ... - def border_rows_iter(self) -> Generator[Incomplete, None, None]: ... + allowed_kinds: tuple[Literal["PNG"]] + 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 rows_iter(self) -> Generator[list[int], Any, None]: ... + def border_rows_iter(self) -> Generator[list[int], Any, None]: ... PymagingImage = PyPNGImage diff --git a/stubs/qrcode/qrcode/image/styledpil.pyi b/stubs/qrcode/qrcode/image/styledpil.pyi index 1d2ed26bef00..99ad89ccd7a3 100644 --- a/stubs/qrcode/qrcode/image/styledpil.pyi +++ b/stubs/qrcode/qrcode/image/styledpil.pyi @@ -1,22 +1,37 @@ import abc -from _typeshed import Incomplete +from _typeshed import StrOrBytesPath +from typing import IO, Any, Literal -import qrcode.image.base -from qrcode.image.styles.colormasks import QRColorMask -from qrcode.image.styles.moduledrawers import SquareModuleDrawer +from PIL import Image -class StyledPilImage(qrcode.image.base.BaseImageWithDrawer, metaclass=abc.ABCMeta): - kind: str - needs_processing: bool +from .._types import Ink +from . import base +from .styles.colormasks import QRColorMask +from .styles.moduledrawers import SquareModuleDrawer +from .styles.moduledrawers.base import QRModuleDrawer + +class StyledPilImage(base.BaseImageWithDrawer, metaclass=abc.ABCMeta): + kind: Literal["PNG"] color_mask: QRColorMask - default_drawer_class = SquareModuleDrawer - embeded_image: Incomplete - embeded_image_resample: Incomplete - paint_color: Incomplete - def __init__(self, *args, **kwargs) -> None: ... - def new_image(self, **kwargs): ... - def init_new_image(self) -> None: ... - def process(self) -> None: ... + default_drawer_class: type[SquareModuleDrawer] + embeded_image: Image.Image + embeded_image_resample: Image.Resampling + paint_color: Ink + def __init__( + self, + border: int, + width: int, + box_size: int, + *args: Any, + 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: Image.Image | None = None, + embeded_image_resample: Image.Resampling = ..., + **kwargs: Any, + ) -> None: ... + def new_image(self, **kwargs: Any) -> Image.Image: ... def draw_embeded_image(self) -> None: ... - def save(self, stream, format: Incomplete | None = None, **kwargs) -> None: ... # type: ignore[override] - def __getattr__(self, name): ... + def save(self, stream: IO[bytes], format: str | None = None, *, kind: str | None = None, **kwargs: Any) -> None: ... # type: ignore[override] + def __getattr__(self, name: str) -> Any: ... diff --git a/stubs/qrcode/qrcode/image/styles/colormasks.pyi b/stubs/qrcode/qrcode/image/styles/colormasks.pyi index 12ad288796df..b42232d6b7b1 100644 --- a/stubs/qrcode/qrcode/image/styles/colormasks.pyi +++ b/stubs/qrcode/qrcode/image/styles/colormasks.pyi @@ -1,65 +1,62 @@ -from _typeshed import Incomplete +from _typeshed import Incomplete, StrOrBytesPath +from typing import IO, Any + +from PIL import Image + +from ..._types import Ink +from ..styledpil import StyledPilImage class QRColorMask: - back_color: Incomplete + back_color: Ink has_transparency: bool - paint_color = back_color - def initialize(self, styledPilImage, image) -> None: ... - def apply_mask(self, image) -> None: ... - def get_fg_pixel(self, image, x, y) -> None: ... - def get_bg_pixel(self, image, x, y): ... - def interp_num(self, n1, n2, norm): ... - def interp_color(self, col1, col2, norm): ... - def extrap_num(self, n1, n2, interped_num): ... - def extrap_color(self, col1, col2, interped_color): ... + paint_color: Ink + def initialize(self, styledPilImage: StyledPilImage, image: Any) -> None: ... + def apply_mask(self, image: Image.Image) -> None: ... + def get_fg_pixel(self, image: Image.Image, x: int, y: int) -> Ink: ... + def get_bg_pixel(self, image: Image.Image, x: int, y: int) -> Ink: ... + def interp_num(self, n1: int, n2: int, norm: float) -> int: ... + def interp_color(self, col1: Ink, col2: Ink, norm: float) -> Ink: ... + def extrap_num(self, n1: int, n2: int, interped_num: int) -> float | None: ... + def extrap_color(self, col1: Ink, col2: Ink, interped_color: Ink) -> float | None: ... class SolidFillColorMask(QRColorMask): - back_color: Incomplete - front_color: Incomplete - has_transparency: Incomplete - def __init__(self, back_color=(255, 255, 255), front_color=(0, 0, 0)) -> None: ... - def apply_mask(self, image) -> None: ... - def get_fg_pixel(self, image, x, y): ... + front_color: Ink + def __init__(self, back_color: Ink = (255, 255, 255), front_color: Ink = (0, 0, 0)) -> None: ... class RadialGradiantColorMask(QRColorMask): - back_color: Incomplete - center_color: Incomplete - edge_color: Incomplete - has_transparency: Incomplete - def __init__(self, back_color=(255, 255, 255), center_color=(0, 0, 0), edge_color=(0, 0, 255)) -> None: ... - def get_fg_pixel(self, image, x, y): ... + center_color: Ink + edge_color: Ink + def __init__( + self, back_color: Ink = (255, 255, 255), center_color: Ink = (0, 0, 0), edge_color: Ink = (0, 0, 255) + ) -> None: ... class SquareGradiantColorMask(QRColorMask): - back_color: Incomplete - center_color: Incomplete - edge_color: Incomplete - has_transparency: Incomplete - def __init__(self, back_color=(255, 255, 255), center_color=(0, 0, 0), edge_color=(0, 0, 255)) -> None: ... - def get_fg_pixel(self, image, x, y): ... + center_color: Ink + edge_color: Ink + def __init__( + self, back_color: Ink = (255, 255, 255), center_color: Ink = (0, 0, 0), edge_color: Ink = (0, 0, 255) + ) -> None: ... class HorizontalGradiantColorMask(QRColorMask): - back_color: Incomplete - left_color: Incomplete - right_color: Incomplete - has_transparency: Incomplete - def __init__(self, back_color=(255, 255, 255), left_color=(0, 0, 0), right_color=(0, 0, 255)) -> None: ... - def get_fg_pixel(self, image, x, y): ... + left_color: Ink + right_color: Ink + def __init__( + self, back_color: Ink = (255, 255, 255), left_color: Ink = (0, 0, 0), right_color: Ink = (0, 0, 255) + ) -> None: ... class VerticalGradiantColorMask(QRColorMask): - back_color: Incomplete top_color: Incomplete bottom_color: Incomplete - has_transparency: Incomplete - def __init__(self, back_color=(255, 255, 255), top_color=(0, 0, 0), bottom_color=(0, 0, 255)) -> None: ... - def get_fg_pixel(self, image, x, y): ... + 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): - back_color: Incomplete color_img: Incomplete - has_transparency: Incomplete def __init__( - self, back_color=(255, 255, 255), color_mask_path: Incomplete | None = None, color_mask_image: Incomplete | None = None + self, + back_color: Ink = (255, 255, 255), + color_mask_path: StrOrBytesPath | IO[bytes] | None = None, + color_mask_image: Image.Image | None = None, ) -> None: ... - paint_color: Incomplete - def initialize(self, styledPilImage, image) -> None: ... - def get_fg_pixel(self, image, x, y): ... + paint_color: Ink diff --git a/stubs/qrcode/qrcode/image/styles/moduledrawers/base.pyi b/stubs/qrcode/qrcode/image/styles/moduledrawers/base.pyi index 917c1ac41424..4d000288334e 100644 --- a/stubs/qrcode/qrcode/image/styles/moduledrawers/base.pyi +++ b/stubs/qrcode/qrcode/image/styles/moduledrawers/base.pyi @@ -1,12 +1,14 @@ import abc -from _typeshed import Incomplete +from typing import Any -from qrcode.image.base import BaseImage +from ...._types import Box +from ....main import ActiveWithNeighbors +from ...base import BaseImage class QRModuleDrawer(abc.ABC, metaclass=abc.ABCMeta): - needs_neighbors: bool - def __init__(self, **kwargs) -> None: ... - img: Incomplete + needs_neighbors: bool = False + def __init__(self, **kwargs: Any) -> None: ... + img: BaseImage def initialize(self, img: BaseImage) -> None: ... @abc.abstractmethod - def drawrect(self, box, is_active) -> None: ... + def drawrect(self, box: Box, is_active: bool | ActiveWithNeighbors) -> None: ... diff --git a/stubs/qrcode/qrcode/image/styles/moduledrawers/pil.pyi b/stubs/qrcode/qrcode/image/styles/moduledrawers/pil.pyi index e5c4e94b7c4f..637091661493 100644 --- a/stubs/qrcode/qrcode/image/styles/moduledrawers/pil.pyi +++ b/stubs/qrcode/qrcode/image/styles/moduledrawers/pil.pyi @@ -1,9 +1,12 @@ import abc -from _typeshed import Incomplete +from typing import Literal -from qrcode.image.styledpil import StyledPilImage -from qrcode.image.styles.moduledrawers.base import QRModuleDrawer -from qrcode.main import ActiveWithNeighbors +from PIL import Image, ImageDraw + +from ...._types import Box +from ....main import ActiveWithNeighbors +from ...styledpil import StyledPilImage +from .base import QRModuleDrawer ANTIALIASING_FACTOR: int @@ -11,59 +14,53 @@ class StyledPilQRModuleDrawer(QRModuleDrawer, metaclass=abc.ABCMeta): img: StyledPilImage class SquareModuleDrawer(StyledPilQRModuleDrawer): - imgDraw: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - def drawrect(self, box, is_active: bool): ... + imgDraw: ImageDraw.ImageDraw + def drawrect(self, box: Box, is_active: bool) -> None: ... # type: ignore[override] class GappedSquareModuleDrawer(StyledPilQRModuleDrawer): - size_ratio: Incomplete + size_ratio: float def __init__(self, size_ratio: float = 0.8) -> None: ... - imgDraw: Incomplete - delta: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - def drawrect(self, box, is_active: bool): ... + imgDraw: ImageDraw.ImageDraw + delta: float + def drawrect(self, box: Box, is_active: bool) -> None: ... # type: ignore[override] class CircleModuleDrawer(StyledPilQRModuleDrawer): - circle: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - def drawrect(self, box, is_active: bool): ... + circle: Image.Image + def drawrect(self, box: Box, is_active: bool) -> None: ... # type: ignore[override] class RoundedModuleDrawer(StyledPilQRModuleDrawer): - needs_neighbors: bool - radius_ratio: Incomplete - def __init__(self, radius_ratio: int = 1) -> None: ... - corner_width: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - SQUARE: Incomplete - NW_ROUND: Incomplete - SW_ROUND: Incomplete - SE_ROUND: Incomplete - NE_ROUND: Incomplete + needs_neighbors: Literal[True] + radius_ratio: float + def __init__(self, radius_ratio: float = 1) -> None: ... + corner_width: int + SQUARE: Image.Image + NW_ROUND: Image.Image + SW_ROUND: Image.Image + SE_ROUND: Image.Image + NE_ROUND: Image.Image def setup_corners(self) -> None: ... - def drawrect(self, box: list[list[int]], is_active: ActiveWithNeighbors): ... + def drawrect(self, box: Box, is_active: ActiveWithNeighbors) -> None: ... # type: ignore[override] class VerticalBarsDrawer(StyledPilQRModuleDrawer): - needs_neighbors: bool - horizontal_shrink: Incomplete + needs_neighbors: Literal[True] + horizontal_shrink: float def __init__(self, horizontal_shrink: float = 0.8) -> None: ... - half_height: Incomplete - delta: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - SQUARE: Incomplete - ROUND_TOP: Incomplete - ROUND_BOTTOM: Incomplete + half_height: int + delta: int + SQUARE: Image.Image + ROUND_TOP: Image.Image + ROUND_BOTTOM: Image.Image def setup_edges(self) -> None: ... - def drawrect(self, box, is_active: ActiveWithNeighbors): ... + def drawrect(self, box: Box, is_active: ActiveWithNeighbors) -> None: ... # type: ignore[override] class HorizontalBarsDrawer(StyledPilQRModuleDrawer): - needs_neighbors: bool - vertical_shrink: Incomplete + needs_neighbors: Literal[True] + vertical_shrink: float def __init__(self, vertical_shrink: float = 0.8) -> None: ... - half_width: Incomplete - delta: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - SQUARE: Incomplete - ROUND_LEFT: Incomplete - ROUND_RIGHT: Incomplete + half_width: int + delta: int + SQUARE: Image.Image + ROUND_LEFT: Image.Image + ROUND_RIGHT: Image.Image def setup_edges(self) -> None: ... - def drawrect(self, box, is_active: ActiveWithNeighbors): ... + def drawrect(self, box: Box, is_active: ActiveWithNeighbors) -> None: ... # type: ignore[override] diff --git a/stubs/qrcode/qrcode/image/styles/moduledrawers/svg.pyi b/stubs/qrcode/qrcode/image/styles/moduledrawers/svg.pyi index 8ff91c13e06d..ed50e41860e0 100644 --- a/stubs/qrcode/qrcode/image/styles/moduledrawers/svg.pyi +++ b/stubs/qrcode/qrcode/image/styles/moduledrawers/svg.pyi @@ -1,10 +1,11 @@ import abc -from _typeshed import Incomplete from decimal import Decimal -from typing import NamedTuple +from typing import Any, NamedTuple +from xml.etree.ElementTree import Element, QName -from qrcode.image.styles.moduledrawers.base import QRModuleDrawer -from qrcode.image.svg import SvgFragmentImage, SvgPathImage +from ...._types import Box +from ...svg import SvgFragmentImage, SvgPathImage +from .base import QRModuleDrawer ANTIALIASING_FACTOR: int @@ -18,42 +19,37 @@ class Coords(NamedTuple): class BaseSvgQRModuleDrawer(QRModuleDrawer, metaclass=abc.ABCMeta): img: SvgFragmentImage - size_ratio: Incomplete - def __init__(self, *, size_ratio: Decimal = ..., **kwargs) -> None: ... - box_delta: Incomplete - box_size: Incomplete - box_half: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - def coords(self, box) -> Coords: ... + size_ratio: Decimal + def __init__(self, *, size_ratio: Decimal = ..., **kwargs: Any) -> None: ... + box_delta: float + box_size: Decimal + box_half: Decimal + def coords(self, box: Box) -> Coords: ... class SvgQRModuleDrawer(BaseSvgQRModuleDrawer, metaclass=abc.ABCMeta): tag: str - tag_qname: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - def drawrect(self, box, is_active: bool): ... + tag_qname: QName + def drawrect(self, box: Box, is_active: bool) -> None: ... # type: ignore[override] @abc.abstractmethod - def el(self, box): ... + def el(self, box: Box) -> Element: ... class SvgSquareDrawer(SvgQRModuleDrawer): - unit_size: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - def el(self, box): ... + unit_size: str + def el(self, box: Box) -> Element: ... class SvgCircleDrawer(SvgQRModuleDrawer): tag: str - radius: Incomplete - def initialize(self, *args, **kwargs) -> None: ... - def el(self, box): ... + radius: str + def el(self, box: Box) -> Element: ... class SvgPathQRModuleDrawer(BaseSvgQRModuleDrawer, metaclass=abc.ABCMeta): img: SvgPathImage - def drawrect(self, box, is_active: bool): ... + def drawrect(self, box: Box, is_active: bool) -> None: ... # type: ignore[override] @abc.abstractmethod - def subpath(self, box) -> str: ... + def subpath(self, box: Box) -> str: ... class SvgPathSquareDrawer(SvgPathQRModuleDrawer): - def subpath(self, box) -> str: ... + def subpath(self, box: Box) -> str: ... class SvgPathCircleDrawer(SvgPathQRModuleDrawer): - def initialize(self, *args, **kwargs) -> None: ... - def subpath(self, box) -> str: ... + def subpath(self, box: Box) -> str: ... diff --git a/stubs/qrcode/qrcode/image/svg.pyi b/stubs/qrcode/qrcode/image/svg.pyi index 73f50127b1c3..471a8dcddaea 100644 --- a/stubs/qrcode/qrcode/image/svg.pyi +++ b/stubs/qrcode/qrcode/image/svg.pyi @@ -1,38 +1,59 @@ import abc -from _typeshed import Incomplete from decimal import Decimal -from typing import Literal, overload +from typing import Any, Literal, overload from xml.etree.ElementTree import Element -import qrcode.image.base -from qrcode.image.styles.moduledrawers.base import QRModuleDrawer +from . import base +from .styles.moduledrawers.base import QRModuleDrawer -class SvgFragmentImage(qrcode.image.base.BaseImageWithDrawer, metaclass=abc.ABCMeta): +class SvgFragmentImage(base.BaseImageWithDrawer, metaclass=abc.ABCMeta): kind: str - allowed_kinds: Incomplete + allowed_kinds: tuple[Literal["SVG"]] default_drawer_class: type[QRModuleDrawer] - unit_size: Incomplete - def __init__(self, *args, **kwargs) -> None: ... + unit_size: Decimal | str @overload def units(self, pixels: int | Decimal, text: Literal[False]) -> Decimal: ... @overload def units(self, pixels: int | Decimal, text: Literal[True] = True) -> str: ... - def save(self, stream, kind: Incomplete | None = None) -> None: ... - def to_string(self, **kwargs): ... - def new_image(self, **kwargs): ... + @overload + def to_string( + self, + *, + encoding: None = None, + method: str | None = None, + xml_declaration: bool | None = None, + default_namespace: str | None = None, + short_empty_elements: bool = True, + ) -> bytes: ... + @overload + def to_string( + self, + *, + encoding: Literal["unicode"], + method: str | None = None, + xml_declaration: bool | None = None, + default_namespace: str | None = None, + short_empty_elements: bool = True, + ) -> str: ... + @overload + def to_string( + self, + *, + encoding: str, + method: str | None = None, + xml_declaration: bool | None = None, + default_namespace: str | None = None, + short_empty_elements: bool = True, + ) -> Any: ... + def new_image(self, **kwargs: Any) -> Element: ... class SvgImage(SvgFragmentImage, metaclass=abc.ABCMeta): background: str | None - drawer_aliases: qrcode.image.base.DrawerAliases + drawer_aliases: base.DrawerAliases class SvgPathImage(SvgImage, metaclass=abc.ABCMeta): - QR_PATH_STYLE: Incomplete - needs_processing: bool + QR_PATH_STYLE: dict[str, str] path: Element | None - default_drawer_class: type[QRModuleDrawer] - drawer_aliases: Incomplete - def __init__(self, *args, **kwargs) -> None: ... - def process(self) -> None: ... class SvgFillImage(SvgImage, metaclass=abc.ABCMeta): background: str diff --git a/stubs/qrcode/qrcode/main.pyi b/stubs/qrcode/qrcode/main.pyi index 63329bb55e2b..2a9939bee343 100644 --- a/stubs/qrcode/qrcode/main.pyi +++ b/stubs/qrcode/qrcode/main.pyi @@ -1,38 +1,43 @@ -from _typeshed import ConvertibleToInt, Incomplete -from typing import Any, Generic, Literal, NamedTuple, TypeVar, overload +from _typeshed import ConvertibleToInt +from collections.abc import Sequence +from typing import Any, Generic, NamedTuple, TextIO, TypeVar, overload from typing_extensions import TypeAlias +from ._types import ErrorCorrect, MaskPattern from .image.base import BaseImage -from .util import QRData, _MaskPattern +from .image.pil import PilImage +from .image.pure import PyPNGImage +from .util import QRData ModulesType: TypeAlias = list[list[bool | None]] precomputed_qr_blanks: dict[int, ModulesType] -_DefaultImage: TypeAlias = Any # PilImage if Pillow is installed, PyPNGImage otherwise +_DefaultImage: TypeAlias = PilImage | PyPNGImage # PilImage if Pillow is installed, PyPNGImage otherwise +_AnySeq = TypeVar("_AnySeq", bound=Sequence[Any]) @overload def make( data: QRData | bytes | str, *, version: ConvertibleToInt | None = None, - error_correction: Literal[0, 1, 2, 3] = 0, + error_correction: ErrorCorrect = 0, box_size: ConvertibleToInt = 10, border: ConvertibleToInt = 4, image_factory: None = None, - mask_pattern: _MaskPattern | None = None, + mask_pattern: MaskPattern | None = None, ) -> _DefaultImage: ... @overload def make( data: QRData | bytes | str, *, version: ConvertibleToInt | None = None, - error_correction: Literal[0, 1, 2, 3] = 0, + error_correction: ErrorCorrect = 0, box_size: ConvertibleToInt = 10, border: ConvertibleToInt = 4, image_factory: type[GenericImage], - mask_pattern: _MaskPattern | None = None, + mask_pattern: MaskPattern | None = None, ) -> GenericImage: ... -def copy_2d_array(x): ... +def copy_2d_array(x: Sequence[_AnySeq]) -> list[_AnySeq]: ... class ActiveWithNeighbors(NamedTuple): NW: bool @@ -51,7 +56,7 @@ GenericImageLocal = TypeVar("GenericImageLocal", bound=BaseImage) # noqa: Y001 class QRCode(Generic[GenericImage]): modules: ModulesType - error_correction: Literal[0, 1, 2, 3] + error_correction: ErrorCorrect box_size: int border: int image_factory: type[GenericImage] | None @@ -59,53 +64,53 @@ class QRCode(Generic[GenericImage]): def __init__( self, version: ConvertibleToInt | None, - error_correction: Literal[0, 1, 2, 3], + error_correction: ErrorCorrect, box_size: ConvertibleToInt, border: ConvertibleToInt, image_factory: type[GenericImage], - mask_pattern: _MaskPattern | None = None, + mask_pattern: MaskPattern | None = None, ) -> None: ... @overload def __init__( self, version: ConvertibleToInt | None = None, - error_correction: Literal[0, 1, 2, 3] = 0, + error_correction: ErrorCorrect = 0, box_size: ConvertibleToInt = 10, border: ConvertibleToInt = 4, *, image_factory: type[GenericImage], - mask_pattern: _MaskPattern | None = None, + mask_pattern: MaskPattern | None = None, ) -> None: ... @overload def __init__( - self: QRCode[_DefaultImage], + self: QRCode[BaseImage], version: ConvertibleToInt | None = None, - error_correction: Literal[0, 1, 2, 3] = 0, + error_correction: ErrorCorrect = 0, box_size: ConvertibleToInt = 10, border: ConvertibleToInt = 4, image_factory: None = None, - mask_pattern: _MaskPattern | None = None, + mask_pattern: MaskPattern | None = None, ) -> None: ... @property def version(self) -> int: ... @version.setter def version(self, value: ConvertibleToInt | None) -> None: ... @property - def mask_pattern(self) -> _MaskPattern | None: ... + def mask_pattern(self) -> MaskPattern | None: ... @mask_pattern.setter - def mask_pattern(self, pattern: _MaskPattern | None) -> None: ... + def mask_pattern(self, pattern: MaskPattern | None) -> None: ... modules_count: int - data_cache: Incomplete - data_list: Incomplete + data_cache: list[int] + data_list: list[QRData] def clear(self) -> None: ... def add_data(self, data: QRData | bytes | str, optimize: int = 20) -> None: ... def make(self, fit: bool = True) -> None: ... - def makeImpl(self, test, mask_pattern) -> None: ... - def setup_position_probe_pattern(self, row, col) -> None: ... - def best_fit(self, start: Incomplete | None = None): ... - def best_mask_pattern(self): ... - def print_tty(self, out: Incomplete | None = None) -> None: ... - def print_ascii(self, out: Incomplete | None = None, tty: bool = False, invert: bool = False): ... + def makeImpl(self, test: bool, mask_pattern: MaskPattern) -> None: ... + 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: ... @overload def make_image(self, image_factory: None = None, **kwargs: Any) -> GenericImage: ... @overload @@ -113,8 +118,8 @@ class QRCode(Generic[GenericImage]): def is_constrained(self, row: int, col: int) -> bool: ... def setup_timing_pattern(self) -> None: ... def setup_position_adjust_pattern(self) -> None: ... - def setup_type_number(self, test) -> None: ... - def setup_type_info(self, test, mask_pattern) -> None: ... - def map_data(self, data, mask_pattern) -> None: ... - def get_matrix(self): ... + def setup_type_number(self, test: bool) -> None: ... + def setup_type_info(self, test: bool, mask_pattern: MaskPattern) -> None: ... + def map_data(self, data: Sequence[int], mask_pattern: MaskPattern) -> None: ... + def get_matrix(self) -> list[list[bool]]: ... def active_with_neighbors(self, row: int, col: int) -> ActiveWithNeighbors: ... diff --git a/stubs/qrcode/qrcode/release.pyi b/stubs/qrcode/qrcode/release.pyi index eac4d5241953..823dd58f3e15 100644 --- a/stubs/qrcode/qrcode/release.pyi +++ b/stubs/qrcode/qrcode/release.pyi @@ -1 +1 @@ -def update_manpage(data) -> None: ... +def update_manpage(data: dict[str, str]) -> None: ... diff --git a/stubs/qrcode/qrcode/util.pyi b/stubs/qrcode/qrcode/util.pyi index 993455589c3e..8a423121e20d 100644 --- a/stubs/qrcode/qrcode/util.pyi +++ b/stubs/qrcode/qrcode/util.pyi @@ -1,65 +1,69 @@ -from _typeshed import Incomplete from collections.abc import Callable, Generator +from re import Pattern from typing import Final, Literal, overload from typing_extensions import TypeAlias -from qrcode.base import RSBlock as RSBlock - -_MaskPattern: TypeAlias = Literal[0, 1, 2, 3, 4, 5, 6, 7] +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_SIZE_SMALL: Incomplete -MODE_SIZE_MEDIUM: Incomplete -MODE_SIZE_LARGE: Incomplete +_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] ALPHA_NUM: bytes -RE_ALPHA_NUM: Incomplete -NUMBER_LENGTH: Incomplete -PATTERN_POSITION_TABLE: Incomplete -G15: Incomplete -G18: Incomplete -G15_MASK: Incomplete +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: Incomplete +BIT_LIMIT_TABLE: list[list[int]] + +# In the implementation, MODE_KANJI is not accepted in all places +_SupportedMode: TypeAlias = Literal[1, 2, 4] -def BCH_type_info(data): ... -def BCH_type_number(data): ... -def BCH_digit(data): ... -def pattern_position(version): ... -def mask_func(pattern: _MaskPattern) -> Callable[[int, int], bool]: ... -def mode_sizes_for_version(version): ... -def length_in_bits(mode, version): ... -def check_version(version) -> None: ... -def lost_point(modules): ... +def BCH_type_info(data: int) -> int: ... +def BCH_type_number(data: int) -> int: ... +def BCH_digit(data: int) -> int: ... +def pattern_position(version: int) -> list[int]: ... +def mask_func(pattern: MaskPattern) -> Callable[[int, int], bool]: ... +def mode_sizes_for_version(version: int) -> dict[_MODE, int]: ... +def length_in_bits(mode: _MODE, version: int) -> int: ... +def check_version(version: int) -> None: ... +def lost_point(modules: list[list[bool | None]]) -> int: ... def optimal_data_chunks(data: str | bytes, minimum: int = 4) -> Generator[QRData, None, None]: ... def to_bytestring(data: str | bytes) -> bytes: ... -def optimal_mode(data) -> Literal[1, 2, 4]: ... +def optimal_mode(data: bytes) -> _SupportedMode: ... class QRData: - mode: Literal[1, 2, 4] + mode: _SupportedMode data: bytes @overload - def __init__(self, data: bytes | str, mode: Literal[1, 2, 4] | None = None, check_data: Literal[True] = True) -> None: ... + def __init__(self, data: bytes | str, mode: _SupportedMode | None = None, check_data: Literal[True] = True) -> None: ... @overload - def __init__(self, data: bytes, mode: Literal[1, 2, 4] | None = None, *, check_data: Literal[False]) -> None: ... + def __init__(self, data: bytes, mode: _SupportedMode | None = None, *, check_data: Literal[False]) -> None: ... @overload - def __init__(self, data: bytes, mode: Literal[1, 2, 4] | None, check_data: Literal[False]) -> None: ... + def __init__(self, data: bytes, mode: _SupportedMode | None, check_data: Literal[False]) -> None: ... def __len__(self) -> int: ... def write(self, buffer: BitBuffer) -> None: ... class BitBuffer: - buffer: Incomplete + buffer: list[int] length: int def __init__(self) -> None: ... - def get(self, index): ... - def put(self, num, length) -> None: ... + def get(self, index: int) -> bool: ... + def put(self, num: int, length: int) -> None: ... def __len__(self) -> int: ... - def put_bit(self, bit) -> None: ... + def put_bit(self, bit: bool) -> None: ... -def create_bytes(buffer: BitBuffer, rs_blocks: list[RSBlock]): ... -def create_data(version, error_correction, data_list): ... +def create_bytes(buffer: BitBuffer, rs_blocks: list[RSBlock]) -> list[int]: ... +def create_data(version: int, error_correction: ErrorCorrect, data_list: list[QRData]) -> list[int]: ...