From: Plom Heller Date: Sun, 5 Apr 2026 20:58:24 +0000 (+0200) Subject: Extend code documentation, improve some variable names. X-Git-Url: https://plomlompom.com/repos/booking/%22https:/validator.w3.org/%7Broute%7D?a=commitdiff_plain;h=1e7de62b6c858a31f7ad8f2370e1e9421e606f47;p=bookmaker Extend code documentation, improve some variable names. --- diff --git a/bookmaker.py b/bookmaker.py index edd90bb..b8d51f2 100755 --- a/bookmaker.py +++ b/bookmaker.py @@ -11,6 +11,7 @@ import sys def handled_error_exit(msg): + 'Print msg, then exit(1).' print(f'ERROR: {msg}') sys.exit(1) @@ -38,6 +39,7 @@ PAGE_ORDER_FOR_NUP4 = (3, 0, 7, 4, 1, 2, 5, 6) class PageCrop: + 'Per-page crop instructions as sizes in point and cm, and A4-zoom factor.' def __init__(self, left_cm=0, bottom_cm=0, right_cm=0, top_cm=0): self.left_cm = left_cm @@ -63,18 +65,22 @@ class PageCrop: @property def format_in_cm(self): + 'Human-readable listing of crops in cm.' return (f'left {self.left_cm}cm, bottom {self.bottom_cm}cm, ' f'right {self.right_cm}cm, top {self.top_cm}cm') @property def remaining_width(self): + "What's left of A4_WIDTH after applying width croppings." return A4_WIDTH - self.left - self.right @property def remaining_height(self): + "What's left of A4_WIDTH after applying height croppings." return A4_HEIGHT - self.bottom - self.top - def give_mirror(self): + def make_mirror(self): + 'Return PageCrop of swapped .left and .right.' return PageCrop(left_cm=self.right_cm, bottom_cm=self.bottom_cm, right_cm=self.left_cm, @@ -82,6 +88,7 @@ class PageCrop: class Nup4Geometry: + 'Nup4-specific attributes, i.e. outer-page margins, spine sizes.' def __init__(self, margin_cm): self.margin = margin_cm * POINTS_PER_CM @@ -103,6 +110,7 @@ class ArgFail(Exception): def parse_args(): + 'Collect command line arguments.' help_epilogue = ('See README.txt for detailed usage instructions, ' 'command examples, etc.') parser = argparse.ArgumentParser( @@ -316,6 +324,7 @@ def validate_ranges(args, pages_to_add): def rotate_pages(args_rotate_page, pages_to_add): + '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] @@ -328,6 +337,7 @@ def rotate_pages(args_rotate_page, pages_to_add): def pad_pages_to_multiple_of_8(pages_to_add): + '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) @@ -340,6 +350,7 @@ def pad_pages_to_multiple_of_8(pages_to_add): def normalize_pages_to_a4(pages_to_add): + 'Adjust pages_to_add .mediabox=.cropbox to A4, enact /Rotate inside that.' for page in pages_to_add: if '/Rotate' in page: # TODO: preserve rotation, but in canvas? page.rotate(360 - page['/Rotate']) @@ -350,11 +361,12 @@ def normalize_pages_to_a4(pages_to_add): page.cropbox = page.mediabox -def collect_per_page_crops_and_zooms(args_crops, - args_keep_mediabox, - args_symmetry, - pages_to_add): - crop_at_page = [PageCrop()] * len(pages_to_add) +def collect_page_croppings(args_crops, + args_keep_mediabox, + args_symmetry, + pages_to_add): + 'Calculate individual PageCrops from inputs.' + page_croppings = [PageCrop()] * len(pages_to_add) if args_crops: for c_string in args_crops: page_range, crops = split_crops_string(c_string) @@ -365,52 +377,54 @@ def collect_per_page_crops_and_zooms(args_crops, page_crop = PageCrop(*crops.split(',')) print(f'{prefix}: to pages {idx_start + 1}:{idx_after} ' f'applying crop: {page_crop.format_in_cm}{suffix}') - for page_num in range(idx_start, idx_after): - if args_symmetry and page_num % 2: - crop_at_page[page_num] = page_crop.give_mirror() + for n_page in range(idx_start, idx_after): + if args_symmetry and n_page % 2: + page_croppings[n_page] = page_crop.make_mirror() else: - crop_at_page[page_num] = page_crop + page_croppings[n_page] = page_crop elif args_keep_mediabox: - for page_num, page in enumerate(pages_to_add): - crop_at_page[page_num] = PageCrop( + for n_page, page in enumerate(pages_to_add): + page_croppings[n_page] = PageCrop( page.mediabox.left / POINTS_PER_CM, page.mediabox.bottom / POINTS_PER_CM, (0.01 + A4_WIDTH - page.mediabox.right) / POINTS_PER_CM, (0.01 + A4_HEIGHT - page.mediabox.top) / POINTS_PER_CM) - if args_symmetry and not page_num % 2: - crop_at_page[page_num] = crop_at_page[page_num].give_mirror() - return crop_at_page + if args_symmetry and not n_page % 2: + page_croppings[n_page] = page_croppings[n_page].make_mirror() + return page_croppings -def build_single_pages_output(writer, pages_to_add, crop_at_page): +def build_single_pages_output(writer, pages_to_add, page_croppings): + '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 + odd_page = True # TODO: removable? for i, page in enumerate(pages_to_add): page.add_transformation(pypdf.Transformation().translate( - tx=-crop_at_page[i].left, ty=-crop_at_page[i].bottom)) + tx=-page_croppings[i].left, ty=-page_croppings[i].bottom)) page.add_transformation(pypdf.Transformation().scale( - crop_at_page[i].zoom, crop_at_page[i].zoom)) + page_croppings[i].zoom, page_croppings[i].zoom)) page.mediabox.right\ - = crop_at_page[i].remaining_width * crop_at_page[i].zoom + = page_croppings[i].remaining_width * page_croppings[i].zoom page.mediabox.top\ - = crop_at_page[i].remaining_height * crop_at_page[i].zoom + = page_croppings[i].remaining_height * page_croppings[i].zoom writer.add_page(page) - odd_page = not odd_page + odd_page = not odd_page # TODO: removable? print(f'built page number {i+1} (of {len(pages_to_add)})') def build_nup4_output(writer, pages_to_add, - crop_at_page, + page_croppings, args_print_margin, args_analyze, canvas_class): + 'Build nup4 pages from inputs.' print('-n: building 4-input-pages-per-output-page book') print(f'-m: applying printable-area margin of {args_print_margin}cm') if args_analyze: print('-a: drawing page borders, spine limits') nup4_geometry = Nup4Geometry(args_print_margin) - pages_to_add, new_i_order = resort_pages_for_nup4(pages_to_add) + pages_to_add, old_indices = resort_pages_for_nup4(pages_to_add) nup4_i = 0 page_count = 0 is_front_page = True @@ -418,9 +432,9 @@ def build_nup4_output(writer, if nup4_i == 0: new_page = pypdf.PageObject.create_blank_page( width=A4_WIDTH, height=A4_HEIGHT) - corrected_i = new_i_order[i] + corrected_i = old_indices[i] nup4_inner_page_transform( - page, crop_at_page[corrected_i], nup4_geometry, nup4_i) + page, page_croppings[corrected_i], nup4_geometry, nup4_i) nup4_outer_page_transform(page, nup4_geometry, nup4_i) new_page.merge_page(page) page_count += 1 @@ -439,8 +453,9 @@ def build_nup4_output(writer, def resort_pages_for_nup4(pages_to_add): + 'Adapt pages_to_add towards PAGE_ORDER_FOR_NUP4.' new_page_order = [] - new_i_order = [] + old_indices = [] eight_pack = [] i = 0 n_eights = 0 @@ -452,13 +467,14 @@ def resort_pages_for_nup4(pages_to_add): if i == 8: i = 0 for n in PAGE_ORDER_FOR_NUP4: - new_i_order += [8 * n_eights + n] + old_indices += [8 * n_eights + n] new_page_order += [eight_pack[n]] n_eights += 1 - return new_page_order, new_i_order + return new_page_order, old_indices def nup4_inner_page_transform(page, crop, nup4_geometry, nup4_i): + 'Apply to page crop instructions adequate to position in nup4 geometry.' page.add_transformation(pypdf.Transformation().translate( ty=A4_HEIGHT / crop.zoom - (A4_HEIGHT - crop.top))) if nup4_i in {0, 2}: @@ -476,6 +492,7 @@ def nup4_inner_page_transform(page, crop, nup4_geometry, nup4_i): def nup4_outer_page_transform(page, nup4_geometry, nup4_i): + 'Shrink and position page into nup4_geometry as per its position nup4_i.' page.add_transformation(pypdf.Transformation().translate( ty=(1-nup4_geometry.shrink_for_spine)*A4_HEIGHT)) if nup4_i in {0, 1}: @@ -507,6 +524,7 @@ def ornate_nup4(args_analyze, new_page, nup4_geometry, canvas_class): + 'Apply nup4 line guides onto new_page.' if args_analyze: # borders packet = io.BytesIO() @@ -548,6 +566,7 @@ def ornate_nup4(args_analyze, def draw_cut(canvas, x_spine_limit, direction): + 'Into canvas draw book binding cut guide at x_spine_limit into direction.' outer_start_x = x_spine_limit - 0.5 * CUT_WIDTH * direction inner_start_x = x_spine_limit + 0.5 * CUT_WIDTH * direction middle_point_y = A4_HALF_HEIGHT + MIDDLE_POINT_DEPTH * direction @@ -558,6 +577,7 @@ def draw_cut(canvas, x_spine_limit, direction): def main(): + 'Full program run to be wrapped into ArgFail catcher.' args = parse_args() validate_args_syntax(args) if args.nup4: @@ -574,18 +594,20 @@ def main(): pad_pages_to_multiple_of_8(pages_to_add) if not args.keep_mediabox: normalize_pages_to_a4(pages_to_add) - crop_at_page = collect_per_page_crops_and_zooms( - args.crops, args.keep_mediabox, args.symmetry, pages_to_add) + page_croppings = collect_page_croppings(args.crops, + args.keep_mediabox, + args.symmetry, + pages_to_add) writer = pypdf.PdfWriter() if args.nup4: build_nup4_output(writer, pages_to_add, - crop_at_page, + page_croppings, args.print_margin, args.analyze, Canvas) else: - build_single_pages_output(writer, pages_to_add, crop_at_page) + build_single_pages_output(writer, pages_to_add, page_croppings) for file in opened_files: file.close() with open(args.output_file, 'wb') as output_file: