''' Manipulation des formulaires PDF @author: olivier.massot, sept. 2017 ''' import codecs import subprocess from path import Path PDFTK_PATH = Path(__file__).parent.parent / r"bin\pdftk.exe" def gen_xfdf(filename, datas={}): ''' Generates a temp XFDF file suited for fill_form function, based on dict input data ''' fields = [] for key, value in datas.items(): fields.append("""%s""" % (key, _normalize(value))) tpl = """ %s """ % "\n\t\t\t".join(fields) filename = Path(filename) with open(filename, 'w') as f: f.write(tpl) convert_to_utf8(filename) return filename def convert_to_utf8(filename): f = codecs.open(filename, 'r', 'cp1252', errors='ignore') u = f.read() # now the contents have been transformed to a Unicode string out = codecs.open(filename, 'w', 'utf-8', errors='ignore') out.write(u) # and now the contents have been output as UTF-8 f.close() out.close() def fill_form(pdfname, xfdfname, out_file, flatten=True): ''' Fills a PDF form with given dict input data. Return temp file if no out_file provided. ''' cmd = "%s %s fill_form %s output %s need_appearances" % (PDFTK_PATH, pdfname, xfdfname, out_file) if flatten: cmd += ' flatten' run_command(cmd, True) return out_file def check_output(*popenargs, **kwargs): if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise subprocess.CalledProcessError(retcode, cmd) return output def _normalize(value): return str(value).replace("\"", "'").replace("<", "<").replace(">", ">") def run_command(command, shell=False): ''' run a system command and yield output ''' p = check_output(command, shell=shell) return str(p).split('\n')