Skip to content

Commit

Permalink
Complete coverage for the qrcode package
Browse files Browse the repository at this point in the history
  • Loading branch information
mjpieters committed Sep 17, 2024
1 parent d3070c5 commit 50c3950
Show file tree
Hide file tree
Showing 20 changed files with 364 additions and 293 deletions.
1 change: 0 additions & 1 deletion pyrightconfig.stricter.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
"stubs/pywin32",
"stubs/pyxdg",
"stubs/PyYAML",
"stubs/qrcode",
"stubs/redis",
"stubs/reportlab",
"stubs/requests",
Expand Down
13 changes: 10 additions & 3 deletions stubs/qrcode/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion stubs/qrcode/METADATA.toml
Original file line number Diff line number Diff line change
@@ -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"]
4 changes: 1 addition & 3 deletions stubs/qrcode/qrcode/LUT.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
from _typeshed import Incomplete

rsPoly_LUT: Incomplete
rsPoly_LUT: dict[int, list[int]]
6 changes: 4 additions & 2 deletions stubs/qrcode/qrcode/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from typing import Any

from qrcode import image as image
from qrcode.constants import (
ERROR_CORRECT_H as ERROR_CORRECT_H,
ERROR_CORRECT_L as ERROR_CORRECT_L,
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: ...
9 changes: 9 additions & 0 deletions stubs/qrcode/qrcode/_types.pyi
Original file line number Diff line number Diff line change
@@ -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]
32 changes: 17 additions & 15 deletions stubs/qrcode/qrcode/base.pyi
Original file line number Diff line number Diff line change
@@ -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]: ...
12 changes: 6 additions & 6 deletions stubs/qrcode/qrcode/console_scripts.pyi
Original file line number Diff line number Diff line change
@@ -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: ...
51 changes: 30 additions & 21 deletions stubs/qrcode/qrcode/image/base.pyi
Original file line number Diff line number Diff line change
@@ -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]]]

Expand All @@ -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]
Expand All @@ -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: ...
21 changes: 12 additions & 9 deletions stubs/qrcode/qrcode/image/pil.pyi
Original file line number Diff line number Diff line change
@@ -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: ...
24 changes: 14 additions & 10 deletions stubs/qrcode/qrcode/image/pure.pyi
Original file line number Diff line number Diff line change
@@ -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
49 changes: 32 additions & 17 deletions stubs/qrcode/qrcode/image/styledpil.pyi
Original file line number Diff line number Diff line change
@@ -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: ...
Loading

0 comments on commit 50c3950

Please sign in to comment.