msgram 3.2.2__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {msgram-3.2.2 → msgram-3.3.0}/PKG-INFO +2 -2
- {msgram-3.2.2 → msgram-3.3.0}/msgram.egg-info/PKG-INFO +2 -2
- {msgram-3.2.2 → msgram-3.3.0}/msgram.egg-info/SOURCES.txt +2 -0
- {msgram-3.2.2 → msgram-3.3.0}/msgram.egg-info/requires.txt +1 -1
- {msgram-3.2.2 → msgram-3.3.0}/pyproject.toml +2 -2
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/commands/cmd_calculate.py +35 -23
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/commands/cmd_diff.py +13 -6
- msgram-3.3.0/src/cli/commands/cmd_extract.py +237 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/commands/cmd_list.py +1 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/commands/cmd_norm_diff.py +9 -16
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/jsonReader/jsonReader.py +8 -7
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/parsers.py +55 -60
- msgram-3.3.0/src/cli/resources/perf_eff_measure.py +165 -0
- msgram-3.3.0/src/cli/resources/perf_eff_parser.py +76 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/utils.py +22 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/system/test_extract.py +2 -6
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_calculate.py +71 -17
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_diff.py +33 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_extract.py +33 -75
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_jsonReader.py +1 -3
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_parser.py +5 -16
- msgram-3.2.2/src/cli/commands/cmd_extract.py +0 -176
- {msgram-3.2.2 → msgram-3.3.0}/LICENSE +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/README.md +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/msgram.egg-info/dependency_links.txt +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/msgram.egg-info/entry_points.txt +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/msgram.egg-info/top_level.txt +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/setup.cfg +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/aggregate_metrics.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/cli.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/commands/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/commands/cmd_init.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/exceptions/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/exceptions/exceptions.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/jsonReader/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/resources/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/resources/characteristic.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/resources/measure.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/resources/metrics.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/resources/subcharacteristic.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/cli/resources/tsqmi.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/config/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/config/settings.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/src/config/setup_log.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/system/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/system/test_help.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/system/test_init.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/system/test_list.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/__init__.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/data/file_reader_response.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_aggregate.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_characteristic.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_init.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_list.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_measures.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_norm_diff.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_setup_log.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_subcharacteristic.py +0 -0
- {msgram-3.2.2 → msgram-3.3.0}/tests/unit/test_tsqmi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: msgram
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: The msgram CLI is a command-line interface to use MeasureSoftGram software
|
|
5
5
|
Author-email: MeasureSoftGram <measuresoftgram@gmail.com>
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -684,7 +684,7 @@ Requires-Dist: setuptools~=72.1.0
|
|
|
684
684
|
Requires-Dist: python-dotenv
|
|
685
685
|
Requires-Dist: rich
|
|
686
686
|
Requires-Dist: validators~=0.33.0
|
|
687
|
-
Requires-Dist: msgram-core~=1.
|
|
687
|
+
Requires-Dist: msgram-core~=1.5.3
|
|
688
688
|
Requires-Dist: msgram-parser~=1.2.1
|
|
689
689
|
Requires-Dist: anytree
|
|
690
690
|
Provides-Extra: dev
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: msgram
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: The msgram CLI is a command-line interface to use MeasureSoftGram software
|
|
5
5
|
Author-email: MeasureSoftGram <measuresoftgram@gmail.com>
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -684,7 +684,7 @@ Requires-Dist: setuptools~=72.1.0
|
|
|
684
684
|
Requires-Dist: python-dotenv
|
|
685
685
|
Requires-Dist: rich
|
|
686
686
|
Requires-Dist: validators~=0.33.0
|
|
687
|
-
Requires-Dist: msgram-core~=1.
|
|
687
|
+
Requires-Dist: msgram-core~=1.5.3
|
|
688
688
|
Requires-Dist: msgram-parser~=1.2.1
|
|
689
689
|
Requires-Dist: anytree
|
|
690
690
|
Provides-Extra: dev
|
|
@@ -28,6 +28,8 @@ src/cli/resources/__init__.py
|
|
|
28
28
|
src/cli/resources/characteristic.py
|
|
29
29
|
src/cli/resources/measure.py
|
|
30
30
|
src/cli/resources/metrics.py
|
|
31
|
+
src/cli/resources/perf_eff_measure.py
|
|
32
|
+
src/cli/resources/perf_eff_parser.py
|
|
31
33
|
src/cli/resources/subcharacteristic.py
|
|
32
34
|
src/cli/resources/tsqmi.py
|
|
33
35
|
src/config/__init__.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "msgram"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.3.0"
|
|
8
8
|
description = "The msgram CLI is a command-line interface to use MeasureSoftGram software"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -32,7 +32,7 @@ dependencies = [
|
|
|
32
32
|
"python-dotenv",
|
|
33
33
|
"rich",
|
|
34
34
|
"validators~=0.33.0",
|
|
35
|
-
"msgram-core~=1.
|
|
35
|
+
"msgram-core~=1.5.3",
|
|
36
36
|
"msgram-parser~=1.2.1",
|
|
37
37
|
"anytree"
|
|
38
38
|
]
|
|
@@ -16,9 +16,9 @@ from src.cli.resources.measure import calculate_measures
|
|
|
16
16
|
from src.cli.resources.tsqmi import calculate_tsqmi
|
|
17
17
|
from src.cli.resources.subcharacteristic import calculate_subcharacteristics
|
|
18
18
|
from src.cli.utils import print_error, print_info, print_panel, print_rule, print_table
|
|
19
|
-
from src.cli.aggregate_metrics import aggregate_metrics
|
|
20
19
|
from src.cli.exceptions import exceptions
|
|
21
20
|
from src.config.settings import DEFAULT_CONFIG_PATH, FILE_CONFIG
|
|
21
|
+
from src.cli.resources.perf_eff_measure import calculate_perf_eff_measures
|
|
22
22
|
|
|
23
23
|
logger = logging.getLogger("msgram")
|
|
24
24
|
|
|
@@ -34,23 +34,33 @@ def read_config_file(config_path):
|
|
|
34
34
|
exit(1)
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
# calculate_sonar
|
|
38
|
+
# calculate_github
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def calculate_metrics(extracted_path, config):
|
|
38
42
|
data_calculated = []
|
|
39
43
|
|
|
44
|
+
print(extracted_path)
|
|
40
45
|
if not extracted_path.is_file():
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if file_name.startswith("
|
|
51
|
-
file_name = file_name[len("
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
# should not aggregate
|
|
47
|
+
# if not aggregate_metrics(input_format, extracted_path, config):
|
|
48
|
+
# print_error(
|
|
49
|
+
# "> [red] Failed to aggregate metrics, calculate was not performed. \n"
|
|
50
|
+
# )
|
|
51
|
+
# return data_calculated, False
|
|
52
|
+
|
|
53
|
+
for file, file_name in read_multiple_files(extracted_path, "metrics"):
|
|
54
|
+
print(file_name)
|
|
55
|
+
if file_name.startswith("perf-eff_"):
|
|
56
|
+
file_name = file_name[len("perf-eff_") :]
|
|
57
|
+
result = calculate_perf_eff_measures(file_name, file)
|
|
58
|
+
data_calculated.append(result)
|
|
59
|
+
else:
|
|
60
|
+
if file_name.startswith("github_"):
|
|
61
|
+
file_name = file_name[len("github_") :]
|
|
62
|
+
result = calculate_all(file, file_name, config)
|
|
63
|
+
data_calculated.append(result)
|
|
54
64
|
|
|
55
65
|
return data_calculated, True
|
|
56
66
|
else:
|
|
@@ -59,7 +69,8 @@ def calculate_metrics(input_format, extracted_path, config):
|
|
|
59
69
|
if extracted_path.name.startswith("github_"):
|
|
60
70
|
file_name = file_name[len("github_") :]
|
|
61
71
|
result = calculate_all(open_json_file(extracted_path), file_name, config)
|
|
62
|
-
|
|
72
|
+
data_calculated.append(result)
|
|
73
|
+
return data_calculated, True
|
|
63
74
|
except exceptions.MeasureSoftGramCLIException as e:
|
|
64
75
|
print_error(f"[red]Error calculating {extracted_path}: {e}\n")
|
|
65
76
|
return data_calculated, False
|
|
@@ -68,7 +79,7 @@ def calculate_metrics(input_format, extracted_path, config):
|
|
|
68
79
|
def command_calculate(args):
|
|
69
80
|
try:
|
|
70
81
|
output_format: str = args["output_format"]
|
|
71
|
-
input_format: str = args["input_format"]
|
|
82
|
+
# input_format: str = args["input_format"]
|
|
72
83
|
config_path = args["config_path"]
|
|
73
84
|
extracted_path = args["extracted_path"]
|
|
74
85
|
|
|
@@ -86,7 +97,7 @@ def command_calculate(args):
|
|
|
86
97
|
|
|
87
98
|
print_info("\n> [blue] Reading extracted files:[/]")
|
|
88
99
|
|
|
89
|
-
data_calculated, success = calculate_metrics(
|
|
100
|
+
data_calculated, success = calculate_metrics(extracted_path, config)
|
|
90
101
|
|
|
91
102
|
if success:
|
|
92
103
|
print_info("\n[#A9A9A9]All calculations performed[/] successfully!")
|
|
@@ -96,8 +107,9 @@ def command_calculate(args):
|
|
|
96
107
|
|
|
97
108
|
print_panel(
|
|
98
109
|
title="Done",
|
|
99
|
-
menssage="> See
|
|
100
|
-
"
|
|
110
|
+
menssage="> See the publications for more information: \n"
|
|
111
|
+
"https://dl.acm.org/doi/10.1145/3239235.3267438 \n"
|
|
112
|
+
"https://dl.acm.org/doi/10.1145/3422392.3422450 \n",
|
|
101
113
|
)
|
|
102
114
|
|
|
103
115
|
|
|
@@ -139,13 +151,13 @@ def calculate_all(json_data, file_name, config):
|
|
|
139
151
|
def show_results(output_format, data_calculated, config_path):
|
|
140
152
|
|
|
141
153
|
if output_format == "tabular":
|
|
142
|
-
show_tabulate(data_calculated)
|
|
154
|
+
show_tabulate(data_calculated[0])
|
|
143
155
|
|
|
144
156
|
elif output_format == "raw":
|
|
145
|
-
print(data_calculated)
|
|
157
|
+
print(data_calculated[0])
|
|
146
158
|
|
|
147
159
|
elif output_format == "tree":
|
|
148
|
-
show_tree(data_calculated, pre_config)
|
|
160
|
+
show_tree(data_calculated[0], pre_config)
|
|
149
161
|
|
|
150
162
|
elif len(data_calculated) == 0:
|
|
151
163
|
print_info(
|
|
@@ -15,6 +15,7 @@ from src.cli.utils import (
|
|
|
15
15
|
print_info,
|
|
16
16
|
print_panel,
|
|
17
17
|
print_rule,
|
|
18
|
+
validate_json_values,
|
|
18
19
|
)
|
|
19
20
|
from src.cli.exceptions import exceptions
|
|
20
21
|
from src.config.settings import DEFAULT_CONFIG_PATH
|
|
@@ -61,7 +62,7 @@ def read_calculated_file(extracted_calculation):
|
|
|
61
62
|
exit(1)
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
def calculate_diff(planned, calculated):
|
|
65
|
+
def calculate_diff(planned, calculated, rp_path, rd_path):
|
|
65
66
|
formated_result = []
|
|
66
67
|
|
|
67
68
|
try:
|
|
@@ -73,7 +74,7 @@ def calculate_diff(planned, calculated):
|
|
|
73
74
|
)
|
|
74
75
|
|
|
75
76
|
data_planned, data_calculated = extract_values(
|
|
76
|
-
planned, calculated_item["characteristics"]
|
|
77
|
+
planned, calculated_item["characteristics"], rp_path, rd_path
|
|
77
78
|
)
|
|
78
79
|
|
|
79
80
|
diff_calculated = diff(data_planned, data_calculated)
|
|
@@ -124,7 +125,9 @@ def command_diff(args):
|
|
|
124
125
|
|
|
125
126
|
calculated = read_calculated_file(extracted_calculation)
|
|
126
127
|
|
|
127
|
-
diff_calculated, success = calculate_diff(
|
|
128
|
+
diff_calculated, success = calculate_diff(
|
|
129
|
+
planned, calculated, config_path, extracted_calculation
|
|
130
|
+
)
|
|
128
131
|
|
|
129
132
|
if success:
|
|
130
133
|
print_info("\n[#A9A9A9]Diff calculation performed[/] successfully!")
|
|
@@ -136,8 +139,9 @@ def command_diff(args):
|
|
|
136
139
|
|
|
137
140
|
print_panel(
|
|
138
141
|
title="Done",
|
|
139
|
-
menssage="> See
|
|
140
|
-
"
|
|
142
|
+
menssage="> See the publications for more information: \n"
|
|
143
|
+
"https://dl.acm.org/doi/10.1145/3239235.3267438 \n"
|
|
144
|
+
"https://dl.acm.org/doi/10.1145/3422392.3422450 \n",
|
|
141
145
|
)
|
|
142
146
|
|
|
143
147
|
|
|
@@ -208,7 +212,7 @@ def export_csv(data_calculated: list, file_path: Path = Path("DEFAULT_CONFIG_PAT
|
|
|
208
212
|
print(f"Success: {file_path.name} exported as CSV")
|
|
209
213
|
|
|
210
214
|
|
|
211
|
-
def extract_values(planned, calculated):
|
|
215
|
+
def extract_values(planned, calculated, rp_path, rd_path):
|
|
212
216
|
vector_calculated = []
|
|
213
217
|
vector_planned = []
|
|
214
218
|
|
|
@@ -221,4 +225,7 @@ def extract_values(planned, calculated):
|
|
|
221
225
|
vector_calculated.append(calculated[x]["value"])
|
|
222
226
|
vector_planned.append(planned[x]["value"])
|
|
223
227
|
|
|
228
|
+
validate_json_values(vector_planned, rp_path)
|
|
229
|
+
validate_json_values(vector_calculated, rd_path)
|
|
230
|
+
|
|
224
231
|
return vector_planned, vector_calculated
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
import sys
|
|
7
|
+
from time import perf_counter
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from rich import print
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from genericparser import GenericParser
|
|
13
|
+
|
|
14
|
+
from src.cli.jsonReader import folder_reader
|
|
15
|
+
from src.cli.utils import (
|
|
16
|
+
make_progress_bar,
|
|
17
|
+
print_info,
|
|
18
|
+
print_panel,
|
|
19
|
+
print_rule,
|
|
20
|
+
print_warn,
|
|
21
|
+
is_valid_date_range,
|
|
22
|
+
)
|
|
23
|
+
from src.cli.resources.perf_eff_parser import parse_performance_efficiency_data
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger("msgram")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_infos_from_name(filename: str) -> str:
|
|
29
|
+
"""
|
|
30
|
+
filename: str = fga-eps-mds-2022-1-MeasureSoftGram-Service-09-11-2022-16-11-42-develop.json
|
|
31
|
+
"""
|
|
32
|
+
file_date = re.search(r"\d{1,2}-\d{1,2}-\d{4}-\d{1,2}-\d{1,2}", filename)
|
|
33
|
+
|
|
34
|
+
if not file_date:
|
|
35
|
+
message = (
|
|
36
|
+
"Could not extract creation date from file. Was the file name "
|
|
37
|
+
"to contain a date in the format dd-mm-yyyy-hh-mm"
|
|
38
|
+
)
|
|
39
|
+
print_warn(message)
|
|
40
|
+
print_warn(f"filename: {filename}")
|
|
41
|
+
sys.exit(1)
|
|
42
|
+
|
|
43
|
+
file_name = filename.split(".")[0]
|
|
44
|
+
|
|
45
|
+
return f"{file_name}-extracted.metrics"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def parse_input_quotes(user_input):
|
|
49
|
+
# Aspas para normalizar
|
|
50
|
+
quotes = "“‘«”’»"
|
|
51
|
+
|
|
52
|
+
if user_input:
|
|
53
|
+
# Remove aspas no início
|
|
54
|
+
user_input = user_input[1:] if user_input[0] in quotes else user_input
|
|
55
|
+
|
|
56
|
+
# Remove aspas no final
|
|
57
|
+
user_input = user_input[:-1] if user_input[-1] in quotes else user_input
|
|
58
|
+
|
|
59
|
+
return user_input
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def extract_github(
|
|
63
|
+
extracted_path: Path,
|
|
64
|
+
gh_repository: str,
|
|
65
|
+
gh_date_range: str,
|
|
66
|
+
gh_label: str,
|
|
67
|
+
gh_workflows: str,
|
|
68
|
+
parser: GenericParser,
|
|
69
|
+
):
|
|
70
|
+
input_origin = "github"
|
|
71
|
+
if gh_date_range is not None and not is_valid_date_range(gh_date_range):
|
|
72
|
+
logger.error(
|
|
73
|
+
"Error: Range of dates for filter must be in format 'dd/mm/yyyy-dd/mm/yyyy'"
|
|
74
|
+
)
|
|
75
|
+
print_warn(
|
|
76
|
+
"Error: Range of dates for filter must be in format 'dd/mm/yyyy-dd/mm/yyyy'"
|
|
77
|
+
)
|
|
78
|
+
sys.exit(1)
|
|
79
|
+
filters = {
|
|
80
|
+
"labels": gh_label if gh_label else "US,User Story,User Stories",
|
|
81
|
+
"workflows": gh_workflows.split(",") if gh_workflows else "build",
|
|
82
|
+
"dates": gh_date_range if gh_date_range else None,
|
|
83
|
+
}
|
|
84
|
+
print_info(f"\n> Extract and save metrics [[blue ]{input_origin}[/]]:")
|
|
85
|
+
result = parser.parse(
|
|
86
|
+
input_value=gh_repository, type_input=input_origin, filters=filters
|
|
87
|
+
)
|
|
88
|
+
repository_name = gh_repository.replace("/", "-")
|
|
89
|
+
save_file_with_results(
|
|
90
|
+
extracted_path,
|
|
91
|
+
gh_repository,
|
|
92
|
+
name=f"github_{repository_name}-{datetime.now().strftime('%d-%m-%Y-%H-%M-%S')}-extracted.metrics",
|
|
93
|
+
result=result,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def extract_sonar(extracted_path: Path, sonar_path: Path, parser: GenericParser):
|
|
98
|
+
time_init = perf_counter()
|
|
99
|
+
input_origin = "sonarqube"
|
|
100
|
+
|
|
101
|
+
logger.debug(f"input_origin: {input_origin}")
|
|
102
|
+
logger.debug(f"data_path: {sonar_path}")
|
|
103
|
+
logger.debug(f"extracted_path: {extracted_path}")
|
|
104
|
+
|
|
105
|
+
files = list(sonar_path.glob("*.json"))
|
|
106
|
+
|
|
107
|
+
if not files:
|
|
108
|
+
print_warn(f"No JSON files found in the specified data_path: {sonar_path}\n")
|
|
109
|
+
sys.exit(1)
|
|
110
|
+
|
|
111
|
+
valid_files = len(files)
|
|
112
|
+
|
|
113
|
+
print_info(f"\n> Extract and save metrics [[blue ]{input_origin}[/]]:")
|
|
114
|
+
with make_progress_bar() as progress_bar:
|
|
115
|
+
task_request = progress_bar.add_task(
|
|
116
|
+
"[#A9A9A9]Extracting files: ", total=len(files)
|
|
117
|
+
)
|
|
118
|
+
progress_bar.advance(task_request)
|
|
119
|
+
|
|
120
|
+
for component, filename, files_error in folder_reader(sonar_path, "json"):
|
|
121
|
+
if files_error:
|
|
122
|
+
progress_bar.update(task_request, advance=files_error)
|
|
123
|
+
valid_files = valid_files - files_error
|
|
124
|
+
|
|
125
|
+
name = get_infos_from_name(filename)
|
|
126
|
+
result = parser.parse(input_value=component, type_input=input_origin)
|
|
127
|
+
|
|
128
|
+
save_file_with_results(extracted_path, filename, name, result)
|
|
129
|
+
|
|
130
|
+
progress_bar.advance(task_request)
|
|
131
|
+
|
|
132
|
+
time_extract = perf_counter() - time_init
|
|
133
|
+
print_info(
|
|
134
|
+
f"\n\nMetrics successfully extracted [[blue bold]{valid_files}/{len(files)} "
|
|
135
|
+
f"files - {time_extract:0.2f} seconds[/]]!"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def extract_perf_eff():
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def command_extract(args):
|
|
144
|
+
try:
|
|
145
|
+
extracted_path = args["extracted_path"]
|
|
146
|
+
sonar_path = args.get("sonar_path", None)
|
|
147
|
+
gh_repository = args.get("gh_repository", None)
|
|
148
|
+
gh_label = args.get("gh_label", None)
|
|
149
|
+
gh_workflows = args.get("gh_workflows", None)
|
|
150
|
+
gh_date_range = args.get("gh_date_range", None)
|
|
151
|
+
pe_release1 = args.get("pe_release_1", None)
|
|
152
|
+
pe_release2 = args.get("pe_release_2", None)
|
|
153
|
+
pe_repository_name = args.get("pe_repository_name", None)
|
|
154
|
+
|
|
155
|
+
except Exception as e:
|
|
156
|
+
logger.error(f"KeyError: args[{e}] - non-existent parameters")
|
|
157
|
+
print_warn(f"KeyError: args[{e}] - non-existent parameters")
|
|
158
|
+
exit(1)
|
|
159
|
+
|
|
160
|
+
pe_params = (
|
|
161
|
+
(pe_release1 is not None)
|
|
162
|
+
+ (pe_release2 is not None)
|
|
163
|
+
+ (pe_repository_name is not None)
|
|
164
|
+
)
|
|
165
|
+
if pe_params > 0 and pe_params < 3:
|
|
166
|
+
print_warn(
|
|
167
|
+
"Error: Some pe_ parameters for extracting the performance efficiency data are missing"
|
|
168
|
+
)
|
|
169
|
+
exit()
|
|
170
|
+
|
|
171
|
+
# First check if sonar_path and gh_repository are none
|
|
172
|
+
if (sonar_path is None) and (gh_repository is None) and (pe_params == 0):
|
|
173
|
+
logger.error(
|
|
174
|
+
"It is necessary to pass sonar_path, github_repository or the pe_ parameters"
|
|
175
|
+
)
|
|
176
|
+
print_warn(
|
|
177
|
+
"It is necessary to pass sonar_path, github_repository or the pe_ parameters"
|
|
178
|
+
)
|
|
179
|
+
sys.exit(1)
|
|
180
|
+
|
|
181
|
+
console = Console()
|
|
182
|
+
console.clear()
|
|
183
|
+
print_rule("Extract metrics")
|
|
184
|
+
parser = GenericParser()
|
|
185
|
+
|
|
186
|
+
if not os.path.isdir(extracted_path):
|
|
187
|
+
logger.error(
|
|
188
|
+
f'FileNotFoundError: extract directory "{extracted_path}" does not exists'
|
|
189
|
+
)
|
|
190
|
+
print_warn(
|
|
191
|
+
f"FileNotFoundError: extract directory[blue]'{extracted_path}'[/]does not exists"
|
|
192
|
+
)
|
|
193
|
+
sys.exit(1)
|
|
194
|
+
|
|
195
|
+
# Github repository is defined so we should generate github metrics
|
|
196
|
+
if gh_repository:
|
|
197
|
+
extract_github(
|
|
198
|
+
extracted_path, gh_repository, gh_date_range, gh_label, gh_workflows, parser
|
|
199
|
+
)
|
|
200
|
+
elif gh_label or gh_workflows or gh_date_range:
|
|
201
|
+
logger.error(
|
|
202
|
+
"Error: gh_repository must be specified in order to use gh_ parameters"
|
|
203
|
+
)
|
|
204
|
+
print_warn(
|
|
205
|
+
"Error: gh_repository must be specified in order to use gh_ parameters"
|
|
206
|
+
)
|
|
207
|
+
sys.exit(1)
|
|
208
|
+
|
|
209
|
+
if pe_params == 3:
|
|
210
|
+
input_origin = "performance-efficiency"
|
|
211
|
+
print_info(f"\n> Extract and save metrics [[blue ]{input_origin}[/]]:")
|
|
212
|
+
# All pe_params are set, so we should extract the performance efficiency data
|
|
213
|
+
parsed_data = parse_performance_efficiency_data(
|
|
214
|
+
pe_release1, pe_release2, pe_repository_name
|
|
215
|
+
)
|
|
216
|
+
save_file_with_results(
|
|
217
|
+
extracted_path,
|
|
218
|
+
pe_repository_name,
|
|
219
|
+
name=f"perf-eff_{pe_repository_name}-{datetime.now().strftime('%d-%m-%Y-%H-%M-%S')}-extracted.metrics",
|
|
220
|
+
result=parsed_data,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# Sonargube path is defined so we should generate sonar metrics
|
|
224
|
+
if sonar_path:
|
|
225
|
+
extract_sonar(extracted_path, sonar_path, parser)
|
|
226
|
+
|
|
227
|
+
print_panel(
|
|
228
|
+
"> Run [#008080]msgram calculate all -ep 'extracted_path' -cp 'extracted_path' -o 'input_origin'"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def save_file_with_results(extracted_path, filename, name, result):
|
|
233
|
+
print(f"[dark_green]Reading:[/] [black]{filename}[/]")
|
|
234
|
+
print(f"[dark_green]Save :[/] [black]{name}[/]\n")
|
|
235
|
+
|
|
236
|
+
with open(f"{extracted_path}/{name}", "w") as f:
|
|
237
|
+
f.write(json.dumps(result, indent=2))
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from core.transformations import norm_diff
|
|
3
3
|
from src.cli.jsonReader import open_json_file
|
|
4
|
-
from src.cli.utils import
|
|
4
|
+
from src.cli.utils import (
|
|
5
|
+
print_error,
|
|
6
|
+
print_info,
|
|
7
|
+
print_rule,
|
|
8
|
+
validate_json_values,
|
|
9
|
+
)
|
|
5
10
|
from src.cli.exceptions import exceptions
|
|
6
11
|
import numpy as np
|
|
7
12
|
|
|
@@ -51,6 +56,7 @@ def command_norm_diff(args):
|
|
|
51
56
|
exit(1)
|
|
52
57
|
|
|
53
58
|
planned_data = read_planned_file(rp_path, sort_key="key")
|
|
59
|
+
|
|
54
60
|
calculated_data = read_calculated_file(rd_path)
|
|
55
61
|
|
|
56
62
|
planned_vector, calculated_vector = extract_values(
|
|
@@ -98,21 +104,8 @@ def extract_values(planned_data, calculated_data, rp_path, rd_path):
|
|
|
98
104
|
planned_values = [planned_dict[key] for key in planned_keys]
|
|
99
105
|
calculated_values = [calculated_dict[key] for key in planned_keys]
|
|
100
106
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
print_error(
|
|
104
|
-
f"[red]The values informed in the .json file {rp_path} must be between 0 and 1.\n"
|
|
105
|
-
)
|
|
106
|
-
print_rule()
|
|
107
|
-
exit(1)
|
|
108
|
-
|
|
109
|
-
for value in calculated_values:
|
|
110
|
-
if value > 1 or value < 0:
|
|
111
|
-
print_error(
|
|
112
|
-
f"[red]The values informed in the .json file {rd_path} must be between 0 and 1.\n"
|
|
113
|
-
)
|
|
114
|
-
print_rule()
|
|
115
|
-
exit(1)
|
|
107
|
+
validate_json_values(planned_values, rp_path)
|
|
108
|
+
validate_json_values(calculated_values, rd_path)
|
|
116
109
|
|
|
117
110
|
return (np.array(planned_values), np.array(calculated_values))
|
|
118
111
|
except exceptions.MeasureSoftGramCLIException as e:
|
|
@@ -29,13 +29,14 @@ def file_reader(path_file):
|
|
|
29
29
|
return components
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def read_multiple_files(directory: Path,
|
|
33
|
-
if format == "github":
|
|
34
|
-
|
|
35
|
-
elif format == "sonarqube":
|
|
36
|
-
|
|
37
|
-
else:
|
|
38
|
-
|
|
32
|
+
def read_multiple_files(directory: Path, pattern: str):
|
|
33
|
+
# if format == "github":
|
|
34
|
+
# glob_pattern = f"github_*.{pattern}"
|
|
35
|
+
# elif format == "sonarqube":
|
|
36
|
+
# glob_pattern = f"[!github_]*.{pattern}"
|
|
37
|
+
# else:
|
|
38
|
+
# glob_pattern = f"*.{pattern}"
|
|
39
|
+
glob_pattern = f"*.{pattern}"
|
|
39
40
|
|
|
40
41
|
for path_file in directory.glob(glob_pattern):
|
|
41
42
|
try:
|