Add winziprint/
This commit is contained in:
111
winziprint/winziprint.py
Executable file
111
winziprint/winziprint.py
Executable file
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import gc
|
||||
|
||||
import weasyprint
|
||||
import pypdf
|
||||
|
||||
|
||||
BATCH_SIZE = 10
|
||||
|
||||
|
||||
def convert(input_file_names: list[str], output_file_name: str, encoding: str = None) -> list[int]:
|
||||
# it takes roughly 100ms to generate one document
|
||||
page_nums = []
|
||||
tmp_file_names = []
|
||||
|
||||
for i in range(0, len(input_file_names), BATCH_SIZE):
|
||||
batch = input_file_names[i:i + BATCH_SIZE]
|
||||
documents = []
|
||||
for file_name in batch:
|
||||
html = weasyprint.HTML(file_name, encoding=encoding)
|
||||
doc = html.render()
|
||||
documents.append(doc)
|
||||
del html
|
||||
all_pages = [p for doc in documents for p in doc.pages]
|
||||
tmp_file_name = f'{output_file_name}.part.{i:0000}'
|
||||
documents[0].copy(all_pages).write_pdf(tmp_file_name)
|
||||
tmp_file_names.append(tmp_file_name)
|
||||
page_nums += [len(doc.pages) for doc in documents]
|
||||
del documents
|
||||
del all_pages
|
||||
gc.collect()
|
||||
|
||||
merger = pypdf.PdfWriter()
|
||||
for pdf in tmp_file_names:
|
||||
merger.append(pdf)
|
||||
os.remove(pdf)
|
||||
merger.write(output_file_name)
|
||||
merger.close()
|
||||
|
||||
return page_nums
|
||||
|
||||
|
||||
def _wrapper_convert(args: list[str], encoding: str = None) -> None:
|
||||
try:
|
||||
t0 = time.process_time()
|
||||
pages = convert(args[:-1], args[-1], encoding=encoding)
|
||||
t1 = time.process_time()
|
||||
print(f'{len(args) - 1} documents, '
|
||||
f'{sum(pages)} pages ({", ".join(str(p) for p in pages)}), '
|
||||
f'{t1 - t0:.1f} sec',
|
||||
flush=True)
|
||||
except Exception as e:
|
||||
msg = str(e).replace('\n', ' ')
|
||||
print(f'error: {msg}', flush=True)
|
||||
traceback.print_exception(e)
|
||||
|
||||
|
||||
def usage() -> None:
|
||||
print(f'usage: {sys.argv[0]} [-h] [-d DIR] [-e ENCODING] [ - | INPUT [INPUT...] OUTPUT ]\n\n'
|
||||
'options:\n'
|
||||
' -h, --help show this help message and exit\n'
|
||||
' -d, --directory set the working directory\n'
|
||||
' -e, --encoding encoding of the input files\n'
|
||||
'\n'
|
||||
' - use stdin for retrieving input and output file names (semi-colon-seperated)\n'
|
||||
' INPUT name of an html input file\n'
|
||||
' OUTPUT name of an pdf output file', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _get_arg(args: list[str], n1: str, n2: str = None) -> str:
|
||||
v = None
|
||||
for n in [n1] + (n2 and [n2] or []):
|
||||
if n in args:
|
||||
i = args.index(n)
|
||||
if i + 1 >= len(args):
|
||||
usage()
|
||||
v = args[i + 1]
|
||||
args.pop(i)
|
||||
args.pop(i)
|
||||
return v
|
||||
|
||||
|
||||
def main() -> None:
|
||||
args = sys.argv[1:]
|
||||
if len(args) == 0 or '-h' in args or '--help' in args:
|
||||
usage()
|
||||
|
||||
working_dir = _get_arg(args, '-d', '--directory')
|
||||
if working_dir:
|
||||
os.chdir(working_dir)
|
||||
encoding = _get_arg(args, '-e', '--encoding')
|
||||
|
||||
if args == ['-']:
|
||||
for line in sys.stdin:
|
||||
_wrapper_convert(line.strip().split(';'), encoding=encoding)
|
||||
elif len(args) < 2:
|
||||
usage()
|
||||
else:
|
||||
_wrapper_convert(args, encoding=encoding)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
sys.exit(0)
|
Reference in New Issue
Block a user