Use temp dir without changing into it

Dieser Commit ist enthalten in:
Axel Svensson 2021-10-11 20:15:13 +02:00
Ursprung c499826141
Commit ba9cdb2e77

Datei anzeigen

@ -2,20 +2,21 @@
#Dependencies: python3, pdftk, gs, mv, pdfinfo #Dependencies: python3, pdftk, gs, mv, pdfinfo
import contextlib, os, queue, re, subprocess, sys, tempfile, threading, time, tkinter as tk import os, queue, re, subprocess, sys, tempfile, threading, time, tkinter as tk
signatureDir=os.path.expanduser(os.environ['PDF_SIGNATURE_DIR'] if 'PDF_SIGNATURE_DIR' in os.environ else "~/.pdf_signatures") signatureDir=os.path.expanduser(os.environ['PDF_SIGNATURE_DIR'] if 'PDF_SIGNATURE_DIR' in os.environ else "~/.pdf_signatures")
# Inspired by https://unix.stackexchange.com/a/141496 # Inspired by https://unix.stackexchange.com/a/141496
def main(filePath, pagestr=None): def main(filePath, pagestr=None):
fileAbsPath=os.path.abspath(filePath) #filePath=os.path.expanduser(filePath)
with inTmpDir(): with tempfile.TemporaryDirectory() as tempdir:
intmp=lambda fileName: os.path.join(tempdir, fileName)
# Flatten (make forms non-editable) before signing # Flatten (make forms non-editable) before signing
flatPDF=Cell(lambda: subprocess.run(['pdftk', fileAbsPath, 'output', 'flat.pdf', 'flatten'], check=True) and 'flat.pdf') flatPDF=Cell(lambda: subprocess.run(['pdftk', filePath, 'output', intmp('flat.pdf'), 'flatten'], check=True) and intmp('flat.pdf'))
# The chosen page # The chosen page
pageCount=pdfCountPages(flatPDF()) pageCount=pdfCountPages(flatPDF())
pageNumber=Cell(int(pagestr) if pagestr else pageCount) pageNumber=Cell(int(pagestr) if pagestr else pageCount)
pagePDF=Cell(lambda: subprocess.run(['pdftk', flatPDF(), 'cat', str(pageNumber()), 'output', 'page.pdf'], check=True) and 'page.pdf') pagePDF=Cell(lambda: subprocess.run(['pdftk', flatPDF(), 'cat', str(pageNumber()), 'output', intmp('page.pdf')], check=True) and intmp('page.pdf'))
pageSize=Cell(lambda: pdfGetSize(pagePDF())) pageSize=Cell(lambda: pdfGetSize(pagePDF()))
# The chosen signature # The chosen signature
signatures=[*filter(lambda x: m("^.*\.pdf$", x), os.listdir(signatureDir))] signatures=[*filter(lambda x: m("^.*\.pdf$", x), os.listdir(signatureDir))]
@ -32,22 +33,23 @@ def main(filePath, pagestr=None):
resize=1.1**signatureScale()*min(w/sw, h/sh)/3 resize=1.1**signatureScale()*min(w/sw, h/sh)/3
dx=w*signaturePositionX()/resize - sw/2 dx=w*signaturePositionX()/resize - sw/2
dy=h*(1-signaturePositionY())/resize - sh/2 dy=h*(1-signaturePositionY())/resize - sh/2
outFile=intmp('signature-positioned.pdf')
subprocess.run([ subprocess.run([
'gs', '-dBATCH', '-dNOPAUSE', '-dSAFER', '-dQUIET', 'gs', '-dBATCH', '-dNOPAUSE', '-dSAFER', '-dQUIET',
'-sOutputFile=page.signature.pdf', f'-sOutputFile={outFile}',
'-sDEVICE=pdfwrite', '-sDEVICE=pdfwrite',
f'-dDEVICEWIDTHPOINTS={w}', f'-dDEVICEHEIGHTPOINTS={h}', '-dFIXEDMEDIA', f'-dDEVICEWIDTHPOINTS={w}', f'-dDEVICEHEIGHTPOINTS={h}', '-dFIXEDMEDIA',
'-c', f'<</BeginPage{{{resize} {resize} scale {dx} {dy} translate}}>> setpagedevice', '-c', f'<</BeginPage{{{resize} {resize} scale {dx} {dy} translate}}>> setpagedevice',
'-f', signatureAbsPath(), '-f', signatureAbsPath(),
], check=True) ], check=True)
return 'page.signature.pdf' return outFile
# The signed page # The signed page
signedPagePDF=Cell(lambda: subprocess.run([ signedPagePDF=Cell(lambda: subprocess.run([
'pdftk', 'pdftk',
pagePDF(), pagePDF(),
'stamp', signaturePositionedPDF(), 'stamp', signaturePositionedPDF(),
'output', 'page.signed.pdf', 'output', intmp('signed-page.pdf'),
], check=True) and 'page.signed.pdf') ], check=True) and intmp('signed-page.pdf'))
# The signed page as PNG, for GUI use # The signed page as PNG, for GUI use
displayMaxSize=Cell((400, 800)) displayMaxSize=Cell((400, 800))
@Cell @Cell
@ -59,15 +61,16 @@ def main(filePath, pagestr=None):
@Cell @Cell
def displayPNG(): def displayPNG():
(w, h)=displaySize() (w, h)=displaySize()
outFile=intmp('display.png')
subprocess.run([ subprocess.run([
'gs', '-dBATCH', '-dNOPAUSE', '-dSAFER', '-dQUIET', 'gs', '-dBATCH', '-dNOPAUSE', '-dSAFER', '-dQUIET',
'-sOutputFile=page.display.png', f'-sOutputFile={outFile}',
'-sDEVICE=pngalpha', '-sDEVICE=pngalpha',
'-dMaxBitmap=2147483647', '-dMaxBitmap=2147483647',
f'-dDEVICEWIDTHPOINTS={w}', f'-dDEVICEHEIGHTPOINTS={h}', '-dFIXEDMEDIA', '-dPDFFitPage', f'-dDEVICEWIDTHPOINTS={w}', f'-dDEVICEHEIGHTPOINTS={h}', '-dFIXEDMEDIA', '-dPDFFitPage',
'-f', signedPagePDF(), '-f', signedPagePDF(),
], check=True) ], check=True)
return './page.display.png' return outFile
# GUI # GUI
doSign=True doSign=True
gui=True gui=True
@ -201,16 +204,16 @@ def main(filePath, pagestr=None):
root.mainloop() root.mainloop()
# End of GUI # End of GUI
if doSign: if doSign:
[ignored, pathPart1, pathPart2] = m("^(.*)(\.[Pp][Dd][Ff])$", fileAbsPath) [ignored, pathPart1, pathPart2] = m("^(.*)(\.[Pp][Dd][Ff])$", filePath)
signedFileAbsPath=f'{pathPart1}.signed{pathPart2}' signedFilePath=f'{pathPart1}.signed{pathPart2}'
if os.path.exists(signedFileAbsPath): if os.path.exists(signedFilePath):
backupFileAbsPath=f'{pathPart1}.signed.backup{time.strftime("%Y%m%d_%H%M%S")}{pathPart2}' backupFilePath=f'{pathPart1}.signed.backup{time.strftime("%Y%m%d_%H%M%S")}{pathPart2}'
subprocess.run([ subprocess.run([
'mv', 'mv',
signedFileAbsPath, signedFilePath,
backupFileAbsPath, backupFilePath,
], check=True) ], check=True)
print(f'Renamed {signedFileAbsPath} to {backupFileAbsPath}') print(f'Renamed {signedFilePath} to {backupFilePath}')
pnr=pageNumber() pnr=pageNumber()
subprocess.run([ subprocess.run([
'pdftk', 'pdftk',
@ -220,9 +223,9 @@ def main(filePath, pagestr=None):
*([f'A1-{pnr-1}'] if 1 < pnr else []), *([f'A1-{pnr-1}'] if 1 < pnr else []),
'B', 'B',
*([f'A{pnr+1}-end'] if pnr < pageCount else []), *([f'A{pnr+1}-end'] if pnr < pageCount else []),
'output', signedFileAbsPath, 'output', signedFilePath,
], check=True) ], check=True)
print(f'Signed document saved as {signedFileAbsPath}') print(f'Signed document saved as {signedFilePath}')
else: else:
print(f'Aborted') print(f'Aborted')
@ -276,16 +279,6 @@ def m(pattern, string):
ret.append(match.group(index)) ret.append(match.group(index))
return ret return ret
@contextlib.contextmanager
def inTmpDir():
olddir = os.getcwd()
with tempfile.TemporaryDirectory() as tempdir:
try:
os.chdir(tempdir)
yield
finally:
os.chdir(olddir)
def fromCmdOutput(cmd, pattern): def fromCmdOutput(cmd, pattern):
sp=subprocess.run(cmd, check=True, capture_output=True) sp=subprocess.run(cmd, check=True, capture_output=True)
result=sp.stdout.decode('utf-8') result=sp.stdout.decode('utf-8')