Created
May 5, 2024 07:45
-
-
Save fractal161/1cb3e31765c1d4160ba73ca92d32befb to your computer and use it in GitHub Desktop.
VGO Part Merger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ''' | |
| Utility for merging orchestra parts in a printer-friendly manner | |
| Motivation: print.mit.edu has an unfortunate quirk where only one document can | |
| be uploaded at a time. This is quite inconvenient when printing a bunch of | |
| orchestral parts because there are many instruments. | |
| Only dependencies are python and the pypdf package. Its generic usage is of the | |
| form | |
| python merge.py -i INPUT_FOLDER -o OUTPUT_FILE | |
| Further options are documented under the -h option. | |
| List of implemented features: | |
| - merges all top-level files in the specified folder | |
| - can specify the number of copies for each part | |
| List of desired features: | |
| - config file for repeated operations | |
| - better control over how to align each part's pages | |
| - download directly from sharepoint url? | |
| ''' | |
| import argparse | |
| import os | |
| from pypdf import PdfReader, PdfWriter | |
| def input_int(prompt): | |
| while True: | |
| try: | |
| result = int(input(prompt)) | |
| if result < 0: | |
| raise ValueError | |
| return result | |
| except ValueError: | |
| print('Please enter a nonnegative integer') | |
| # fancy cli thing | |
| parser = argparse.ArgumentParser( | |
| prog='parts-merger', | |
| description='merges parts') | |
| parser.add_argument('-i', '--input', | |
| required=True, | |
| help='directory containing parts to merge') | |
| parser.add_argument('-o', '--output', | |
| required=True, | |
| help='file to write merged pdf to') | |
| parser.add_argument('-c', '--config', | |
| help='load the specified configuration file') | |
| parser.add_argument('-n', '--no-blank', | |
| help='don\'t insert a blank page in front of a part if needed', | |
| action='store_true') | |
| args = parser.parse_args() | |
| if not os.path.isdir(args.input): | |
| raise ValueError('must supply a directory as input!') | |
| # for simplicity, only iterate through top-level files | |
| parts = [f for f in os.listdir(args.input) | |
| if os.path.isfile(os.path.join(args.input, f))] | |
| parts.sort() | |
| outFile = PdfWriter() | |
| # TODO: check for config file's existence | |
| should_save_config = False | |
| for part in parts: | |
| # TODO: use config file to determine copies | |
| copies = input_int(f'How many copies for {part}? ') | |
| if copies == 0: | |
| continue | |
| partFile = PdfReader(os.path.join(args.input, part)) | |
| # get page dimensions | |
| pages = partFile.pages | |
| if len(pages) == 0: | |
| print('Empty file, skipping...') | |
| continue | |
| box = partFile.pages[0].mediabox | |
| num_pages = partFile.get_num_pages() | |
| for _ in range(copies): | |
| # we use a naive approach: if the number of pages is even, do | |
| # [BLANK] [PART] [BLANK] | |
| # and if the number of pages is odd, do | |
| # [PART] [BLANK] | |
| if num_pages % 2 == 0: | |
| box = partFile.pages[0].mediabox | |
| outFile.add_blank_page(box.width, box.height) | |
| outFile.append(partFile) | |
| box = partFile.pages[-1].mediabox | |
| outFile.add_blank_page(box.width, box.height) | |
| outFile.write(args.output) | |
| outFile.close() | |
| if should_save_config: | |
| # TODO: write copy counts to config file | |
| pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment