class Test_Lambda_Graph(Test_Helper): def setUp(self): super().setUp() self.lambda_graph = Lambda_Graph() def test_get_graph_data(self): graph_name = 'graph_I3H' self.result = self.lambda_graph.get_graph_data(graph_name) def test_get_gs_graph_by_name(self): graph = self.lambda_graph.get_gs_graph___by_name("test_save_gs_graph_____org_chart") Dev.pprint( graph.stats() ) assert graph.stats() == {'count_edges': 94, 'count_nodes': 124, 'size_puml': 14110} # def test_get_gs_graph_by_name__reload(self): # graph = self.lambda_graph.get_gs_graph___by_name('sec-9696-up' ) # Dev.pprint(graph.nodes) def test_get_gs_graph_by_type(self): graph = self.lambda_graph.get_gs_graph___by_type("keys___['FACT-47']__up___depth_3") assert graph.stats() == {'count_edges': 23, 'count_nodes': 19, 'size_puml': 2398} def test_get_gs_graph___from_user(self): user = '******' graph = GS_Graph().add_node("aaa").add_edge("aaa", "->", "bbb") self.lambda_graph.save_gs_graph(graph, user = user) graph = self.lambda_graph.get_gs_graph___from_user(user) assert graph.stats() == {'count_edges': 1, 'count_nodes': 1, 'size_puml': 90} def test_get_graph_png___by_name(self): name = "test_save_gs_graph_____org_chart" data = self.lambda_graph.get_graph_png___by_name(name) assert len(data['png_base64']) > 300000 def test_handle_lambda_event(self): command = 'last_5_graphs' payload = { "params": [command], "data": {"channel": "DDKUZTK6X"} } self.lambda_graph.handle_lambda_event(payload) def test_handle_lambda_event_raw_data(self): graph_name = 'graph_J2O' payload ={'params': ['raw_data', graph_name, 'details'], 'data': {}} self.result = self.lambda_graph.handle_lambda_event(payload) def test_send_graph_to_slack___by_type(self): result = self.lambda_graph.send_graph_to_slack___by_type("keys___['FACT-47']__up___depth_3", "DDKUZTK6X") assert result == 'image sent .... ' def test_get_last_n_graphs_of_type(self): results = self.lambda_graph.get_last_n_graphs_of_type('lambda_graph' ,10) print() for item in results: print('{0} {1} - {2}'.format(item["id"],item['value'].get('date'), item['value'].get('doc_data').get('type'))) #Dev.pprint(item) #D[graph['date']]={ "_id": _id, "graph": 'graph'} #Dev.pprint(sorted(indexed_by_date.keys(),"desc")) #list(results.values()).pop()) def test_save_graph(self): nodes = ['a','b'] edges = [('a', 'goes to','b')] extra_data = None graph_id = None # 'unit_test_test_save_graph_nodes_edges' graph_name = 'test_save_graph_nodes_edges' graph_type = 'unit-test' result = self.lambda_graph.save_graph(nodes, edges, extra_data, graph_id, graph_name, graph_type) Dev.pprint(result) def test_save_gs_graph(self): graph = GS_Graph() graph.add_node("aaa") graph.add_edge("aaa","->","bbb") result = self.lambda_graph.save_gs_graph(graph, "test_save_gs_graph", "from unit test") Dev.pprint(result) def test_render_and_save_gs_graph_____org_chart(self): graph = GS_Graph() is_a_manager_nodes = graph.api_issues.all_link_types('it_assets')['is manager of'].keys() graph.add_nodes(is_a_manager_nodes) graph.add_linked_issues_of_type('is manager of') graph.render_and_save_to_elk ("test_save_gs_graph_____org_chart", "from unit test") def test_wait_for_elk_to_index_graph(self): graph = self.lambda_graph.load_gs_graph('graph_CT6') new_name = self.lambda_graph.save_gs_graph(graph) self.result = self.lambda_graph.wait_for_elk_to_index_graph(new_name) #self.lambda_graph.save_gs_graph(graph, "test_save_gs_graph_____org_chart", "from unit test") #def test_lambda_update(self): # self.lambda_graph = Lambda('lambdas.gsbot.gsbot_graph').update()
class Graph_View: def __init__(self, graph=None): self.graph = graph self.lambda_graph = Lambda_Graph() def handle_lambda_request(self, params, slack_channel=None, team_id=None): if len(params) > 1: graph_name = params[0] view_name = params[1] self.load_graph(graph_name) if self.graph is None: slack_message( ":red_circle: in Graph View, graph not found: `{0}`". format(graph_name), [], slack_channel) else: self.render_view(view_name, slack_channel, team_id, graph_name) return self.graph def render_view(self, view_name, slack_channel=None, team_id=None, graph_name=None): if self.graph: try: method_name = "view_{0}".format(view_name) method = getattr(Graph_View, method_name) try: if slack_channel: slack_message( "Generating view `{0}` for graph with `{1}` nodes and `{2}` edges" .format(view_name, len(self.graph.nodes), len(self.graph.edges)), [], slack_channel, team_id) method(self) if slack_channel: saved_graph = Lambda_Graph().save_gs_graph( self.graph, None, "{0} - {0}".format(view_name, graph_name), slack_channel) slack_message( "Saved view `{0}` as new graph `{1}`".format( view_name, saved_graph), [], slack_channel, team_id) except Exception as error: slack_message( ":red_circle: Error executing view `{0}`".format( view_name), [{ "text": "{0}".format(error) }], slack_channel, team_id) except Exception: slack_message( ":red_circle: view not found: `{0}`".format(view_name), [], slack_channel, team_id) slack_message(self.bad_params_message(), [], slack_channel, team_id) return self def bad_params_message(self): message = ":red_circle: For the `graph` `view` command, you need to provide a view name, current options are: \n" view_names = [ func for func in dir(Graph_View) if callable(getattr(Graph_View, func)) and func.startswith("view") ] for view_name in view_names: message += " • {0} \n".format( view_name.replace('view_', '')) return message def load_graph(self, graph_name): self.graph = self.lambda_graph.get_gs_graph___by_name(graph_name) if self.graph: self.graph.reset_puml() return self def puml(self): return self.graph.puml.puml def print_puml(self): print(self.graph.puml.puml) return self # These are the views available (just create a method and it will be available for use) def view_default(self): self.graph.render_puml() return self.puml() def view_by_issue_type(self): issues = self.graph.get_nodes_issues() self.graph.puml.add_line('left to right direction') for key, issue in issues.items(): if issue: summary = issue.get('Summary') issue_type = issue.get('Issue Type') self.graph.puml.add_card(issue_type, issue_type) self.graph.puml.add_card(summary, key) self.graph.puml.add_edge(issue_type, key) self.graph.puml.enduml() return self.puml() def view_by_labels(self): issues = self.graph.get_nodes_issues() self.graph.puml.add_line('left to right direction') for key, issue in issues.items(): if issue: for label in issue.get('Labels'): summary = issue.get('Summary') self.graph.puml.add_card(summary, key) self.graph.puml.add_edge(label, key) self.graph.puml.enduml() return self.puml() def view_by_status(self): issues = self.graph.get_nodes_issues() self.graph.puml.add_line('left to right direction') anchors = [] edges = [] for key, issue in issues.items(): if issue: summary = issue.get('Summary') #summary = Misc.word_wrap_escaped(summary,30) status = issue.get('Status') self.graph.puml.add_card(summary, key) edges.append((status, key)) anchors.append(status) for anchor in list(set(anchors)): self.graph.puml.add_cloud(anchor, anchor) for edge in edges: self.graph.puml.add_edge(edge[0], edge[1]) self.graph.puml.enduml() return self.puml() def view_links(self): def on_add_node(element, title, id, original_id): issue = self.graph.issues.get(original_id) if issue: issue_links = json.dumps(issue.get('Issue Links'), indent=4) self.graph.notes.append(('right', id, issue_links)) return '{0} "{1} \\n \\n {2}" as {3}'.format( element, title, original_id, id) (self.graph.set_puml_show_key_in_text(False).set_puml_on_add_node( on_add_node).render_puml()) return self.puml() def view_no_keys(self): (self.graph.set_puml_show_key_in_text(False).set_puml_show_edge_labels( False).set_skin_param('Padding', '4').set_skin_param( 'ArrowColor', 'DarkGray').render_puml()) return self.puml() def view_schema(self): issues = self.graph.get_nodes_issues() schema = {} puml = self.graph.puml for edge in self.graph.edges: if issues[edge[0]]: from_issue_type = puml.fix_id( issues[edge[0]].get('Issue Type')) else: from_issue_type = 'NA' link_name = edge[1] if issues[edge[2]]: to_issue_type = puml.fix_id(issues[edge[2]].get('Issue Type')) else: to_issue_type = 'NA' schema_edge = (from_issue_type, link_name, to_issue_type) if schema.get(schema_edge) is None: schema[schema_edge] = { 'count': 0, 'from_issue_type': from_issue_type, 'link_name': link_name, 'to_issue_type': to_issue_type } schema.get(schema_edge)['count'] += 1 new_graph = GS_Graph() for item in schema.values(): new_graph.add_node(item.get('from_issue_type')) new_graph.add_node(item.get('to_issue_type')) new_graph.add_edge(item.get('from_issue_type'), item.get('link_name'), item.get('to_issue_type')) self.graph = new_graph self.graph.render_puml() return self.puml() def view_colors(self): issues = self.graph.get_nodes_issues() def resolve_letter(issue_type): if issue_type == 'GS-Project': return 'P', 'LightGreen' if issue_type == 'Risk': return 'R', 'LightPink' if issue_type == 'Risk Theme': return 'R', 'LightPink' if issue_type == 'GS Service': return 'S', 'LightGreen' return issue_type[0], 'lightBlue' def resolve_status_color(status): if status == 'Done': return 'black', 'LightGreen' if status == 'In Progress': return 'black', 'LightGreen' if status == 'To Do': return 'black', 'LightPink' if status == 'Open': return 'white', 'Black' if status == 'BackLog': return 'black', 'LightGray' return 'black', 'lightBlue' def on_add_node(element, title, fixed_id, original_id): issue = issues.get(original_id) if issue is None: return '\t {0} "{1}" as {2}'.format(element, title, fixed_id) issue_type = issue.get('Issue Type').strip() status = issue.get('Status') rating = issue.get('Rating') if rating: if rating == 'High' or rating == 'Critical': rating = '-' + rating else: rating = '+' + rating (letter, letter_color) = resolve_letter(issue_type) color_text, status_back = resolve_status_color(status) template = '\tclass "<size:25> {0}" as {1} << ({2},{3} ) >>{{ \n ' + \ '\t\t\t {4} | {5} | <b><color:{8}><back:{9}>{6} \n' + \ '\t\t\t----\n' + \ '\t\t\t {7} \n' + \ '\t\t}}' return template.format(title, fixed_id, letter, letter_color, original_id, issue_type, status, rating, color_text, status_back) self.graph.set_puml_show_key_in_text(False) self.graph.set_puml_on_add_node(on_add_node) self.graph.set_skin_param('ClassBackgroundColor', 'White') self.graph.set_skin_param('ClassBorderColor', 'Gray') self.graph.set_skin_param('ClassBorderThickness', '2') self.graph.set_skin_param('Shadowing', 'False') self.graph.set_skin_param('ArrowColor', 'Gray') self.graph.set_skin_param('Padding', '3') self.graph.render_puml() return self.puml() def view_top_down(self): self.graph.set_puml_direction_top_down() self.graph.render_puml() return self.puml() def view_top_down_in_blue(self): (self.graph.set_puml_direction_top_down().set_puml_show_key_in_text( False).set_puml_show_edge_labels(False).set_skin_param( 'Padding', 10).set_skin_param('DefaultFontSize', 40).set_skin_param( 'DefaultFontColor', 'white').set_skin_param( 'CardBorderColor', 'white').set_skin_param( 'CardBackgroundColor', '175B73').set_skin_param( 'CardBorderThickness', 0).set_skin_param('Shadowing', False).render_puml()) return self.puml()