generateUmlDiagram.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #!/usr/bin/env python
  2. import logging
  3. import os
  4. import tempfile
  5. from zlib import adler32
  6. from subprocess import Popen, PIPE
  7. from pelican import logger
  8. def generate_uml_image(path, plantuml_code, imgformat):
  9. tf = tempfile.NamedTemporaryFile(delete=False)
  10. tf.write('@startuml\n'.encode('utf8'))
  11. tf.write(plantuml_code.encode('utf8'))
  12. tf.write('\n@enduml'.encode('utf8'))
  13. tf.flush()
  14. logger.debug("[plantuml] Temporary PlantUML source at "+(tf.name))
  15. if imgformat == 'png':
  16. imgext = ".png"
  17. outopt = "-tpng"
  18. elif imgformat == 'svg':
  19. imgext = ".svg"
  20. outopt = "-tsvg"
  21. else:
  22. logger.error("Bad uml image format '"+imgformat+"', using png")
  23. imgext = ".png"
  24. outopt = "-tpng"
  25. # make a name
  26. name = tf.name+imgext
  27. # build cmd line
  28. cmdline = ['plantuml', '-o', path, outopt, tf.name]
  29. try:
  30. logger.debug("[plantuml] About to execute "+" ".join(cmdline))
  31. p = Popen(cmdline, stdout=PIPE, stderr=PIPE)
  32. out, err = p.communicate()
  33. except Exception as exc:
  34. raise Exception('Failed to run plantuml: %s' % exc)
  35. else:
  36. if p.returncode == 0:
  37. # diagram was correctly generated, we can remove the temporary file (if not debugging)
  38. if not logger.isEnabledFor(logging.DEBUG):
  39. os.remove(tf.name)
  40. # renaming output image using an hash code, just to not pollute
  41. # output directory with a growing number of images
  42. name = os.path.join(path, os.path.basename(name))
  43. newname = os.path.join(path, "%08x" % (adler32(plantuml_code.encode()) & 0xffffffff))+imgext
  44. if os.path.exists(newname):
  45. os.remove(newname)
  46. os.rename(name, newname)
  47. return 'images/' + os.path.basename(newname)
  48. else:
  49. # the temporary file is still available as aid understanding errors
  50. raise RuntimeError('Error calling plantuml: %s' % err)