Skip to content

Commit

Permalink
MAINT: Use typing.IO for file streams (#1498)
Browse files Browse the repository at this point in the history
In addition, the following changes were made:

* DEV: Add in-project virtual envs to .gitignore

Many developers (like myself) like to use virtual environments included within
the current project. These virtual environment are local development constructs
and should not be checked into source control.

This commit adds two common virtual environment directory names to the
.gitignore to avoid accidental commits from future developers.

* DEV: Include `pillow` in `requirements/dev.in`

The current contribution instructions in `docs/dev/intro.md` direct new code
contributors to install the `dev` requirements. After following that
instruction, the minimal test suite fails.

This commit adds `pillow` to  `requirements/dev.in` so that the minimal test
suite can pass on the first try so that new code contributors can start
implementing improvements with confidence.

* STY: Use official `IO` type for file streams

The Python standard library provides the `IO` type for file streams. (Source:
https://docs.python.org/3/library/typing.html#typing.IO)

This commit replaces the complex Union type of the `IO` implementations with the
official `IO` type. This will improve the accuracy of type checking in users'
IDEs.

* STY: Use standard `IO` type hint for writers

The CI system flagged some additional conflicts with the `IO` type in the writer
classes.

This commit changes the writer classes to use the standard `IO` type instead of
the union of IO implementations.
  • Loading branch information
thehale committed Dec 15, 2022
1 parent 10ab085 commit b8f787e
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 36 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -8,6 +8,10 @@ build
dist/*
__pycache__/

# in-project virtual environments
venv/
.venv/

#
.mutmut-cache
mutmut-results.*
Expand Down
7 changes: 2 additions & 5 deletions PyPDF2/_protocols.py
@@ -1,8 +1,7 @@
"""Helpers for working with PDF types."""

from io import BufferedReader, BufferedWriter, BytesIO, FileIO
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple, Union
from typing import IO, Any, Dict, List, Optional, Tuple, Union

try:
# Python 3.8+: https://peps.python.org/pep-0586
Expand Down Expand Up @@ -59,7 +58,5 @@ class PdfWriterProtocol(Protocol): # pragma: no cover
def get_object(self, indirect_reference: Any) -> Optional[PdfObjectProtocol]:
...

def write(
self, stream: Union[Path, StrByteType]
) -> Tuple[bool, Union[FileIO, BytesIO, BufferedReader, BufferedWriter]]:
def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO]:
...
11 changes: 3 additions & 8 deletions PyPDF2/_utils.py
Expand Up @@ -34,15 +34,10 @@
import warnings
from codecs import getencoder
from dataclasses import dataclass
from io import (
DEFAULT_BUFFER_SIZE,
BufferedReader,
BufferedWriter,
BytesIO,
FileIO,
)
from io import DEFAULT_BUFFER_SIZE
from os import SEEK_CUR
from typing import (
IO,
Any,
Callable,
Dict,
Expand All @@ -68,7 +63,7 @@
float, float, float, float, float, float
]

StreamType = Union[BytesIO, BufferedReader, BufferedWriter, FileIO]
StreamType = IO
StrByteType = Union[str, StreamType]

DEPR_MSG_NO_REPLACEMENT = "{} is deprecated and will be removed in PyPDF2 {}."
Expand Down
18 changes: 11 additions & 7 deletions PyPDF2/_writer.py
Expand Up @@ -38,10 +38,11 @@
import uuid
import warnings
from hashlib import md5
from io import BufferedReader, BufferedWriter, BytesIO, FileIO, IOBase
from io import BytesIO, FileIO, IOBase
from pathlib import Path
from types import TracebackType
from typing import (
IO,
Any,
Callable,
Deque,
Expand Down Expand Up @@ -962,9 +963,7 @@ def write_stream(self, stream: StreamType) -> None:
self._write_trailer(stream)
stream.write(b_(f"\nstartxref\n{xref_location}\n%%EOF\n")) # eof

def write(
self, stream: Union[Path, StrByteType]
) -> Tuple[bool, Union[FileIO, BytesIO, BufferedReader, BufferedWriter]]:
def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO]:
"""
Write the collection of pages added to this object out as a PDF file.
Expand Down Expand Up @@ -1289,7 +1288,7 @@ def add_outline_item_destination(
page_destination: Union[None, PageObject, TreeObject] = None,
parent: Union[None, TreeObject, IndirectObject] = None,
before: Union[None, TreeObject, IndirectObject] = None,
dest: Union[None, PageObject, TreeObject] = None, # deprecated
dest: Union[None, PageObject, TreeObject] = None, # deprecated
) -> IndirectObject:
if page_destination is not None and dest is not None: # deprecated
raise ValueError(
Expand Down Expand Up @@ -2483,7 +2482,9 @@ def _add_articles_thread(
pag_obj = cast("PageObject", pag.get_object())
if "/B" not in pag_obj:
pag_obj[NameObject("/B")] = ArrayObject()
cast("ArrayObject", pag_obj["/B"]).append(new_article.indirect_reference)
cast("ArrayObject", pag_obj["/B"]).append(
new_article.indirect_reference
)
current_article = cast("DictionaryObject", current_article["/N"])
if current_article == first_article:
new_article[NameObject("/N")] = new_first.indirect_reference # type: ignore
Expand Down Expand Up @@ -2674,7 +2675,10 @@ def find_outline_item(

i = 0
while o is not None:
if o.indirect_reference == outline_item or o.get("/Title", None) == outline_item:
if (
o.indirect_reference == outline_item
or o.get("/Title", None) == outline_item
):
return [i]
else:
if "/First" in o:
Expand Down
1 change: 1 addition & 0 deletions requirements/dev.in
@@ -1,4 +1,5 @@
black
pillow
pip-tools
pre-commit<2.18.0
pytest-cov
Expand Down
21 changes: 5 additions & 16 deletions requirements/dev.txt
@@ -1,6 +1,6 @@
#
# This file is autogenerated by pip-compile with python 3.7
# To update, run:
# This file is autogenerated by pip-compile with Python 3.8
# by the following command:
#
# pip-compile requirements/dev.in
#
Expand Down Expand Up @@ -38,13 +38,6 @@ identify==2.5.9
# via pre-commit
idna==3.4
# via requests
importlib-metadata==5.1.0
# via
# build
# click
# pre-commit
# pytest
# virtualenv
iniconfig==1.1.1
# via pytest
mypy-extensions==0.4.3
Expand All @@ -59,6 +52,8 @@ pathspec==0.10.3
# via black
pep517==0.13.0
# via build
pillow==9.3.0
# via -r requirements/dev.in
pip-tools==6.11.0
# via -r requirements/dev.in
platformdirs==2.6.0
Expand Down Expand Up @@ -87,12 +82,8 @@ tomli==2.0.1
# pytest
tomli-w==1.0.0
# via flit
typed-ast==1.5.4
# via black
typing-extensions==4.4.0
# via
# black
# importlib-metadata
# via black
urllib3==1.26.13
# via requests
virtualenv==20.17.1
Expand All @@ -101,8 +92,6 @@ wheel==0.38.4
# via
# -r requirements/dev.in
# pip-tools
zipp==3.11.0
# via importlib-metadata

# The following packages are considered to be unsafe in a requirements file:
# pip
Expand Down

0 comments on commit b8f787e

Please sign in to comment.