From 5a0693825a672d2f9895f83e5cdf787fdcfe4716 Mon Sep 17 00:00:00 2001 From: Holger Frey Date: Mon, 18 Feb 2019 13:51:21 +0100 Subject: [PATCH] it works --- Makefile | 63 ++++++++++++++++++ pdftools/__init__.py | 0 pdftools/cli.py | 89 +++++++++++++++++++++++++ pdftools/formfill.py | 101 ++++++++++++++++++++++++++++ pdftools/logo_imtek.png | Bin 0 -> 50000 bytes pdftools/nameplate.py | 141 ++++++++++++++++++++++++++++++++++++++++ pdftools/ruler.py | 26 ++++++++ poetry.lock | 44 +++++++++++++ pyproject.toml | 36 ++++++++++ readme.md | 43 ++++++++++++ 10 files changed, 543 insertions(+) create mode 100644 Makefile create mode 100644 pdftools/__init__.py create mode 100644 pdftools/cli.py create mode 100644 pdftools/formfill.py create mode 100644 pdftools/logo_imtek.png create mode 100644 pdftools/nameplate.py create mode 100644 pdftools/ruler.py create mode 100644 poetry.lock create mode 100644 pyproject.toml create mode 100644 readme.md diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fd52af4 --- /dev/null +++ b/Makefile @@ -0,0 +1,63 @@ +.PHONY: clean clean-test clean-pyc clean-build help +.DEFAULT_GOAL := help + +define BROWSER_PYSCRIPT +import os, webbrowser, sys + +try: + from urllib import pathname2url +except: + from urllib.request import pathname2url + +webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) +endef +export BROWSER_PYSCRIPT + +define PRINT_HELP_PYSCRIPT +import re, sys + +for line in sys.stdin: + match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) + if match: + target, help = match.groups() + print("%-20s %s" % (target, help)) +endef +export PRINT_HELP_PYSCRIPT + +BROWSER := python -c "$$BROWSER_PYSCRIPT" + +help: + @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + +clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts + +clean-build: ## remove build artifacts + rm -fr build/ + rm -fr dist/ + rm -fr .eggs/ + find . -name '*.egg-info' -exec rm -fr {} + + find . -name '*.egg' -exec rm -f {} + + +clean-pyc: ## remove Python file artifacts + find . -name '*.pyc' -exec rm -f {} + + find . -name '*.pyo' -exec rm -f {} + + find . -name '*~' -exec rm -f {} + + find . -name '__pycache__' -exec rm -fr {} + + +clean-test: ## remove test and coverage artifacts + rm -fr .tox/ + rm -f .coverage + rm -fr htmlcov/ + +lint: ## check style with flake8 + black pdftools tests + flake8 pdftools tests + +test: ## run tests quickly with the default Python + py.test -x --disable-warnings + +coverage: ## check code coverage with the default Python + coverage run --source pdftools -m pytest + coverage report -m + coverage html + $(BROWSER) htmlcov/index.html diff --git a/pdftools/__init__.py b/pdftools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pdftools/cli.py b/pdftools/cli.py new file mode 100644 index 0000000..c00c5d0 --- /dev/null +++ b/pdftools/cli.py @@ -0,0 +1,89 @@ +import click + +from reportlab.lib.units import mm + +from . import nameplate +from . import ruler + + +@click.command() +@click.argument( + "attendees", + type=click.Path( + exists=True, + file_okay=True, + dir_okay=False, + writable=False, + readable=True, + ), +) +@click.argument( + "logo", + type=click.Path( + exists=True, + file_okay=True, + dir_okay=False, + writable=False, + readable=True, + ), + required=False, +) +@click.option( + "-s", + "--size", + type=click.INT, + required=False, + default=10, + show_default="10 mm", +) +@click.option( + "-y", + "--adjust_y", + type=click.INT, + required=False, + default=0, + show_default=" 0 mm", +) +@click.option( + "-x", + "--adjust_x", + type=click.INT, + required=False, + default=0, + show_default=" 0 mm", +) +def nameplates(attendees, logo, size, adjust_x, adjust_y): + """ creates a pdf with name plate cards + + The attendees file should be a tab separated text file with no headers. Put + the company name in the first column, the given name in the second and the + last name in the third column, e.g: + + Hochimin Enterprizes \\t Jane \\t Doe \\n + + + The positioning of the optional logo file can be controlled with the + size and adjustment options. + """ + if logo is not None: + logo = nameplate.Logo(logo, size * mm, adjust_x=adjust_x, adjust_y=adjust_y) + npc = nameplate.NamePlateCards(logo) + npc.generate(attendees, show=True) + + + + +@click.command() +@click.argument( + "pdf", + type=click.Path( + exists=True, + file_okay=True, + dir_okay=False, + writable=False, + readable=True, + ), +) +def addruler(pdf): + """ adds a blue ruler overlay to a pdf file """ + ruler.ruler_overlay(pdf) diff --git a/pdftools/formfill.py b/pdftools/formfill.py new file mode 100644 index 0000000..7f8a477 --- /dev/null +++ b/pdftools/formfill.py @@ -0,0 +1,101 @@ +import pdfrw +import subprocess +import itertools +import tempfile + +from pathlib import Path +from reportlab.pdfgen import canvas +from reportlab.lib.units import mm +from reportlab.lib.pagesizes import A4 + + +def parse_text_file(text_file, ignore_first_line=True): + with open(text_file) as fh: + if ignore_first_line: + next(fh) + lines = [line.strip() for line in fh] + + parts = [line.split("\t") for line in lines if line] + return [tuple(map(str.strip, p)) for p in parts] + + +def fill(original_form, draw_function, values, output_file="filled.pdf"): + p = Path(output_file) + if p.exists(): + p.unlink() + + with tempfile.TemporaryFile() as overlay_fh: + with tempfile.TemporaryFile() as multipage_fh: + + # first create the pages with the values at the right positions + # this must be done first, because we need to know the number of + # pages + c = canvas.Canvas(overlay_fh, pagesize=A4) + for items in values: + draw_function(c, items) + c.showPage() + c.save() + overlay_fh.seek(0) + + olay = pdfrw.PdfReader(overlay_fh) + + # create a temporary pdf that has as many pages as the filled in + # values + original_form = pdfrw.PdfReader(original_form) + writer = pdfrw.PdfWriter() + for i in range(len(olay.pages)): + writer.addpages(original_form.pages) + writer.write(multipage_fh) + multipage_fh.seek(0) + + # merge the overlay and the multipage form + form = pdfrw.PdfReader(multipage_fh) + for form_page, overlay_page in zip(form.pages, olay.pages): + merge_obj = pdfrw.PageMerge() + filled = merge_obj.add(overlay_page)[0] + pdfrw.PageMerge(form_page).add(filled).render() + + # write the combined file to the output + pdfrw.PdfWriter().write(output_file, form) + subprocess.run(["open", output_file]) + + + + + + +if __name__=="__main__": + + attend = parse_text_file("teilnehmertabelle.txt") + + def create_overlay(c, item): + company, addr, name = item + c.setFont("Helvetica", 11) + c.drawString( 75*mm, 234*mm, "Universität Freiburg, IMTEK, CPI") + c.drawString(118*mm, 225*mm, "20126 N") + c.drawString( 58*mm, 216*mm, "VDK-Bestimmung in Jungbier") + + if company.startswith("Wissenschaftsförderung"): + c.setFont("Helvetica", 10) + c.drawString( 35*mm, 204*mm, f"{company}, {addr}") + if company.startswith("Wissenschaftsförderung"): + c.setFont("Helvetica", 11) + c.drawString( 35*mm, 191*mm, f"19.02.2019") + c.drawString(113*mm, 191*mm, f"10:30 Uhr") + c.drawString(150*mm, 191*mm, f"16:00 Uhr") + + c.drawString( 25.8*mm, 177.75*mm, f"X") + + c.drawString( 35*mm, 169*mm, name) + c.drawString( 35*mm, 156*mm, "Teilname Kickoff-Meeting") + + c.drawString( 37.15*mm, 134.35*mm, f"X") + c.drawString( 54*mm, 134*mm, "1") + + c.drawString( 24*mm, 82*mm, "Freiburg, den 19.02.2019") + + c.setFont("Helvetica-Bold", 12) + c.drawString( 117*mm, 100*mm, "1.000") + + #fill("form.pdf", create_overlay, attend) + ruler_overlay("form.pdf") diff --git a/pdftools/logo_imtek.png b/pdftools/logo_imtek.png new file mode 100644 index 0000000000000000000000000000000000000000..60063650b222cc55b069ab0f023950459913cb1e GIT binary patch literal 50000 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 c-k?9mic`twyj{GK9IZ"] +license = "Beerware" + +[tool.poetry.dependencies] +python = "^3.7" +reportlab = "^3.5" +pdfrw = "^0.4.0" +click = "^7.0" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" + +[tool.poetry.scripts] +nameplates = 'pdftools.cli:nameplates' +addruler = 'pdftools.cli:addruler' + +[tool.black] +line-length = 79 +py37 = true +include = '\.pyi?$' +exclude = ''' +/( + \.git + | \.tox + | \.venv + | build + | dist +)/ +''' diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..93ab292 --- /dev/null +++ b/readme.md @@ -0,0 +1,43 @@ +PDF helpers for the work at IMTEK +================================= + +This package provides some cli commands: + + - `nameplates` generate a pdf with nameplates + - `addruler` adds a blue ruler to a pdf + + + +nameplates +---------- + + Usage: nameplates [OPTIONS] ATTENDEES [LOGO] + + creates a pdf with name plate cards + + The attendees file should be a tab separated text file with no headers. + Put the company name in the first column, the given name in the second and + the last name in the third column, e.g: + + Hochimin Enterprizes \t Jane \t Doe \n + + The positioning of the optional logo file can be controlled with the size + and adjustment options. + + Options: + -s, --size INTEGER [default: (10 mm)] + -y, --adjust_y INTEGER [default: ( 0 mm)] + -x, --adjust_x INTEGER [default: ( 0 mm)] + --help Show this message and exit. + + + +addruler +-------- + + Usage: addruler [OPTIONS] PDF + + adds a blue ruler overlay to a pdf file + + Options: + --help Show this message and exit.