pdfform.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. '''
  2. Manipulation des formulaires PDF
  3. @author: olivier.massot, sept. 2017
  4. '''
  5. import codecs
  6. import subprocess
  7. from path import Path
  8. PDFTK_PATH = Path(__file__).parent.parent / r"bin\pdftk.exe"
  9. def gen_xfdf(filename, datas={}):
  10. ''' Generates a temp XFDF file suited for fill_form function, based on dict input data '''
  11. fields = []
  12. for key, value in datas.items():
  13. fields.append("""<field name="%s"><value>%s</value></field>""" % (key, _normalize(value)))
  14. tpl = """<?xml version="1.0" encoding="UTF-8"?>
  15. <xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
  16. <fields>
  17. %s
  18. </fields>
  19. </xfdf>""" % "\n\t\t\t".join(fields)
  20. filename = Path(filename)
  21. with open(filename, 'w') as f:
  22. f.write(tpl)
  23. convert_to_utf8(filename)
  24. return filename
  25. def convert_to_utf8(filename):
  26. f = codecs.open(filename, 'r', 'cp1252', errors='ignore')
  27. u = f.read() # now the contents have been transformed to a Unicode string
  28. out = codecs.open(filename, 'w', 'utf-8', errors='ignore')
  29. out.write(u) # and now the contents have been output as UTF-8
  30. f.close()
  31. out.close()
  32. def fill_form(pdfname, xfdfname, out_file, flatten=True):
  33. '''
  34. Fills a PDF form with given dict input data.
  35. Return temp file if no out_file provided.
  36. '''
  37. cmd = "%s %s fill_form %s output %s need_appearances" % (PDFTK_PATH, pdfname, xfdfname, out_file)
  38. if flatten:
  39. cmd += ' flatten'
  40. run_command(cmd, True)
  41. return out_file
  42. def check_output(*popenargs, **kwargs):
  43. if 'stdout' in kwargs:
  44. raise ValueError('stdout argument not allowed, it will be overridden.')
  45. process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
  46. output, unused_err = process.communicate()
  47. retcode = process.poll()
  48. if retcode:
  49. cmd = kwargs.get("args")
  50. if cmd is None:
  51. cmd = popenargs[0]
  52. raise subprocess.CalledProcessError(retcode, cmd)
  53. return output
  54. def _normalize(value):
  55. return str(value).replace("\"", "'").replace("<", "&lt;").replace(">", "&gt;")
  56. def run_command(command, shell=False):
  57. ''' run a system command and yield output '''
  58. p = check_output(command, shell=shell)
  59. return str(p).split('\n')