Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEP: Deprecate PdfMerger #1866

Merged
merged 1 commit into from
Jun 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 9 additions & 17 deletions pypdf/_merger.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
from ._reader import PdfReader
from ._utils import (
StrByteType,
deprecate_with_replacement,
deprecation_bookmark,
deprecation_with_replacement,
str_,
Expand Down Expand Up @@ -86,26 +87,16 @@ def __init__(self, pagedata: PageObject, src: PdfReader, id: int) -> None:

class PdfMerger:
"""
Initialize a ``PdfMerger`` object.
Use :class:`PdfWriter` instead.

``PdfMerger`` merges multiple PDFs into a single PDF.
It can concatenate, slice, insert, or any combination of the above.

See the functions :meth:`merge()<merge>` (or :meth:`append()<append>`)
and :meth:`write()<write>` for usage information.

Args:
strict: Determines whether user should be warned of all
problems and also causes some correctable problems to be fatal.
Defaults to ``False``.
fileobj: Output file. Can be a filename or any kind of
file-like object.
.. deprecated:: 5.0.0
"""

@deprecation_bookmark(bookmarks="outline")
def __init__(
self, strict: bool = False, fileobj: Union[Path, StrByteType] = ""
) -> None:
deprecate_with_replacement("PdfMerger", "PdfWriter", "5.0.0")
self.inputs: List[Tuple[Any, PdfReader]] = []
self.pages: List[Any] = []
self.output: Optional[PdfWriter] = PdfWriter()
Expand All @@ -117,6 +108,7 @@ def __init__(

def __enter__(self) -> "PdfMerger":
# There is nothing to do.
deprecate_with_replacement("PdfMerger", "PdfWriter", "5.0.0")
return self

def __exit__(
Expand Down Expand Up @@ -522,13 +514,13 @@ def _write_dests(self) -> None:
raise RuntimeError(ERR_CLOSED_WRITER)
for named_dest in self.named_dests:
page_index = None
if "/Page" in named_dest:
if "/Page" in named_dest: # deprecated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you add those comments?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked in coverage which lines where not covered, with the objective to get 100% for this file

for page_index, page in enumerate(self.pages): # noqa: B007
if page.id == named_dest["/Page"]:
named_dest[NameObject("/Page")] = page.out_pagedata
break

if page_index is not None:
if page_index is not None: # deprecated
self.output.add_named_destination_object(named_dest)

@deprecation_bookmark(bookmarks="outline")
Expand Down Expand Up @@ -606,7 +598,7 @@ def _associate_dests_to_pages(self, pages: List[_MergedPage]) -> None:
if np.get_object() == page.pagedata.get_object():
page_index = page.id

if page_index is None:
if page_index is None: # deprecated
raise ValueError(
f"Unresolved named destination '{named_dest['/Title']}'"
)
Expand Down Expand Up @@ -651,7 +643,7 @@ def find_outline_item(
# 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
if res:
if res: # deprecated
return [i] + res
elif (
oi_enum == outline_item
Expand Down
1 change: 1 addition & 0 deletions tests/test_encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ def test_read_page_from_encrypted_file_aes_256(pdffile, password):
],
)
@pytest.mark.skipif(not HAS_PYCRYPTODOME, reason="No pycryptodome")
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merge_encrypted_pdfs(names):
"""Encrypted PDFs can be merged after decryption."""
merger = pypdf.PdfMerger()
Expand Down
1 change: 1 addition & 0 deletions tests/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@ def test_bool_repr(tmp_path):

@pytest.mark.enable_socket()
@patch("pypdf._reader.logger_warning")
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_issue_997(mock_logger_warning, pdf_file_path):
url = (
"https://github.com/py-pdf/pypdf/files/8908874/"
Expand Down
27 changes: 26 additions & 1 deletion tests/test_merger.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
sys.path.append(str(PROJECT_ROOT))


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def merger_operate(merger):
pdf_path = RESOURCE_ROOT / "crazyones.pdf"
outline = RESOURCE_ROOT / "pdflatex-outline.pdf"
Expand Down Expand Up @@ -156,6 +157,7 @@ def check_outline(tmp_path):
tmp_filename = "dont_commit_merged.pdf"


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merger_operations_by_traditional_usage(tmp_path):
# Arrange
merger = PdfMerger()
Expand Down Expand Up @@ -183,6 +185,7 @@ def test_merger_operations_by_traditional_usage_with_writer(tmp_path):
check_outline(path)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merger_operations_by_semi_traditional_usage(tmp_path):
path = tmp_path / tmp_filename

Expand All @@ -207,6 +210,7 @@ def test_merger_operations_by_semi_traditional_usage_with_writer(tmp_path):
check_outline(path)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merger_operation_by_new_usage(tmp_path):
path = tmp_path / tmp_filename
with PdfMerger(fileobj=path) as merger:
Expand All @@ -226,6 +230,7 @@ def test_merger_operation_by_new_usage_with_writer(tmp_path):
check_outline(path)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merge_page_exception():
merger = pypdf.PdfMerger()
pdf_path = RESOURCE_ROOT / "crazyones.pdf"
Expand All @@ -247,6 +252,7 @@ def test_merge_page_exception_with_writer():
merger.close()


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merge_page_tuple():
merger = pypdf.PdfMerger()
pdf_path = RESOURCE_ROOT / "crazyones.pdf"
Expand All @@ -261,6 +267,7 @@ def test_merge_page_tuple_with_writer():
merger.close()


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merge_write_closed_fh():
merger = pypdf.PdfMerger()
pdf_path = RESOURCE_ROOT / "crazyones.pdf"
Expand Down Expand Up @@ -312,6 +319,7 @@ def test_merge_write_closed_fh_with_writer(pdf_file_path):


@pytest.mark.enable_socket()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_trim_outline_list(pdf_file_path):
url = "https://corpora.tika.apache.org/base/docs/govdocs1/995/995175.pdf"
name = "tika-995175.pdf"
Expand All @@ -334,6 +342,7 @@ def test_trim_outline_list_with_writer(pdf_file_path):


@pytest.mark.enable_socket()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_zoom(pdf_file_path):
url = "https://corpora.tika.apache.org/base/docs/govdocs1/994/994759.pdf"
name = "tika-994759.pdf"
Expand All @@ -356,6 +365,7 @@ def test_zoom_with_writer(pdf_file_path):


@pytest.mark.enable_socket()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_zoom_xyz_no_left(pdf_file_path):
url = "https://corpora.tika.apache.org/base/docs/govdocs1/933/933322.pdf"
name = "tika-933322.pdf"
Expand All @@ -378,6 +388,7 @@ def test_zoom_xyz_no_left_with_writer(pdf_file_path):


@pytest.mark.enable_socket()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_outline_item(pdf_file_path):
url = "https://corpora.tika.apache.org/base/docs/govdocs1/997/997511.pdf"
name = "tika-997511.pdf"
Expand All @@ -402,6 +413,7 @@ def test_outline_item_with_writer(pdf_file_path):

@pytest.mark.enable_socket()
@pytest.mark.slow()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_trim_outline(pdf_file_path):
url = "https://corpora.tika.apache.org/base/docs/govdocs1/982/982336.pdf"
name = "tika-982336.pdf"
Expand All @@ -426,6 +438,7 @@ def test_trim_outline_with_writer(pdf_file_path):

@pytest.mark.enable_socket()
@pytest.mark.slow()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test1(pdf_file_path):
url = "https://corpora.tika.apache.org/base/docs/govdocs1/923/923621.pdf"
name = "tika-923621.pdf"
Expand All @@ -450,6 +463,7 @@ def test1_with_writer(pdf_file_path):

@pytest.mark.enable_socket()
@pytest.mark.slow()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_sweep_recursion1(pdf_file_path):
# TODO: This test looks like an infinite loop.
url = "https://corpora.tika.apache.org/base/docs/govdocs1/924/924546.pdf"
Expand Down Expand Up @@ -496,6 +510,7 @@ def test_sweep_recursion1_with_writer(pdf_file_path):
),
],
)
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_sweep_recursion2(url, name, pdf_file_path):
reader = PdfReader(BytesIO(get_pdf_from_url(url, name=name)))
merger = PdfMerger()
Expand Down Expand Up @@ -525,7 +540,7 @@ def test_sweep_recursion2(url, name, pdf_file_path):
)
def test_sweep_recursion2_with_writer(url, name, pdf_file_path):
reader = PdfReader(BytesIO(get_pdf_from_url(url, name=name)))
merger = PdfMerger()
merger = PdfWriter()
merger.append(reader)
merger.write(pdf_file_path)
merger.close()
Expand All @@ -535,6 +550,7 @@ def test_sweep_recursion2_with_writer(url, name, pdf_file_path):


@pytest.mark.enable_socket()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_sweep_indirect_list_newobj_is_none(caplog, pdf_file_path):
url = "https://corpora.tika.apache.org/base/docs/govdocs1/906/906769.pdf"
name = "tika-906769.pdf"
Expand Down Expand Up @@ -565,6 +581,7 @@ def test_sweep_indirect_list_newobj_is_none_with_writer(caplog, pdf_file_path):


@pytest.mark.enable_socket()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_iss1145():
# issue with FitH destination with null param
url = "https://github.com/py-pdf/pypdf/files/9164743/file-0.pdf"
Expand All @@ -584,6 +601,7 @@ def test_iss1145_with_writer():
merger.close()


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_deprecation_bookmark_decorator_deprecationexcp():
reader = PdfReader(RESOURCE_ROOT / "outlines-with-invalid-destinations.pdf")
merger = PdfMerger()
Expand All @@ -610,6 +628,7 @@ def test_deprecation_bookmark_decorator_deprecationexcp_with_writer():
merger.merge(0, reader, import_bookmarks=True)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_deprecation_bookmark_decorator_output():
reader = PdfReader(RESOURCE_ROOT / "outlines-with-invalid-destinations.pdf")
merger = PdfMerger()
Expand All @@ -625,6 +644,7 @@ def test_deprecation_bookmark_decorator_output_with_writer():


@pytest.mark.enable_socket()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_iss1344(caplog):
url = "https://github.com/py-pdf/pypdf/files/9549001/input.pdf"
name = "iss1344.pdf"
Expand Down Expand Up @@ -663,3 +683,8 @@ def test_articles_with_writer(caplog):
r = PdfReader(b)
assert len(r.threads) == 4
assert r.threads[0].get_object()["/F"]["/P"] == r.pages[0]


def test_deprecate_pdfmerger():
with pytest.warns(DeprecationWarning), PdfMerger() as merger:
merger.append(RESOURCE_ROOT / "crazyones.pdf")
3 changes: 3 additions & 0 deletions tests/test_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ def test_overlay(pdf_file_path, base_path, overlay_path):
)
],
)
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merge_with_warning(tmp_path, url, name):
data = BytesIO(get_pdf_from_url(url, name=name))
reader = PdfReader(data)
Expand All @@ -367,6 +368,7 @@ def test_merge_with_warning(tmp_path, url, name):
)
],
)
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merge(tmp_path, url, name):
data = BytesIO(get_pdf_from_url(url, name=name))
reader = PdfReader(data)
Expand Down Expand Up @@ -565,6 +567,7 @@ def test_scale_rectangle_indirect_object():
page.scale(sx=2, sy=3)


@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_merge_output(caplog):
# Arrange
base = RESOURCE_ROOT / "Seige_of_Vicksburg_Sample_OCR.pdf"
Expand Down
2 changes: 2 additions & 0 deletions tests/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@ def test_append_pages_from_reader_append():

@pytest.mark.enable_socket()
@pytest.mark.slow()
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_sweep_indirect_references_nullobject_exception(pdf_file_path):
# TODO: Check this more closely... this looks weird
url = "https://corpora.tika.apache.org/base/docs/govdocs1/924/924666.pdf"
Expand All @@ -765,6 +766,7 @@ def test_sweep_indirect_references_nullobject_exception(pdf_file_path):
("https://github.com/py-pdf/pypdf/files/10715624/test.pdf", "iss1627.pdf"),
],
)
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_some_appends(pdf_file_path, url, name):
reader = PdfReader(BytesIO(get_pdf_from_url(url, name=name)))
# PdfMerger
Expand Down