From 96787eba4ca950d22664a421c9ddbec33ecc7e78 Mon Sep 17 00:00:00 2001 From: Rob Adams Date: Thu, 28 Nov 2024 19:18:59 -0600 Subject: [PATCH 1/5] Pass exapand=True to merge_translated_page to allow 2up printing to work. --- pdfly/up2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdfly/up2.py b/pdfly/up2.py index 01b1c2a..25a1cfe 100644 --- a/pdfly/up2.py +++ b/pdfly/up2.py @@ -18,7 +18,7 @@ def main(pdf: Path, output: Path) -> None: for i in range(0, len(reader.pages) - 1, 2): lhs = reader.pages[i] rhs = reader.pages[i + 1] - lhs.merge_translated_page(rhs, float(lhs.mediabox.right), 0, True) + lhs.merge_translated_page(rhs, float(lhs.mediabox.width), 0, True, True) writer.add_page(lhs) print(str(i) + " ") sys.stdout.flush() From f28c38f936680588558d6510f70f783ef1f412bc Mon Sep 17 00:00:00 2001 From: Rob Adams Date: Thu, 28 Nov 2024 20:38:30 -0600 Subject: [PATCH 2/5] fix broken positional parameters to merge_tranlated_page by switching to keyword parameter. --- pdfly/up2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdfly/up2.py b/pdfly/up2.py index 25a1cfe..239cef9 100644 --- a/pdfly/up2.py +++ b/pdfly/up2.py @@ -18,7 +18,7 @@ def main(pdf: Path, output: Path) -> None: for i in range(0, len(reader.pages) - 1, 2): lhs = reader.pages[i] rhs = reader.pages[i + 1] - lhs.merge_translated_page(rhs, float(lhs.mediabox.width), 0, True, True) + lhs.merge_translated_page(rhs, tx=float(lhs.mediabox.width), ty=0, expand=True) writer.add_page(lhs) print(str(i) + " ") sys.stdout.flush() From 8873656207042d8e4e8f6445a5fcb341d98ab91a Mon Sep 17 00:00:00 2001 From: Rob Adams Date: Mon, 2 Dec 2024 10:07:43 -0600 Subject: [PATCH 3/5] Formatting issue from black. --- pdfly/up2.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pdfly/up2.py b/pdfly/up2.py index 239cef9..ab902b0 100644 --- a/pdfly/up2.py +++ b/pdfly/up2.py @@ -18,7 +18,9 @@ def main(pdf: Path, output: Path) -> None: for i in range(0, len(reader.pages) - 1, 2): lhs = reader.pages[i] rhs = reader.pages[i + 1] - lhs.merge_translated_page(rhs, tx=float(lhs.mediabox.width), ty=0, expand=True) + lhs.merge_translated_page( + rhs, tx=float(lhs.mediabox.width), ty=0, expand=True + ) writer.add_page(lhs) print(str(i) + " ") sys.stdout.flush() From 3ad6bb5f82fb0050003edd1b424e501af58c3011 Mon Sep 17 00:00:00 2001 From: Rob Adams Date: Mon, 2 Dec 2024 18:50:22 -0600 Subject: [PATCH 4/5] Test suite for 2-up, including test for #78. --- tests/test_up2.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 tests/test_up2.py diff --git a/tests/test_up2.py b/tests/test_up2.py new file mode 100644 index 0000000..c29467a --- /dev/null +++ b/tests/test_up2.py @@ -0,0 +1,63 @@ +import os +import pytest +from pypdf import PdfReader + +from .conftest import RESOURCES_ROOT, chdir, run_cli + + +def test_up2_fewer_args(capsys, tmp_path): + with chdir(tmp_path): + exit_code = run_cli(["2-up", str(RESOURCES_ROOT / "box.pdf")]) + assert exit_code == 2 + captured = capsys.readouterr() + assert "Missing argument" in captured.err + + +def test_up2_extra_args(capsys, tmp_path): + with chdir(tmp_path): + exit_code = run_cli( + [ + "2-up", + str(RESOURCES_ROOT / "box.pdf"), + "./out.pdf", + "./out2.pdf", + ] + ) + + assert exit_code == 2 + captured = capsys.readouterr() + assert "unexpected extra argument" in captured.err + + with chdir(tmp_path): + assert not os.path.exists("out.pdf"), f"'out.pdf' should not exist." + assert not os.path.exists("out2.pdf"), f"'out2.pdf' should not exist." + + +def test_up2_8page_file(capsys, tmp_path): + # Act + with chdir(tmp_path): + exit_code = run_cli( + [ + "2-up", + str(RESOURCES_ROOT / "input8.pdf"), + "./out.pdf", + ] + ) + captured = capsys.readouterr() + + # Assert + assert exit_code == 0, captured + assert not captured.err + in_reader = PdfReader(RESOURCES_ROOT / "input8.pdf") + out_reader = PdfReader(tmp_path / "./out.pdf") + + assert len(in_reader.pages) == 8 + assert len(out_reader.pages) == 4 + + in_width = in_reader.pages[0].mediabox.width + in_height = in_reader.pages[0].mediabox.height + out_width = out_reader.pages[0].mediabox.width + out_height = out_reader.pages[0].mediabox.height + + assert out_width == 2 * in_width # PR #78 + assert out_height == out_height From 24903096d9992db4dd98c779fd77337d02ef9d18 Mon Sep 17 00:00:00 2001 From: Rob Adams Date: Mon, 2 Dec 2024 18:53:37 -0600 Subject: [PATCH 5/5] Input file for tests. 8 pages, with a large page number near the center of each page. --- resources/input8.pdf | Bin 0 -> 14613 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/input8.pdf diff --git a/resources/input8.pdf b/resources/input8.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f11b56d8d03322e27758268247ae6a50dfcf579c GIT binary patch literal 14613 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 literal 0 HcmV?d00001