devstate.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. from state.pystate import PyState
  2. from uuid import UUID
  3. class DevState(PyState):
  4. """
  5. Version of PyState that allows dumping to .dot files
  6. + node id's are generated sequentially to make writing tests easier
  7. """
  8. free_id = 0
  9. def __init__(self):
  10. super().__init__()
  11. @staticmethod
  12. def new_id() -> UUID:
  13. DevState.free_id += 1
  14. return UUID(int=DevState.free_id - 1)
  15. def dump(self, path: str, png_path: str = None):
  16. """Dumps the whole MV graph to a graphviz .dot-file
  17. Args:
  18. path (str): path for .dot-file
  19. png_path (str, optional): path for .png image generated from the .dot-file. Defaults to None.
  20. """
  21. with open(path, "w") as f:
  22. f.write("digraph main {\n")
  23. for n in sorted(self.nodes):
  24. if n in self.values:
  25. x = self.values[n]
  26. if isinstance(x, tuple):
  27. x = f"{x[0]}"
  28. else:
  29. x = repr(x)
  30. f.write("\"a_%s\" [label=\"%s\"];\n" % (
  31. n.int, x.replace('"', '\\"')))
  32. else:
  33. f.write("\"a_%s\" [label=\"\"];\n" % n)
  34. for i, e in sorted(list(self.edges.items())):
  35. f.write("\"a_%s\" [label=\"e_%s\" shape=point];\n" % (i.int, i.int))
  36. f.write("\"a_%s\" -> \"a_%s\" [arrowhead=none];\n" % (e[0].int, i.int))
  37. f.write("\"a_%s\" -> \"a_%s\";\n" % (i.int, e[1].int))
  38. f.write("}")
  39. if png_path is not None:
  40. # generate png from dot-file
  41. bashCommand = f"dot -Tpng {path} -o {png_path}"
  42. import subprocess
  43. process = subprocess.Popen(
  44. bashCommand.split(), stdout=subprocess.PIPE)
  45. output, error = process.communicate()