Skip to content

Commit

Permalink
DEV: Unify mypy options and warn redundant workarounds (#2223)
Browse files Browse the repository at this point in the history
  • Loading branch information
exiledkingcc authored Oct 7, 2023
1 parent e628555 commit dfb3c03
Show file tree
Hide file tree
Showing 20 changed files with 74 additions and 72 deletions.
18 changes: 5 additions & 13 deletions .github/workflows/github-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
use-crypto-lib: ["cryptography"]
include:
- python-version: "3.6"
use-crypto-lib: "pycryptodome"
- python-version: "3.9"
use-crypto-lib: "pycryptodome"
- python-version: "3.10"
- python-version: "3.7"
use-crypto-lib: ""
steps:
- name: Update APT packages
Expand Down Expand Up @@ -94,9 +92,6 @@ jobs:
- name: Test with pytest
run: |
python -m coverage run --parallel-mode -m pytest tests -vv
- name: Test with mypy
run : |
mypy pypdf --show-error-codes --disallow-untyped-defs --disallow-incomplete-defs
- name: Upload coverage data
uses: actions/upload-artifact@v3
with:
Expand All @@ -112,12 +107,6 @@ jobs:
uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Cache Downloaded Files
id: cache-downloaded-files
uses: actions/cache@v3
with:
path: '**/tests/pdf_cache/*'
key: cache-downloaded-files
- name: Setup Python 3.11
uses: actions/setup-python@v4
with:
Expand All @@ -137,6 +126,9 @@ jobs:
run: |
echo `ruff --version`
ruff .
- name: Test with mypy
run : |
mypy pypdf
package:
name: Build & verify package
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ repos:
rev: 'v1.5.1'
hooks:
- id: mypy
additional_dependencies: [types-Pillow==10.0.0.2]
files: ^pypdf/.*
args: [--ignore-missing-imports]
10 changes: 5 additions & 5 deletions pypdf/_crypt_providers/_cryptography.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@

import secrets

from cryptography import __version__ # type: ignore[import]
from cryptography.hazmat.primitives import padding # type: ignore[import]
from cryptography.hazmat.primitives.ciphers.algorithms import AES, ARC4 # type: ignore[import]
from cryptography.hazmat.primitives.ciphers.base import Cipher # type: ignore[import]
from cryptography.hazmat.primitives.ciphers.modes import CBC, ECB # type: ignore[import]
from cryptography import __version__
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers.algorithms import AES, ARC4
from cryptography.hazmat.primitives.ciphers.base import Cipher
from cryptography.hazmat.primitives.ciphers.modes import CBC, ECB

from pypdf._crypt_providers._base import CryptBase

Expand Down
4 changes: 2 additions & 2 deletions pypdf/_crypt_providers/_fallback.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
crypt_provider = ("local_crypt_fallback", "0.0.0")


class CryptRC4(CryptBase): # type: ignore
class CryptRC4(CryptBase):
def __init__(self, key: bytes) -> None:
self.s = bytearray(range(256))
j = 0
Expand All @@ -58,7 +58,7 @@ def decrypt(self, data: bytes) -> bytes:
return self.encrypt(data)


class CryptAES(CryptBase): # type: ignore
class CryptAES(CryptBase):
def __init__(self, key: bytes) -> None:
pass

Expand Down
6 changes: 3 additions & 3 deletions pypdf/_crypt_providers/_pycryptodome.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@

import secrets

from Crypto import __version__ # type: ignore[import]
from Crypto.Cipher import AES, ARC4 # type: ignore[import]
from Crypto.Util.Padding import pad # type: ignore[import]
from Crypto import __version__
from Crypto.Cipher import AES, ARC4
from Crypto.Util.Padding import pad

from pypdf._crypt_providers._base import CryptBase

Expand Down
2 changes: 1 addition & 1 deletion pypdf/_encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def encrypt_object(self, obj: PdfObject) -> PdfObject:
obj2[key] = self.encrypt_object(value)
obj = obj2
elif isinstance(obj, ArrayObject):
obj = ArrayObject(self.encrypt_object(x) for x in obj) # type: ignore
obj = ArrayObject(self.encrypt_object(x) for x in obj)
return obj

def decrypt_object(self, obj: PdfObject) -> PdfObject:
Expand Down
2 changes: 1 addition & 1 deletion pypdf/_merger.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ def find_outline_item(
if isinstance(oi_enum, list):
# oi_enum is still an inner node
# (OutlineType, if recursive types were supported by mypy)
res = self.find_outline_item(outline_item, oi_enum) # type: ignore
res = self.find_outline_item(outline_item, oi_enum)
if res: # deprecated
return [i] + res
elif (
Expand Down
5 changes: 2 additions & 3 deletions pypdf/_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -1080,8 +1080,7 @@ def _merge_page(
if PG.ANNOTS in page:
annots = page[PG.ANNOTS]
if isinstance(annots, ArrayObject):
for ref in annots:
new_annots.append(ref)
new_annots.extend(annots)

for res in (
RES.EXT_G_STATE,
Expand Down Expand Up @@ -2323,7 +2322,7 @@ def _get_fonts(self) -> Tuple[Set[str], Set[str]]:
assert isinstance(obj, DictionaryObject)
fonts: Set[str] = set()
embedded: Set[str] = set()
fonts, embedded = _get_fonts_walk(cast(DictionaryObject, obj), fonts, embedded)
fonts, embedded = _get_fonts_walk(obj, fonts, embedded)
unembedded = fonts - embedded
return embedded, unembedded

Expand Down
4 changes: 2 additions & 2 deletions pypdf/_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

try:
# Python 3.8+: https://peps.python.org/pep-0586
from typing import Protocol # type: ignore[attr-defined]
from typing import Protocol
except ImportError:
from typing_extensions import Protocol # type: ignore[assignment,misc]
from typing_extensions import Protocol # type: ignore[assignment]

from ._utils import StrByteType, StreamType

Expand Down
14 changes: 7 additions & 7 deletions pypdf/_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ def __init__(
self._page_id2num: Optional[
Dict[Any, Any]
] = None # map page indirect_reference number to Page Number
if hasattr(stream, "mode") and "b" not in stream.mode: # type: ignore
if hasattr(stream, "mode") and "b" not in stream.mode:
logger_warning(
"PdfReader stream/file object is not in binary mode. "
"It may not be read correctly.",
Expand Down Expand Up @@ -1035,7 +1035,7 @@ def _build_outline_item(self, node: DictionaryObject) -> Optional[Destination]:
except KeyError:
if self.strict:
raise PdfReadError(f"Outline Entry Missing /Title attribute: {node!r}")
title = "" # type: ignore
title = ""

if "/A" in node:
# Action, PDFv1.7 Section 12.6 (only type GoTo supported)
Expand Down Expand Up @@ -1074,7 +1074,7 @@ def _build_outline_item(self, node: DictionaryObject) -> Optional[Destination]:
f"Removed unexpected destination {dest!r} from destination",
__name__,
)
outline_item = self._build_destination(title, None) # type: ignore
outline_item = self._build_destination(title, None)

# if outline item created, add color, format, and child count if present
if outline_item:
Expand Down Expand Up @@ -1229,7 +1229,7 @@ def _flatten(
self.flattened_pages = []

if PA.TYPE in pages:
t = pages[PA.TYPE] # type: ignore
t = pages[PA.TYPE]
# if pdf has no type, considered as a page if /Kids is missing
elif PA.KIDS not in pages:
t = "/Page"
Expand Down Expand Up @@ -1358,7 +1358,7 @@ def get_object(
idnum, generation = self.read_object_header(self.stream)
except Exception:
if hasattr(self.stream, "getbuffer"):
buf = bytes(self.stream.getbuffer()) # type: ignore
buf = bytes(self.stream.getbuffer())
else:
p = self.stream.tell()
self.stream.seek(0, 0)
Expand Down Expand Up @@ -1412,7 +1412,7 @@ def get_object(
)
else:
if hasattr(self.stream, "getbuffer"):
buf = bytes(self.stream.getbuffer()) # type: ignore
buf = bytes(self.stream.getbuffer())
else:
p = self.stream.tell()
self.stream.seek(0, 0)
Expand Down Expand Up @@ -1705,7 +1705,7 @@ def _read_standard_xref_table(self, stream: StreamType) -> None:
except Exception:
# if something wrong occurred
if hasattr(stream, "getbuffer"):
buf = bytes(stream.getbuffer()) # type: ignore
buf = bytes(stream.getbuffer())
else:
p = stream.tell()
stream.seek(0, 0)
Expand Down
8 changes: 4 additions & 4 deletions pypdf/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

try:
# Python 3.10+: https://www.python.org/dev/peps/pep-0484/
from typing import TypeAlias # type: ignore[attr-defined]
from typing import TypeAlias
except ImportError:
from typing_extensions import TypeAlias

Expand Down Expand Up @@ -461,9 +461,9 @@ def deprecation_bookmark(**aliases: str) -> Callable:
outline = a collection of outline items.
"""

def decoration(func: Callable) -> Any: # type: ignore
def decoration(func: Callable) -> Any:
@functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any: # type: ignore
def wrapper(*args: Any, **kwargs: Any) -> Any:
rename_kwargs(func.__name__, kwargs, aliases, fail=True)
return func(*args, **kwargs)

Expand All @@ -472,7 +472,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Any: # type: ignore
return decoration


def rename_kwargs( # type: ignore
def rename_kwargs(
func_name: str, kwargs: Dict[str, Any], aliases: Dict[str, str], fail: bool = False
) -> None:
"""
Expand Down
29 changes: 14 additions & 15 deletions pypdf/_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ def get_object(
return self._objects[indirect_reference - 1]
if indirect_reference.pdf != self:
raise ValueError("pdf must be self")
return self._objects[indirect_reference.idnum - 1] # type: ignore
return self._objects[indirect_reference.idnum - 1]

def getObject(self, ido: Union[int, IndirectObject]) -> PdfObject: # deprecated
"""
Expand All @@ -301,7 +301,7 @@ def _replace_object(
return self._objects[indirect_reference - 1]
if indirect_reference.pdf != self:
raise ValueError("pdf must be self")
return self._objects[indirect_reference.idnum - 1] # type: ignore
return self._objects[indirect_reference.idnum - 1]

def _add_page(
self,
Expand All @@ -327,8 +327,8 @@ def _add_page(
if page_org.pdf is not None:
other = page_org.pdf.pdf_header
if isinstance(other, str):
other = other.encode() # type: ignore
self.pdf_header = _get_max_pdf_version_header(self.pdf_header, other) # type: ignore
other = other.encode()
self.pdf_header = _get_max_pdf_version_header(self.pdf_header, other)
page[NameObject(PA.PARENT)] = self._pages
pages = cast(DictionaryObject, self.get_object(self._pages))
assert page.indirect_reference is not None
Expand Down Expand Up @@ -372,7 +372,7 @@ def set_need_appearances_writer(self, state: bool = True) -> None:
@property
def viewer_preferences(self) -> Optional[ViewerPreferences]:
"""Returns the existing ViewerPreferences as an overloaded dictionary."""
o = cast(DictionaryObject, self._root_object).get(CD.VIEWER_PREFERENCES, None)
o = self._root_object.get(CD.VIEWER_PREFERENCES, None)
if o is None:
return None
o = o.get_object()
Expand Down Expand Up @@ -624,7 +624,7 @@ def open_destination(
return create_string_object(str(oa))
elif isinstance(oa, ArrayObject):
try:
page, typ = oa[0:2] # type: ignore
page, typ = oa[0:2]
array = oa[2:]
fit = Fit(typ, tuple(array))
return Destination("OpenAction", page, fit)
Expand Down Expand Up @@ -1153,7 +1153,7 @@ def _flatten(
for attr in inheritable_page_attributes:
if attr in pages:
inherit[attr] = pages[attr]
for page in cast(ArrayObject, cast(DictionaryObject, pages)[PA.KIDS]):
for page in cast(ArrayObject, pages[PA.KIDS]):
addt = {}
if isinstance(page, IndirectObject):
addt["indirect_reference"] = page
Expand Down Expand Up @@ -1192,7 +1192,7 @@ def clone_document_from_reader(
if TK.INFO in reader.trailer:
self._info = reader.trailer[TK.INFO].clone(self).indirect_reference # type: ignore
try:
self._ID = cast(ArrayObject, reader.trailer[TK.ID].clone(self)) # type: ignore
self._ID = cast(ArrayObject, reader.trailer[TK.ID].clone(self))
except KeyError:
pass
if callable(after_page_append):
Expand Down Expand Up @@ -1333,7 +1333,7 @@ def encrypt(
def write_stream(self, stream: StreamType) -> None:
if hasattr(stream, "mode") and "b" not in stream.mode:
logger_warning(
f"File <{stream.name}> to write to is not in binary mode. " # type: ignore
f"File <{stream.name}> to write to is not in binary mode. "
"It may not be written to correctly.",
__name__,
)
Expand Down Expand Up @@ -2205,9 +2205,9 @@ def clean(content: ContentStream, images: List[str], forms: List[str]) -> None:
del content.operations[i]
elif operator == b"Do":
if (
cast(ObjectDeletionFlag, to_delete) & ObjectDeletionFlag.IMAGES
to_delete & ObjectDeletionFlag.IMAGES
and operands[0] in images
or cast(ObjectDeletionFlag, to_delete) & ObjectDeletionFlag.TEXT
or to_delete & ObjectDeletionFlag.TEXT
and operands[0] in forms
):
del content.operations[i]
Expand All @@ -2234,7 +2234,7 @@ def clean_forms(
try:
content: Any = None
if (
cast(ObjectDeletionFlag, to_delete) & ObjectDeletionFlag.IMAGES
to_delete & ObjectDeletionFlag.IMAGES
and o["/Subtype"] == "/Image"
):
content = NullObject()
Expand Down Expand Up @@ -2276,9 +2276,9 @@ def clean_forms(
content = ContentStream(content, page)
images, forms = clean_forms(page, [])

clean(cast(ContentStream, content), images, forms)
clean(content, images, forms)
if isinstance(page["/Contents"], ArrayObject):
for o in cast(ArrayObject, page["/Contents"]):
for o in page["/Contents"]:
self._objects[o.idnum - 1] = NullObject()
try:
self._objects[
Expand Down Expand Up @@ -3244,7 +3244,6 @@ def _insert_filtered_annotations(
p = self._get_cloned_page(d[0], pages, reader)
if p is not None:
anc = ano.clone(self, ignore_fields=("/D",))
anc = cast("DictionaryObject", anc)
cast("DictionaryObject", anc["/A"])[
NameObject("/D")
] = ArrayObject([p] + d[1:])
Expand Down
6 changes: 3 additions & 3 deletions pypdf/_xobj_image_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
)

try:
from typing import Literal, TypeAlias # type: ignore[attr-defined]
from typing import Literal, TypeAlias
except ImportError:
# PEP 586 introduced typing.Literal with Python 3.8
# For older Python versions, the backport typing_extensions is necessary:
from typing_extensions import Literal, TypeAlias # type: ignore[misc, assignment]
from typing_extensions import Literal, TypeAlias # type: ignore[assignment]


try:
Expand Down Expand Up @@ -94,7 +94,7 @@ def _get_imagemode(
mode_map.get(color_space) # type: ignore
or list(mode_map.values())[color_components]
or prev_mode
) # type: ignore
)
return mode, mode == "CMYK"


Expand Down
4 changes: 2 additions & 2 deletions pypdf/annotations/_markup_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
from ._base import NO_FLAGS, AnnotationDictionary

try:
from typing import TypeAlias # type: ignore[attr-defined]
from typing import TypeAlias
except ImportError:
# PEP 613 introduced typing.TypeAlias with Python 3.10
# For older Python versions, the backport typing_extensions is necessary:
from typing_extensions import TypeAlias # type: ignore[misc]
from typing_extensions import TypeAlias


Vertex: TypeAlias = Tuple[float, float]
Expand Down
Loading

0 comments on commit dfb3c03

Please sign in to comment.