From: Plom Heller Date: Sat, 4 Apr 2026 05:08:42 +0000 (+0200) Subject: Enforce code style of max 80 chars line width, consistent quotes choice. X-Git-Url: https://plomlompom.com/repos/booking/%22https:/validator.w3.org/%7B%7Bprefix%7D%7D?a=commitdiff_plain;h=4a945516910c9f39ff0e0c1c9bb0c76015a4cc85;p=bookmaker Enforce code style of max 80 chars line width, consistent quotes choice. --- diff --git a/bookmaker.py b/bookmaker.py index d524783..ce6260d 100755 --- a/bookmaker.py +++ b/bookmaker.py @@ -1,20 +1,24 @@ #!/usr/bin/env python3 """ -bookmaker.py is a helper for optimizing PDFs for the production of small self-printed, self-bound physical books. Towards this goal it offers various PDF manipulation options that may also be used indepéndently and for other purposes. +bookmaker.py helps optimizing PDFs for the production of small self-printed, +self-bound physical books; towards this goal offers various PDF manipulation +options that may also be used indepéndently and for other purposes. """ import argparse import io import os import sys + def handled_error_exit(msg): - print(f"ERROR: {msg}") + print(f'ERROR: {msg}') sys.exit(1) + try: import pypdf except ImportError: - handled_error_exit("Can't run at all without pypdf installed.") + handled_error_exit('Can\'t run at all without pypdf installed.') # some general paper geometry constants POINTS_PER_CM = 10 * 72 / 25.4 @@ -30,7 +34,7 @@ CUT_WIDTH = 1.05 * POINTS_PER_CM MIDDLE_POINT_DEPTH = 0.4 * POINTS_PER_CM INNER_SPINE_MARGIN_PER_PAGE = 1 * POINTS_PER_CM QUARTER_SCALE_FACTOR = 0.5 -PAGE_ORDER_FOR_NUP4 = (3,0,7,4,1,2,5,6) +PAGE_ORDER_FOR_NUP4 = (3, 0, 7, 4, 1, 2, 5, 6) class PageCrop: @@ -46,8 +50,10 @@ class PageCrop: self.top = float(self.top_cm) * POINTS_PER_CM zoom_horizontal = A4_WIDTH / (A4_WIDTH - self.left - self.right) zoom_vertical = A4_HEIGHT / (A4_HEIGHT - self.bottom - self.top) - if (zoom_horizontal > 1 and zoom_vertical < 1) or (zoom_horizontal < 1 and zoom_vertical > 1): - raise HandledException("-c: crops would create opposing zoom directions") + if (zoom_horizontal > 1 and zoom_vertical < 1)\ + or (zoom_horizontal < 1 and zoom_vertical > 1): + raise HandledException( + '-c: crops would create opposing zoom directions') elif zoom_horizontal + zoom_vertical > 2: self.zoom = min(zoom_horizontal, zoom_vertical) else: @@ -58,7 +64,8 @@ class PageCrop: @property def format_in_cm(self): - return f"left {self.left_cm}cm, bottom {self.bottom_cm}cm, right {self.right_cm}cm, top {self.top_cm}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): @@ -69,7 +76,10 @@ class PageCrop: return A4_HEIGHT - self.bottom - self.top def give_mirror(self): - return PageCrop(left_cm=self.right_cm, bottom_cm=self.bottom_cm, right_cm=self.left_cm, top_cm=self.top_cm) + return PageCrop(left_cm=self.right_cm, + bottom_cm=self.bottom_cm, + right_cm=self.left_cm, + top_cm=self.top_cm) class Nup4Geometry: @@ -77,8 +87,10 @@ class Nup4Geometry: def __init__(self, margin_cm): self.margin = margin_cm * POINTS_PER_CM self.shrink_for_margin = (A4_WIDTH - 2 * self.margin)/A4_WIDTH - # NB: We define spine size un-shrunk, but .shrink_for_spine is used with values shrunk for the margin, which we undo here. - spine_part_of_page = (INNER_SPINE_MARGIN_PER_PAGE / A4_HALF_WIDTH) / self.shrink_for_margin + # NB: We define spine size un-shrunk, but .shrink_for_spine is used + # with values shrunk for the margin, which we undo here. + spine_part_of_page = ((INNER_SPINE_MARGIN_PER_PAGE / A4_HALF_WIDTH) + / self.shrink_for_margin) self.shrink_for_spine = 1 - spine_part_of_page @@ -87,85 +99,138 @@ class HandledException(Exception): def parse_args(): - help_epilogue = "See README.txt for detailed usage instructions, command examples, etc." - parser = argparse.ArgumentParser(description=__doc__, epilog=help_epilogue, formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument("-i", "--input_file", action="append", required=True, help="input PDF file") - parser.add_argument("-o", "--output_file", required=True, help="output PDF file") - parser.add_argument("-p", "--page_range", action="append", help="page range, e.g., '2-9' or '3-end' or 'start-14'") - parser.add_argument("-c", "--crops", action="append", help="cm crops left, bottom, right, top – e.g., '10,10,10,10'; prefix with ':'-delimited page range to limit effect") - parser.add_argument("-r", "--rotate_page", type=int, action="append", help="rotate page of number by 90° (usable multiple times on same page!)") - parser.add_argument("-s", "--symmetry", action="store_true", help="alternate horizontal crops between odd and even pages") - parser.add_argument("-n", "--nup4", action='store_true', help="puts 4 input pages onto 1 output page, adds binding cut stencil") - parser.add_argument("-a", "--analyze", action="store_true", help="in --nup4, print lines identifying spine, page borders") - parser.add_argument("-k", "--keep_mediabox", action="store_true", help="keep non-A4 page shapes") - parser.add_argument("-m", "--print_margin", type=float, default=0.43, help="print margin for --nup4 in cm (default 0.43)") + help_epilogue = ('See README.txt for detailed usage instructions, ' + 'command examples, etc.') + parser = argparse.ArgumentParser( + description=__doc__, + epilog=help_epilogue, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('-i', + '--input_file', + action='append', + required=True, + help='input PDF file') + parser.add_argument('-o', + '--output_file', + required=True, + help='output PDF file') + parser.add_argument('-p', + '--page_range', + action='append', + help='page range, e.g. "2-9" or "3-end" or "start-14"') + parser.add_argument('-c', + '--crops', + action='append', + help=('cm crops left, bottom, right, top ' + '– e.g., "10,10,10,10"; ' + 'prefix with ":"-delimited page range ' + 'to limit effect')) + parser.add_argument('-r', + '--rotate_page', + type=int, + action='append', + help=('rotate page of number by 90° ' + '(usable multiple times on same page!)')) + parser.add_argument('-s', + '--symmetry', + action='store_true', + help=('alternate horizontal crops between odd ' + 'and even pages')) + parser.add_argument('-n', + '--nup4', + action='store_true', + help=('puts 4 input pages onto 1 output page, ' + 'adds binding cut stencil')) + parser.add_argument('-a', + '--analyze', + action='store_true', + help=('in --nup4, print lines identifying spine, ' + 'page borders')) + parser.add_argument('-k', + '--keep_mediabox', + action='store_true', + help='keep non-A4 page shapes') + parser.add_argument('-m', + '--print_margin', + type=float, + default=0.43, + help='print margin for --nup4 in cm (default 0.43)') return parser.parse_args() def validate_inputs_first_pass(args): for filename in args.input_file: if not os.path.isfile(filename): - raise HandledException(f"-i: {filename} is not a file") + raise HandledException(f'-i: {filename} is not a file') try: with open(filename, 'rb') as file: pypdf.PdfReader(file) except pypdf.errors.PdfStreamError: - raise HandledException(f"-i: cannot interpret {filename} as PDF file") + raise HandledException( + f'-i: cannot interpret {filename} as PDF file') if args.page_range: for p_string in args.page_range: - validate_page_range(p_string, "-p") + validate_page_range(p_string, '-p') if len(args.page_range) > len(args.input_file): - raise HandledException("-p: more --page_range arguments than --input_file arguments") + raise HandledException( + '-p: more --page_range arguments than --input_file arguments') if args.crops: for c_string in args.crops: initial_split = c_string.split(':') if len(initial_split) > 2: - raise HandledException(f"-c: cropping string has multiple ':': {c_string}") + raise HandledException( + f'-c: cropping string has multiple ":": {c_string}') page_range, crops = split_crops_string(c_string) - crops = crops.split(",") + crops = crops.split(',') if page_range: - validate_page_range(page_range, "-c") + validate_page_range(page_range, '-c') if len(crops) != 4: - raise HandledException(f"-c: cropping does not contain exactly three ',': {c_string}") + raise HandledException( + '-c: cropping does not contain exactly three ",": ' + + c_string) for crop in crops: try: float(crop) except ValueError: - raise HandledException(f"-c: non-number crop in: {c_string}") + raise HandledException( + f'-c: non-number crop in: {c_string}') if args.rotate_page: for r in args.rotate_page: try: int(r) except ValueError: - raise HandledException(f"-r: non-integer value: {r}") + raise HandledException(f'-r: non-integer value: {r}') if r < 1: - raise HandledException(f"-r: value must not be <1: {r}") + raise HandledException(f'-r: value must not be <1: {r}') try: float(args.print_margin) except ValueError: - raise HandledException(f"-m: non-float value: {arg.print_margin}") + raise HandledException(f'-m: non-float value: {args.print_margin}') def validate_page_range(p_string, err_msg_prefix): - prefix = f"{err_msg_prefix}: page range string" + prefix = f'{err_msg_prefix}: page range string' if '-' not in p_string: - raise HandledException(f"{prefix} lacks '-': {p_string}") - tokens = p_string.split("-") + raise HandledException(f'{prefix} lacks "-": {p_string}') + tokens = p_string.split('-') if len(tokens) > 2: - raise HandledException(f"{prefix} has too many '-': {p_string}") + raise HandledException(f'{prefix} has too many "-": {p_string}') for i, token in enumerate(tokens): - if token == "": + if token == '': continue - if i == 0 and token == "start": + if i == 0 and token == 'start': continue - if i == 1 and token == "end": + if i == 1 and token == 'end': continue try: int(token) except ValueError: - raise HandledException(f"{prefix} carries value neither integer, nor 'start', nor 'end': {p_string}") + raise HandledException( + f'{prefix} carries value neither integer, ' + f'nor "start", nor "end": {p_string}') if int(token) < 1: - raise HandledException(f"{prefix} carries page number <1: {p_string}") + raise HandledException( + f'{prefix} carries page number <1: {p_string}') start = -1 end = -1 try: @@ -174,7 +239,8 @@ def validate_page_range(p_string, err_msg_prefix): except ValueError: pass if start > 0 and end > 0 and start > end: - raise HandledException(f"{prefix} has higher start than end value: {p_string}") + raise HandledException( + f'{prefix} has higher start than end value: {p_string}') def split_crops_string(c_string): @@ -193,9 +259,9 @@ def parse_page_range(range_string, pages): end_page = len(pages) if range_string: start, end = range_string.split('-') - if not (len(start) == 0 or start == "start"): + if not (len(start) == 0 or start == 'start'): start_page = int(start) - 1 - if not (len(end) == 0 or end == "end"): + if not (len(end) == 0 or end == 'ebd'): end_page = int(end) return start_page, end_page @@ -215,36 +281,43 @@ def read_inputs_to_pagelist(args_input_file, args_page_range): for old_page_num in range(start_page, end_page): new_page_num += 1 if old_page_num >= len(reader.pages): - page = pypdf.PageObject.create_blank_page(width=A4_WIDTH, height=A4_HEIGHT) + page = pypdf.PageObject.create_blank_page(width=A4_WIDTH, + height=A4_HEIGHT) else: page = reader.pages[old_page_num] pages_to_add += [page] - print(f"-i, -p: read in {input_file} page number {old_page_num+1} as new page {new_page_num}") + print(f'-i, -p: read in {input_file} page number {old_page_num+1} ' + f'as new page {new_page_num}') return pages_to_add, opened_files def validate_inputs_second_pass(args, pages_to_add): if args.crops: for c_string in args.crops: - page_range, _= split_crops_string(c_string) + page_range, _ = split_crops_string(c_string) if page_range: start, end = parse_page_range(page_range, pages_to_add) if end > len(pages_to_add): - raise HandledException(f"-c: page range goes beyond number of pages we're building: {page_range}") + raise HandledException( + f'-c: page range goes beyond number of pages ' + f'we\'re building: {page_range}') if args.rotate_page: for r in args.rotate_page: if r > len(pages_to_add): - raise HandledException(f"-r: page number beyond number of pages we're building: {r}") + raise HandledException('-r: page number beyond number of ' + f'pages we\'re building: {r}') def rotate_pages(args_rotate_page, pages_to_add): if args_rotate_page: for rotate_page in args_rotate_page: page = pages_to_add[rotate_page - 1] - page.add_transformation(pypdf.Transformation().translate(tx=-A4_WIDTH/2, ty=-A4_HEIGHT/2)) + page.add_transformation(pypdf.Transformation().translate( + tx=-A4_WIDTH/2, ty=-A4_HEIGHT/2)) page.add_transformation(pypdf.Transformation().rotate(-90)) - page.add_transformation(pypdf.Transformation().translate(tx=A4_WIDTH/2, ty=A4_HEIGHT/2)) - print(f"-r: rotating (by 90°) page {rotate_page}") + page.add_transformation(pypdf.Transformation().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): @@ -252,15 +325,17 @@ def pad_pages_to_multiple_of_8(pages_to_add): 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(width=A4_WIDTH, height=A4_HEIGHT) + new_page = pypdf.PageObject.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 of 8, padded to {len(pages_to_add)}") + print(f'-n: number of input pages {old_len} not required multiple ' + f'of 8, padded to {len(pages_to_add)}') -def normalize_pages_to_A4(pages_to_add): +def normalize_pages_to_a4(pages_to_add): for page in pages_to_add: - if "/Rotate" in page: # TODO: preserve rotation, but in canvas? - page.rotate(360 - page["/Rotate"]) + if '/Rotate' in page: # TODO: preserve rotation, but in canvas? + page.rotate(360 - page['/Rotate']) page.mediabox.left = 0 page.mediabox.bottom = 0 page.mediabox.top = A4_HEIGHT @@ -268,16 +343,21 @@ 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): +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) if args_crops: for c_string in args_crops: page_range, crops = split_crops_string(c_string) start_page, end_page = parse_page_range(page_range, pages_to_add) - prefix = "-c, -t" if args_symmetry else "-c" - suffix = " (but alternating left and right crop between even and odd pages)" if args_symmetry else "" + prefix = '-c, -t' if args_symmetry else '-c' + suffix = (' (but alternating left and right crop ' + 'between even and odd pages)') if args_symmetry else '' page_crop = PageCrop(*[x for x in crops.split(',')]) - print(f"{prefix}: to pages {start_page + 1} to {end_page} applying crop: {page_crop.format_in_cm}{suffix}") + print(f'{prefix}: to pages {start_page + 1} to {end_page} ' + f'applying crop: {page_crop.format_in_cm}{suffix}') for page_num in range(start_page, end_page): if args_symmetry and page_num % 2: crop_at_page[page_num] = page_crop.give_mirror() @@ -285,33 +365,43 @@ def collect_per_page_crops_and_zooms(args_crops, args_keep_mediabox, args_symmet crop_at_page[page_num] = page_crop elif args_keep_mediabox: for page_num, page in enumerate(pages_to_add): - crop_at_page[page_num] = 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) + crop_at_page[page_num] = 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 def build_single_pages_output(writer, pages_to_add, crop_at_page): - print("building 1-input-page-per-output-page book") + print('building 1-input-page-per-output-page book') odd_page = True 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)) - page.add_transformation(pypdf.Transformation().scale(crop_at_page[i].zoom, crop_at_page[i].zoom)) - page.mediabox.right = crop_at_page[i].remaining_width * crop_at_page[i].zoom - page.mediabox.top = crop_at_page[i].remaining_height * crop_at_page[i].zoom + page.add_transformation(pypdf.Transformation().translate( + tx=-crop_at_page[i].left, ty=-crop_at_page[i].bottom)) + page.add_transformation(pypdf.Transformation().scale( + crop_at_page[i].zoom, crop_at_page[i].zoom)) + page.mediabox.right\ + = crop_at_page[i].remaining_width * crop_at_page[i].zoom + page.mediabox.top\ + = crop_at_page[i].remaining_height * crop_at_page[i].zoom writer.add_page(page) odd_page = not odd_page - print(f"built page number {i+1} (of {len(pages_to_add)})") + print(f'built page number {i+1} (of {len(pages_to_add)})') -def build_nup4_output(writer, pages_to_add, crop_at_page, args_print_margin, args_analyze, canvas_class): - print("-n: building 4-input-pages-per-output-page book") - print(f"-m: applying printable-area margin of {args_print_margin}cm") +def build_nup4_output(writer, + pages_to_add, + crop_at_page, + args_print_margin, + args_analyze, + canvas_class): + 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") + 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) nup4_i = 0 @@ -319,16 +409,23 @@ def build_nup4_output(writer, pages_to_add, crop_at_page, args_print_margin, arg is_front_page = True for i, page in enumerate(pages_to_add): if nup4_i == 0: - new_page = pypdf.PageObject.create_blank_page(width=A4_WIDTH, height=A4_HEIGHT) + new_page = pypdf.PageObject.create_blank_page( + width=A4_WIDTH, height=A4_HEIGHT) corrected_i = new_i_order[i] - nup4_inner_page_transform(page, crop_at_page[corrected_i], nup4_geometry, nup4_i) + nup4_inner_page_transform( + page, crop_at_page[corrected_i], nup4_geometry, nup4_i) nup4_outer_page_transform(page, nup4_geometry, nup4_i) new_page.merge_page(page) page_count += 1 - print(f"merged page number {page_count} (of {len(pages_to_add)})") + print(f'merged page number {page_count} (of {len(pages_to_add)})') nup4_i += 1 if nup4_i > 3: - ornate_nup4(writer, args_analyze, is_front_page, new_page, nup4_geometry, canvas_class) + ornate_nup4(writer, + args_analyze, + is_front_page, + new_page, + nup4_geometry, + canvas_class) writer.add_page(new_page) nup4_i = 0 is_front_page = not is_front_page @@ -355,40 +452,55 @@ def resort_pages_for_nup4(pages_to_add): def nup4_inner_page_transform(page, crop, nup4_geometry, nup4_i): - page.add_transformation(pypdf.Transformation().translate(ty=(A4_HEIGHT / crop.zoom - (A4_HEIGHT - crop.top)))) + page.add_transformation(pypdf.Transformation().translate( + ty=A4_HEIGHT / crop.zoom - (A4_HEIGHT - crop.top))) if nup4_i == 0 or nup4_i == 2: - page.add_transformation(pypdf.Transformation().translate(tx=-crop.left)) + page.add_transformation(pypdf.Transformation().translate( + tx=-crop.left)) elif nup4_i == 1 or nup4_i == 3: - page.add_transformation(pypdf.Transformation().translate(tx=(A4_WIDTH / crop.zoom - (A4_WIDTH - crop.right)))) - page.add_transformation(pypdf.Transformation().scale(crop.zoom * nup4_geometry.shrink_for_spine, crop.zoom * nup4_geometry.shrink_for_spine)) + page.add_transformation(pypdf.Transformation().translate( + tx=A4_WIDTH / crop.zoom - (A4_WIDTH - crop.right))) + page.add_transformation(pypdf.Transformation().scale( + crop.zoom * nup4_geometry.shrink_for_spine, + crop.zoom * nup4_geometry.shrink_for_spine)) if nup4_i == 2 or nup4_i == 3: - page.add_transformation(pypdf.Transformation().translate(ty=-2*nup4_geometry.margin/nup4_geometry.shrink_for_margin)) + page.add_transformation(pypdf.Transformation().translate( + ty=-2*nup4_geometry.margin/nup4_geometry.shrink_for_margin)) def nup4_outer_page_transform(page, nup4_geometry, nup4_i): - page.add_transformation(pypdf.Transformation().translate(ty=(1-nup4_geometry.shrink_for_spine)*A4_HEIGHT)) + page.add_transformation(pypdf.Transformation().translate( + ty=(1-nup4_geometry.shrink_for_spine)*A4_HEIGHT)) if nup4_i == 0 or nup4_i == 1: y_section = A4_HEIGHT page.mediabox.bottom = A4_HALF_HEIGHT - page.mediabox.top = A4_HEIGHT + page.mediabox.top = A4_HEIGHT if nup4_i == 2 or nup4_i == 3: y_section = 0 page.mediabox.bottom = 0 - page.mediabox.top = A4_HALF_HEIGHT + page.mediabox.top = A4_HALF_HEIGHT if nup4_i == 0 or nup4_i == 2: x_section = 0 - page.mediabox.left = 0 - page.mediabox.right = A4_HALF_WIDTH + page.mediabox.left = 0 + page.mediabox.right = A4_HALF_WIDTH if nup4_i == 1 or nup4_i == 3: - page.add_transformation(pypdf.Transformation().translate(tx=(1-nup4_geometry.shrink_for_spine)*A4_WIDTH)) + page.add_transformation(pypdf.Transformation().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(tx=x_section, ty=y_section)) - page.add_transformation(pypdf.Transformation().scale(QUARTER_SCALE_FACTOR, QUARTER_SCALE_FACTOR)) - - -def ornate_nup4(writer, args_analyze, is_front_page, new_page, nup4_geometry, canvas_class): + page.mediabox.left = A4_HALF_WIDTH + page.mediabox.right = A4_WIDTH + page.add_transformation(pypdf.Transformation().translate( + tx=x_section, ty=y_section)) + page.add_transformation(pypdf.Transformation().scale(QUARTER_SCALE_FACTOR, + QUARTER_SCALE_FACTOR)) + + +def ornate_nup4(writer, + args_analyze, + is_front_page, + new_page, + nup4_geometry, + canvas_class): if args_analyze: # borders packet = io.BytesIO() @@ -405,8 +517,10 @@ def ornate_nup4(writer, args_analyze, is_front_page, new_page, nup4_geometry, ca 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(nup4_geometry.shrink_for_margin, nup4_geometry.shrink_for_margin)) - new_page.add_transformation(pypdf.Transformation().translate(tx=printable_offset_x, ty=printable_offset_y)) + new_page.add_transformation(pypdf.Transformation().scale( + nup4_geometry.shrink_for_margin, nup4_geometry.shrink_for_margin)) + new_page.add_transformation(pypdf.Transformation().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 if args_analyze or is_front_page: @@ -430,8 +544,8 @@ def ornate_nup4(writer, args_analyze, is_front_page, new_page, nup4_geometry, ca def draw_cut(canvas, x_spine_limit, 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 - end_point_y = A4_HALF_HEIGHT + CUT_DEPTH * direction + middle_point_y = A4_HALF_HEIGHT + MIDDLE_POINT_DEPTH * direction + end_point_y = A4_HALF_HEIGHT + CUT_DEPTH * direction canvas.line(inner_start_x, A4_HALF_HEIGHT, x_spine_limit, end_point_y) canvas.line(x_spine_limit, end_point_y, x_spine_limit, middle_point_y) canvas.line(x_spine_limit, middle_point_y, outer_start_x, A4_HALF_HEIGHT) @@ -444,18 +558,26 @@ def main(): try: from reportlab.pdfgen.canvas import Canvas except ImportError: - raise HandledException("-n: need reportlab.pdfgen.canvas installed for --nup4") - pages_to_add, opened_files = read_inputs_to_pagelist(args.input_file, args.page_range) + raise HandledException( + '-n: need reportlab.pdfgen.canvas installed for --nup4') + pages_to_add, opened_files = read_inputs_to_pagelist(args.input_file, + args.page_range) validate_inputs_second_pass(args, pages_to_add) rotate_pages(args.rotate_page, pages_to_add) if args.nup4: 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) + 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) writer = pypdf.PdfWriter() if args.nup4: - build_nup4_output(writer, pages_to_add, crop_at_page, args.print_margin, args.analyze, Canvas) + build_nup4_output(writer, + pages_to_add, + crop_at_page, + args.print_margin, + args.analyze, + Canvas) else: build_single_pages_output(writer, pages_to_add, crop_at_page) for file in opened_files: @@ -464,7 +586,7 @@ def main(): writer.write(output_file) -if __name__ == "__main__": +if __name__ == '__main__': try: main() except HandledException as e: