25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

138 satır
3.7 KiB

  1. import sqlite3
  2. import pydot
  3. import cgi
  4. import json
  5. import datetime
  6. import argparse
  7. import urllib2
  8. def make_name(pdu_id, origin):
  9. return "%s@%s" % (pdu_id, origin)
  10. def make_graph(pdus, room, filename_prefix):
  11. pdu_map = {}
  12. node_map = {}
  13. origins = set()
  14. colors = set(("red", "green", "blue", "yellow", "purple"))
  15. for pdu in pdus:
  16. origins.add(pdu.get("origin"))
  17. color_map = {color: color for color in colors if color in origins}
  18. colors -= set(color_map.values())
  19. color_map[None] = "black"
  20. for o in origins:
  21. if o in color_map:
  22. continue
  23. try:
  24. c = colors.pop()
  25. color_map[o] = c
  26. except:
  27. print "Run out of colours!"
  28. color_map[o] = "black"
  29. graph = pydot.Dot(graph_name="Test")
  30. for pdu in pdus:
  31. name = make_name(pdu.get("pdu_id"), pdu.get("origin"))
  32. pdu_map[name] = pdu
  33. t = datetime.datetime.fromtimestamp(
  34. float(pdu["ts"]) / 1000
  35. ).strftime('%Y-%m-%d %H:%M:%S,%f')
  36. label = (
  37. "<"
  38. "<b>%(name)s </b><br/>"
  39. "Type: <b>%(type)s </b><br/>"
  40. "State key: <b>%(state_key)s </b><br/>"
  41. "Content: <b>%(content)s </b><br/>"
  42. "Time: <b>%(time)s </b><br/>"
  43. "Depth: <b>%(depth)s </b><br/>"
  44. ">"
  45. ) % {
  46. "name": name,
  47. "type": pdu.get("pdu_type"),
  48. "state_key": pdu.get("state_key"),
  49. "content": cgi.escape(json.dumps(pdu.get("content")), quote=True),
  50. "time": t,
  51. "depth": pdu.get("depth"),
  52. }
  53. node = pydot.Node(
  54. name=name,
  55. label=label,
  56. color=color_map[pdu.get("origin")]
  57. )
  58. node_map[name] = node
  59. graph.add_node(node)
  60. for pdu in pdus:
  61. start_name = make_name(pdu.get("pdu_id"), pdu.get("origin"))
  62. for i, o in pdu.get("prev_pdus", []):
  63. end_name = make_name(i, o)
  64. if end_name not in node_map:
  65. print "%s not in nodes" % end_name
  66. continue
  67. edge = pydot.Edge(node_map[start_name], node_map[end_name])
  68. graph.add_edge(edge)
  69. # Add prev_state edges, if they exist
  70. if pdu.get("prev_state_id") and pdu.get("prev_state_origin"):
  71. prev_state_name = make_name(
  72. pdu.get("prev_state_id"), pdu.get("prev_state_origin")
  73. )
  74. if prev_state_name in node_map:
  75. state_edge = pydot.Edge(
  76. node_map[start_name], node_map[prev_state_name],
  77. style='dotted'
  78. )
  79. graph.add_edge(state_edge)
  80. graph.write('%s.dot' % filename_prefix, format='raw', prog='dot')
  81. graph.write_png("%s.png" % filename_prefix, prog='dot')
  82. graph.write_svg("%s.svg" % filename_prefix, prog='dot')
  83. def get_pdus(host, room):
  84. transaction = json.loads(
  85. urllib2.urlopen(
  86. "http://%s/context/%s/" % (host, room)
  87. ).read()
  88. )
  89. return transaction["pdus"]
  90. if __name__ == "__main__":
  91. parser = argparse.ArgumentParser(
  92. description="Generate a PDU graph for a given room by talking "
  93. "to the given homeserver to get the list of PDUs. \n"
  94. "Requires pydot."
  95. )
  96. parser.add_argument(
  97. "-p", "--prefix", dest="prefix",
  98. help="String to prefix output files with"
  99. )
  100. parser.add_argument('host')
  101. parser.add_argument('room')
  102. args = parser.parse_args()
  103. host = args.host
  104. room = args.room
  105. prefix = args.prefix if args.prefix else "%s_graph" % (room)
  106. pdus = get_pdus(host, room)
  107. make_graph(pdus, room, prefix)