home · contact · privacy
Use explicit from … imports for pypdf too.
authorPlom Heller <plom@plomlompom.com>
Sun, 5 Apr 2026 23:10:28 +0000 (01:10 +0200)
committerPlom Heller <plom@plomlompom.com>
Sun, 5 Apr 2026 23:10:28 +0000 (01:10 +0200)
bookmaker.py

index 27313edb4ff287a9c64476f137467e33290b2ef7..73ab49d1f6a7cd9990810498d913a3bf9e290b44 100755 (executable)
@@ -24,7 +24,13 @@ def handled_error_exit(
 
 
 try:
-    import pypdf
+    from pypdf import (
+            PageObject as PdfPage,
+            PdfReader,
+            PdfWriter,
+            Transformation as PdfTransformation
+            )
+    from pypdf.errors import PdfStreamError
 except ImportError:
     handled_error_exit('Can\'t run at all without pypdf installed.')
 try:
@@ -307,7 +313,7 @@ def split_crops_string(
 
 def parse_page_range(
         range_string: Optional[str],
-        pages: list[pypdf.PageObject]
+        pages: list[PdfPage]
         ) -> tuple[int, int]:
     'Based on actual pages size read range_string into range limit indices.'
     idx_start = 0
@@ -324,7 +330,7 @@ def parse_page_range(
 def args_to_pagelist(
         args_input_file: list[str],
         args_page_range: list[str]
-        ) -> tuple[list[pypdf.PageObject], list[BufferedReader]]:
+        ) -> tuple[list[PdfPage], list[BufferedReader]]:
     'Follow args_input_file ranged by args_page_range into pages, open files.'
     pages_to_add = []
     opened_files = []
@@ -335,8 +341,8 @@ def args_to_pagelist(
         file = open(filename, 'rb')
         opened_files += [file]
         try:
-            reader = pypdf.PdfReader(file)
-        except pypdf.errors.PdfStreamError:
+            reader = PdfReader(file)
+        except PdfStreamError:
             for file in opened_files:
                 file.close()
             raise ArgFail('i', f'cannot interpret {filename} as PDF file')
@@ -347,8 +353,8 @@ def args_to_pagelist(
                                                     reader.pages)):
             new_page_num += 1
             if old_page_num >= len(reader.pages):
-                page = pypdf.PageObject.create_blank_page(width=A4_WIDTH,
-                                                          height=A4_HEIGHT)
+                page = PdfPage.create_blank_page(width=A4_WIDTH,
+                                                 height=A4_HEIGHT)
             else:
                 page = reader.pages[old_page_num]
             pages_to_add += [page]
@@ -359,7 +365,7 @@ def args_to_pagelist(
 
 def validate_ranges(
         args: ArgsNamespace,
-        pages_to_add: list[pypdf.PageObject]
+        pages_to_add: list[PdfPage]
         ) -> None:
     'Check command args\' ranges fit into pages_to_add count.'
     if args.crops:
@@ -380,29 +386,29 @@ def validate_ranges(
 
 def rotate_pages(
         args_rotate_page: list[int],
-        pages_to_add: list[pypdf.PageObject]
+        pages_to_add: list[PdfPage]
         ) -> None:
     'For pages_to_add page numbered in args_rotate_page, rotate by 90°.'
     if args_rotate_page:
         for rotate_page in args_rotate_page:
             page = pages_to_add[rotate_page - 1]
-            page.add_transformation(pypdf.Transformation().translate(
+            page.add_transformation(PdfTransformation().translate(
                 tx=-A4_WIDTH/2, ty=-A4_HEIGHT/2))
-            page.add_transformation(pypdf.Transformation().rotate(-90))
-            page.add_transformation(pypdf.Transformation().translate(
+            page.add_transformation(PdfTransformation().rotate(-90))
+            page.add_transformation(PdfTransformation().translate(
                 tx=A4_WIDTH/2, ty=A4_HEIGHT/2))
             print(f'-r: rotating (by 90°) page {rotate_page}')
 
 
 def pad_pages_to_multiple_of_8(
-        pages_to_add: list[pypdf.PageObject]
+        pages_to_add: list[PdfPage]
         ) -> None:
     'To pages_to_add add blank pages until its size is multiple of 8.'
     mod_to_8 = len(pages_to_add) % 8
     if mod_to_8 > 0:
         old_len = len(pages_to_add)
         for _ in range(8 - mod_to_8):
-            new_page = pypdf.PageObject.create_blank_page(
+            new_page = PdfPage.create_blank_page(
                     width=A4_WIDTH, height=A4_HEIGHT)
             pages_to_add += [new_page]
         print(f'-n: number of input pages {old_len} not required multiple '
@@ -410,7 +416,7 @@ def pad_pages_to_multiple_of_8(
 
 
 def normalize_pages_to_a4(
-        pages_to_add: list[pypdf.PageObject]
+        pages_to_add: list[PdfPage]
         ) -> None:
     'Adjust pages_to_add .mediabox=.cropbox to A4, enact /Rotate inside that.'
     for page in pages_to_add:
@@ -458,17 +464,17 @@ def collect_page_croppings(args_crops,
 
 
 def build_single_pages_output(
-        writer: pypdf.PdfWriter,
-        pages_to_add: list[pypdf.PageObject],
+        writer: PdfWriter,
+        pages_to_add: list[PdfPage],
         page_croppings: list[PageCrop]
         ) -> None:
     'On each of pages_to_add apply its page_croppings, then writer.add_page.'
     print('building 1-input-page-per-output-page book')
     odd_page = True   # TODO: removable?
     for i, page in enumerate(pages_to_add):
-        page.add_transformation(pypdf.Transformation().translate(
+        page.add_transformation(PdfTransformation().translate(
             tx=-page_croppings[i].left, ty=-page_croppings[i].bottom))
-        page.add_transformation(pypdf.Transformation().scale(
+        page.add_transformation(PdfTransformation().scale(
             page_croppings[i].zoom, page_croppings[i].zoom))
         page.mediabox.right\
             = page_croppings[i].remaining_width * page_croppings[i].zoom
@@ -480,8 +486,8 @@ def build_single_pages_output(
 
 
 def build_nup4_output(
-        writer: pypdf.PdfWriter,
-        pages_to_add: list[pypdf.PageObject],
+        writer: PdfWriter,
+        pages_to_add: list[PdfPage],
         page_croppings: list[PageCrop],
         args_print_margin: int,
         args_analyze: str,
@@ -498,7 +504,7 @@ def build_nup4_output(
     is_front_page = True
     for i, page in enumerate(pages_to_add):
         if nup4_i == 0:
-            new_page = pypdf.PageObject.create_blank_page(
+            new_page = PdfPage.create_blank_page(
                     width=A4_WIDTH, height=A4_HEIGHT)
         corrected_i = old_indices[i]
         nup4_inner_page_transform(
@@ -519,12 +525,12 @@ def build_nup4_output(
 
 
 def resort_pages_for_nup4(
-        pages_to_add: list[pypdf.PageObject]
-        ) -> tuple[list[pypdf.PageObject], list[int]]:
+        pages_to_add: list[PdfPage]
+        ) -> tuple[list[PdfPage], list[int]]:
     'Adapt pages_to_add towards PAGE_ORDER_FOR_NUP4.'
     new_page_order = []
     old_indices = []
-    eight_pack: list[pypdf.PageObject] = []
+    eight_pack: list[PdfPage] = []
     i = 0
     n_eights = 0
     for page in pages_to_add:
@@ -542,35 +548,35 @@ def resort_pages_for_nup4(
 
 
 def nup4_inner_page_transform(
-        page: pypdf.PageObject,
+        page: PdfPage,
         crop: PageCrop,
         nup4_geometry: Nup4Geometry,
         nup4_i: int
         ) -> None:
     'Apply to page crop instructions adequate to position in nup4 geometry.'
-    page.add_transformation(pypdf.Transformation().translate(
+    page.add_transformation(PdfTransformation().translate(
         ty=A4_HEIGHT / crop.zoom - (A4_HEIGHT - crop.top)))
     if nup4_i in {0, 2}:
-        page.add_transformation(pypdf.Transformation().translate(
+        page.add_transformation(PdfTransformation().translate(
             tx=-crop.left))
     elif nup4_i in {1, 3}:
-        page.add_transformation(pypdf.Transformation().translate(
+        page.add_transformation(PdfTransformation().translate(
             tx=A4_WIDTH / crop.zoom - (A4_WIDTH - crop.right)))
-    page.add_transformation(pypdf.Transformation().scale(
+    page.add_transformation(PdfTransformation().scale(
         crop.zoom * nup4_geometry.shrink_for_spine,
         crop.zoom * nup4_geometry.shrink_for_spine))
     if nup4_i in {2, 3}:
-        page.add_transformation(pypdf.Transformation().translate(
+        page.add_transformation(PdfTransformation().translate(
             ty=-2*nup4_geometry.margin/nup4_geometry.shrink_for_margin))
 
 
 def nup4_outer_page_transform(
-        page: pypdf.PageObject,
+        page: PdfPage,
         nup4_geometry: Nup4Geometry,
         nup4_i: int
         ) -> None:
     'Shrink and position page into nup4_geometry as per its position nup4_i.'
-    page.add_transformation(pypdf.Transformation().translate(
+    page.add_transformation(PdfTransformation().translate(
         ty=(1-nup4_geometry.shrink_for_spine)*A4_HEIGHT))
     if nup4_i in {0, 1}:
         y_section = A4_HEIGHT
@@ -586,21 +592,21 @@ def nup4_outer_page_transform(
         page.mediabox.left = 0
         page.mediabox.right = A4_HALF_WIDTH
     if nup4_i in {1, 3}:
-        page.add_transformation(pypdf.Transformation().translate(
+        page.add_transformation(PdfTransformation().translate(
             tx=(1-nup4_geometry.shrink_for_spine)*A4_WIDTH))
         x_section = A4_WIDTH
         page.mediabox.left = A4_HALF_WIDTH
         page.mediabox.right = A4_WIDTH
-    page.add_transformation(pypdf.Transformation().translate(
+    page.add_transformation(PdfTransformation().translate(
         tx=x_section, ty=y_section))
-    page.add_transformation(pypdf.Transformation().scale(QUARTER_SCALE_FACTOR,
-                                                         QUARTER_SCALE_FACTOR))
+    page.add_transformation(PdfTransformation().scale(QUARTER_SCALE_FACTOR,
+                                                      QUARTER_SCALE_FACTOR))
 
 
 def ornate_nup4(
         args_analyze: str,
         is_front_page: bool,
-        new_page: pypdf.PageObject,
+        new_page: PdfPage,
         nup4_geometry: Nup4Geometry,
         ) -> None:
     'Apply nup4 line guides onto new_page.'
@@ -616,13 +622,13 @@ def ornate_nup4(
         c.line(A4_HALF_WIDTH, A4_HEIGHT, A4_HALF_WIDTH, 0)
         c.line(A4_WIDTH, A4_HEIGHT, A4_WIDTH, 0)
         c.save()
-        new_pdf = pypdf.PdfReader(packet)
+        new_pdf = PdfReader(packet)
         new_page.merge_page(new_pdf.pages[0])
     printable_offset_x = nup4_geometry.margin
     printable_offset_y = nup4_geometry.margin * A4_HEIGHT / A4_WIDTH
-    new_page.add_transformation(pypdf.Transformation().scale(
+    new_page.add_transformation(PdfTransformation().scale(
         nup4_geometry.shrink_for_margin, nup4_geometry.shrink_for_margin))
-    new_page.add_transformation(pypdf.Transformation().translate(
+    new_page.add_transformation(PdfTransformation().translate(
         tx=printable_offset_x, ty=printable_offset_y))
     x_left_spine_limit = A4_HALF_WIDTH * nup4_geometry.shrink_for_spine
     x_right_spine_limit = A4_WIDTH - x_left_spine_limit
@@ -640,7 +646,7 @@ def ornate_nup4(
         draw_cut(c, x_right_spine_limit, -1)
     if args_analyze or is_front_page:
         c.save()
-        new_pdf = pypdf.PdfReader(packet)
+        new_pdf = PdfReader(packet)
         new_page.merge_page(new_pdf.pages[0])
 
 
@@ -678,7 +684,7 @@ def main(
                                             args.keep_mediabox,
                                             args.symmetry,
                                             pages_to_add)
-    writer = pypdf.PdfWriter()
+    writer = PdfWriter()
     if args.nup4:
         build_nup4_output(writer,
                           pages_to_add,