Skip to content

Commit daf98d3

Browse files
author
Lennart
authored
clearer feedback (exception) when there is no data (#11)
1 parent 4c6aec1 commit daf98d3

3 files changed

Lines changed: 40 additions & 26 deletions

File tree

notebooks/process_analysis.ipynb

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,27 @@
2323
},
2424
{
2525
"cell_type": "raw",
26+
"metadata": {
27+
"collapsed": false
28+
},
2629
"source": [
2730
"# Status Transitions graph\n",
2831
"\n",
29-
"Display a directed graph of status transitions of the issues data from an issue tracker (e.g., Jira).\n",
32+
"Display a directed graph of status transitions of the issues data from an issue tracker.\n",
3033
"\n",
3134
"This graph can give an overview like a value stream map and highlights potential waste like delays and rework.\n",
3235
"\n",
33-
"> **_NOTE:_** Requires [graphviz](https://graphviz.org/download/) to be installed locally."
34-
],
35-
"metadata": {
36-
"collapsed": false
37-
}
36+
"> **_NOTE:_** Requires [graphviz](https://graphviz.org/download/) to be installed locally.\n",
37+
"\n",
38+
"## How to interpret the graph:\n",
39+
"- Each node represents a status of an issue.\n",
40+
"- The color of the node represents the category of the status (e.g., To Do, In Progress, Done).\n",
41+
"- Each edge represents a transition from one status to another.\n",
42+
"- The number of times that transition has occurred is shown on the edge, and the thickness of the edge is proportional to the number of transitions.\n",
43+
"\n",
44+
"Issue tracker tested: JIRA.\n",
45+
"Other DevLake plugins might not provide the necessary data to generate the graph. An error will be shown if the data is not available."
46+
]
3847
},
3948
{
4049
"cell_type": "code",
@@ -52,22 +61,26 @@
5261
"from playground.process_analysis.status_transition_graph_vistualizer import StatusTransitionGraphVisualizer, StatisticLabelConfig\n",
5362
"from playground.process_analysis.utils.status_transition_data_generator import generate_random_status_changes\n",
5463
"\n",
64+
"# Connection to the devlake database\n",
65+
"DB_URL = \"mysql://merico:merico@127.0.0.1:3306/lake\"\n",
66+
"# Specify the filter for the issues to be included in the graph\n",
67+
"ISSUE_FILTER = IssueFilter(\n",
68+
" # Example usage:\n",
69+
" # issue_type = \"Story\",\n",
70+
" # from_date = pd.Timestamp(datetime.strptime(\"2020-01-01\", \"%Y-%m-%d\"))\n",
71+
")\n",
72+
"# For demo purposes, the following flag can be set to true to generate some random data\n",
73+
"USE_DEMO_DATA = False\n",
5574
"\n",
56-
"DB_URL = \"mysql://root:admin@127.0.0.1:3306/lake\"\n",
5775
"\n",
5876
"if not StatusTransitionGraphVisualizer.is_dot_executable_available():\n",
5977
" print(\"dot executable not found, please install graphviz\")\n",
6078
"\n",
61-
"issue_filter = IssueFilter(\n",
62-
" # Example usage:\n",
63-
" # issue_type = \"Story\",\n",
64-
" # from_date = pd.Timestamp(datetime.strptime(\"2000-01-01\", \"%Y-%m-%d\"))\n",
65-
") \n",
66-
"process_graph = StatusTransitionGraph.from_database(create_db_engine(DB_URL), issue_filter=issue_filter)\n",
67-
"\n",
68-
"# For demo purpose, enable the following lines to generate some random data\n",
69-
"# data_frame = generate_random_status_changes(5000)\n",
70-
"# process_graph = StatusTransitionGraph.from_data_frame(data_frame, issue_filter=issue_filter)\n",
79+
"if not USE_DEMO_DATA:\n",
80+
" process_graph = StatusTransitionGraph.from_database(create_db_engine(DB_URL), issue_filter=ISSUE_FILTER)\n",
81+
"else:\n",
82+
" data_frame = generate_random_status_changes(5000)\n",
83+
" process_graph = StatusTransitionGraph.from_data_frame(data_frame, issue_filter=ISSUE_FILTER)\n",
7184
"\n",
7285
"svg = StatusTransitionGraphVisualizer().visualize(process_graph, threshold=0.99, label_statistic = StatisticLabelConfig.MEDIAN)\n",
7386
"display(svg)"
@@ -116,7 +129,7 @@
116129
"name": "python",
117130
"nbconvert_exporter": "python",
118131
"pygments_lexer": "ipython3",
119-
"version": "3.12.1"
132+
"version": "3.12.2"
120133
}
121134
},
122135
"nbformat": 4,

playground/process_analysis/status_transition_graph.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,11 @@ def from_data_frame(cls, df: pd.DataFrame, issue_filter: IssueFilter | None = No
9898
Note: The DataFrame must have a column for each field in the StatusChange class.
9999
"""
100100

101-
process_graph: StatusTransitionGraph = cls()
102-
103101
if df.empty:
104-
return process_graph
102+
raise ValueError("Provided DataFrame is empty" +
103+
"no status transitions in the 'issue_changelogs' table were found.")
104+
105+
process_graph: StatusTransitionGraph = cls()
105106

106107
df = df.copy().sort_values(by=["issue_key", "changed_date"], ascending=True)
107108

tests/process_analysis/test_status_transition_graph.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16+
import pytest
1617
from datetime import datetime
1718

1819
import pandas as pd
@@ -22,10 +23,9 @@
2223

2324

2425
def test_empty_status_transition_graph():
25-
result = StatusTransitionGraph.from_data_frame(pd.DataFrame([]))
26-
assert result.total_transition_count == 0
27-
assert result.graph.number_of_nodes() == 0
28-
assert result.graph.number_of_edges() == 0
26+
with pytest.raises(ValueError) as exception_info:
27+
StatusTransitionGraph.from_data_frame(pd.DataFrame([]))
28+
assert 'Provided DataFrame is empty' in str(exception_info.value)
2929

3030

3131
def test_create_status_transition_graph_from_data_frame():
@@ -51,7 +51,7 @@ def test_create_status_transition_graph_from_data_frame():
5151

5252

5353
def test_convert_of_empty_status_transition_graph_to_graphiz_dot():
54-
result = StatusTransitionGraph.from_data_frame(pd.DataFrame([]))
54+
result = StatusTransitionGraph()
5555
dot = StatusTransitionGraphVisualizer().visualize(result)
5656

5757
assert dot.source.replace("\t", "") == """strict digraph "Status Transitions" {

0 commit comments

Comments
 (0)