-
Notifications
You must be signed in to change notification settings - Fork 94
Improve compare tool #440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Improve compare tool #440
Changes from all commits
86b1ae5
38dec1f
824a499
716acc5
89f91f2
22241df
4da9b80
c6e45d7
cf1288b
87de2a2
c32a2cf
4d35bd9
7f75ca4
e7bfc30
161bf41
ef7660e
9f1c890
0c9f2fe
8cd4344
3e4d1b2
28aa654
1485d00
22cef5b
4940cfa
2f742b5
7198894
c68064b
fbf5f0e
00e1938
a52a80d
08cd9b4
ad689f2
6df77e8
4c91a17
96fd6f1
cd3e67e
a7e52f6
f3a7c59
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -300,3 +300,33 @@ def print_dl_metrics(variants: list[DiagLayer]) -> None: | |||||||
table.add_row(variant.short_name, variant.variant_type.value, str(len(all_services)), | ||||||||
str(len(ddds.data_object_props)), str(len(comparam_refs))) | ||||||||
rich_print(table) | ||||||||
|
||||||||
|
||||||||
def print_change_metrics(metrics_results: list[dict[str, object]]) -> None: | ||||||||
"""Print new/deleted/renamed/changed counts between files.""" | ||||||||
|
||||||||
table = RichTable( | ||||||||
title="Change Metrics", | ||||||||
show_header=True, | ||||||||
header_style="bold cyan", | ||||||||
border_style="blue", | ||||||||
show_lines=True) | ||||||||
table.add_column("File Comparison", style="green") | ||||||||
table.add_column("Diag Layer", style="magenta") | ||||||||
table.add_column("Variant Type", style="magenta") | ||||||||
table.add_column("Variants Added", justify="right", style="yellow") | ||||||||
table.add_column("Variants Changed", justify="right", style="yellow") | ||||||||
table.add_column("Variants Deleted", justify="right", style="yellow") | ||||||||
table.add_column("Services Added", justify="right", style="yellow") | ||||||||
table.add_column("Services Changed", justify="right", style="yellow") | ||||||||
table.add_column("Services Deleted", justify="right", style="yellow") | ||||||||
table.add_column("Changed Parameters", justify="right", style="yellow") | ||||||||
# | ||||||||
for m in metrics_results: | ||||||||
file_pair = f"{m['file_a']} --> {m['file_b']}" | ||||||||
table.add_row(file_pair, str(m["diag_layer"]), str(m["diag_layer_type"]), | ||||||||
str(m["num_variants_added"]), str(m["num_variants_changed"]), | ||||||||
str(m["num_variants_deleted"]), str(m["num_new_services"]), | ||||||||
str(m["num_deleted_services"]), str(m["num_renamed_services"]), | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the column headers, the order is
Suggested change
|
||||||||
str(m["num_changed_parameters"])) | ||||||||
rich_print(table) |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ | |||||||||||||||
# SPDX-License-Identifier: MIT | ||||||||||||||||
|
||||||||||||||||
import argparse | ||||||||||||||||
import json | ||||||||||||||||
import os | ||||||||||||||||
from dataclasses import dataclass, field | ||||||||||||||||
from typing import Any | ||||||||||||||||
|
@@ -22,7 +23,7 @@ | |||||||||||||||
from ..parameters.valueparameter import ValueParameter | ||||||||||||||||
from . import _parser_utils | ||||||||||||||||
from ._parser_utils import SubparsersList | ||||||||||||||||
from ._print_utils import (extract_service_tabulation_data, print_dl_metrics, | ||||||||||||||||
from ._print_utils import (extract_service_tabulation_data, print_change_metrics, print_dl_metrics, | ||||||||||||||||
print_service_parameters) | ||||||||||||||||
|
||||||||||||||||
# name of the tool | ||||||||||||||||
|
@@ -344,18 +345,18 @@ def compare_services(self, service1: DiagService, service2: DiagService) -> list | |||||||||||||||
) | ||||||||||||||||
# table | ||||||||||||||||
information.append({ | ||||||||||||||||
"List": ["Old list", "New list"], | ||||||||||||||||
"list": ["Old list", "New list"], | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
"Values": [str(response1.parameters), | ||||||||||||||||
str(response2.parameters)] | ||||||||||||||||
}) | ||||||||||||||||
else: | ||||||||||||||||
changed_params += "positive responses list, " | ||||||||||||||||
# infotext | ||||||||||||||||
information.append( | ||||||||||||||||
f"List of positive responses for service '{service2.short_name}' is not identical.") | ||||||||||||||||
f"list of positive responses for service '{service2.short_name}' is not identical.") | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
# table | ||||||||||||||||
information.append({ | ||||||||||||||||
"List": ["Old list", "New list"], | ||||||||||||||||
"list": ["Old list", "New list"], | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
"Values": [str(service1.positive_responses), | ||||||||||||||||
str(service2.positive_responses)] | ||||||||||||||||
}) | ||||||||||||||||
|
@@ -382,23 +383,23 @@ def compare_services(self, service1: DiagService, service2: DiagService) -> list | |||||||||||||||
changed_params += "positive response parameter list, " | ||||||||||||||||
# infotext | ||||||||||||||||
information.append( | ||||||||||||||||
f"List of positive response parameters for service '{service2.short_name}' is not identical.\n" | ||||||||||||||||
f"list of positive response parameters for service '{service2.short_name}' is not identical.\n" | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
) | ||||||||||||||||
# table | ||||||||||||||||
information.append({ | ||||||||||||||||
"List": ["Old list", "New list"], | ||||||||||||||||
"list": ["Old list", "New list"], | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
"Values": [str(response1.parameters), | ||||||||||||||||
str(response2.parameters)] | ||||||||||||||||
}) | ||||||||||||||||
else: | ||||||||||||||||
changed_params += "negative responses list, " | ||||||||||||||||
# infotext | ||||||||||||||||
information.append( | ||||||||||||||||
f"List of positive responses for service '{service2.short_name}' is not identical.\n" | ||||||||||||||||
f"list of positive responses for service '{service2.short_name}' is not identical.\n" | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
) | ||||||||||||||||
# table | ||||||||||||||||
information.append({ | ||||||||||||||||
"List": ["Old list", "New list"], | ||||||||||||||||
"list": ["Old list", "New list"], | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
"Values": [str(service1.negative_responses), | ||||||||||||||||
str(service2.negative_responses)] | ||||||||||||||||
}) | ||||||||||||||||
|
@@ -584,12 +585,29 @@ def add_subparser(subparsers: SubparsersList) -> None: | |||||||||||||||
required=False, | ||||||||||||||||
help="Don't show all service parameter details", | ||||||||||||||||
) | ||||||||||||||||
|
||||||||||||||||
# TODO | ||||||||||||||||
# Idea: provide folder with multiple pdx files as argument | ||||||||||||||||
# -> load all pdx files in folder, sort them alphabetically, compare databases pairwaise | ||||||||||||||||
# -> calculate metrics (number of added services, number of changed services, number of removed services, total number of services per ecu variant, ...) | ||||||||||||||||
# -> display metrics graphically | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comments could be deleted as this PR implements described idea |
||||||||||||||||
parser.add_argument( | ||||||||||||||||
"-f", | ||||||||||||||||
"--folder", | ||||||||||||||||
#action="store_false", | ||||||||||||||||
#default=True, | ||||||||||||||||
metavar="FOLDER", | ||||||||||||||||
required=False, | ||||||||||||||||
help="Provide folder path containing multiple PDX files for pairwise comparison.", | ||||||||||||||||
) | ||||||||||||||||
parser.add_argument( | ||||||||||||||||
"-o", | ||||||||||||||||
"--output", | ||||||||||||||||
#action="store_false", | ||||||||||||||||
#default=True, | ||||||||||||||||
metavar="RESULT", | ||||||||||||||||
required=False, | ||||||||||||||||
help="Write comparison results to JSON file.", | ||||||||||||||||
) | ||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
def run(args: argparse.Namespace) -> None: | ||||||||||||||||
|
@@ -598,7 +616,6 @@ def run(args: argparse.Namespace) -> None: | |||||||||||||||
task.param_detailed = args.no_details | ||||||||||||||||
|
||||||||||||||||
db_names = [args.pdx_file if isinstance(args.pdx_file, str) else str(args.pdx_file[0])] | ||||||||||||||||
|
||||||||||||||||
if args.database and args.variants: | ||||||||||||||||
# compare specified databases, consider only specified variants | ||||||||||||||||
|
||||||||||||||||
|
@@ -715,6 +732,86 @@ def run(args: argparse.Namespace) -> None: | |||||||||||||||
task.print_dl_changes( | ||||||||||||||||
task.compare_diagnostic_layers(dl, task.diagnostic_layers[db_idx + 1])) | ||||||||||||||||
|
||||||||||||||||
else: | ||||||||||||||||
# no databases & no variants specified | ||||||||||||||||
rich_print("Please specify either a database or variant for a comparison") | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd keep the
|
||||||||||||||||
elif getattr(args, "folder", None): | ||||||||||||||||
pdx_files = [] | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By iterating through folder, the positional argument
Suggested change
|
||||||||||||||||
for file in os.listdir(args.folder): | ||||||||||||||||
if file.lower().endswith(".pdx"): | ||||||||||||||||
full_path = os.path.join(args.folder, file) | ||||||||||||||||
pdx_files.append(full_path) | ||||||||||||||||
pdx_files.sort() | ||||||||||||||||
print(f"PDX files in folder {args.folder}: {','.join(pdx_files)}") | ||||||||||||||||
summary_results = [] | ||||||||||||||||
for i in range(len(pdx_files) - 1): | ||||||||||||||||
file_a = pdx_files[i] | ||||||||||||||||
file_b = pdx_files[i + 1] | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this does not really make sense IMO: the desired order of files to be compared pairwise might not be lexicographical. Possibly the whole There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @andlaus Actually as per the comment from @kayoub5, this is the condition, should we go with alphabetically or do we have to compare each and every file without sorting ? Could you please provide me your input? Thanks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is still the opportunity to pass multiple PDX files in a custom order with the command line parameter |
||||||||||||||||
task.databases = [load_file(file_a)] | ||||||||||||||||
db_a = task.databases[0] | ||||||||||||||||
task.databases = [load_file(file_b)] | ||||||||||||||||
db_b = task.databases[0] | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
dl_a = db_a.diag_layers | ||||||||||||||||
dl_b = db_b.diag_layers | ||||||||||||||||
names_a = {dl.short_name for dl in dl_a} | ||||||||||||||||
names_b = {dl.short_name for dl in dl_b} | ||||||||||||||||
|
||||||||||||||||
variants_added = names_b - names_a | ||||||||||||||||
variants_deleted = names_a - names_b | ||||||||||||||||
variants_changed_count = 0 | ||||||||||||||||
services_changed_set = set() | ||||||||||||||||
|
||||||||||||||||
diagnostic_layer_names = {dl.short_name | ||||||||||||||||
for dl in dl_a}.intersection({dl.short_name | ||||||||||||||||
for dl in dl_b}) | ||||||||||||||||
|
||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Idea:
Suggested change
|
||||||||||||||||
for name in diagnostic_layer_names: | ||||||||||||||||
layer_a = next(dl for dl in dl_a if dl.short_name == name) | ||||||||||||||||
layer_b = next(dl for dl in dl_b if dl.short_name == name) | ||||||||||||||||
changes = task.compare_diagnostic_layers(layer_a, layer_b) | ||||||||||||||||
old_names = [] | ||||||||||||||||
if getattr(changes, "changed_name_of_service", None): | ||||||||||||||||
try: | ||||||||||||||||
old_names = changes.changed_name_of_service[0] | ||||||||||||||||
except Exception: | ||||||||||||||||
old_names = [ | ||||||||||||||||
item for sublist in changes.changed_name_of_service for item in sublist | ||||||||||||||||
] | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The list
Moreover, |
||||||||||||||||
num_new = len(getattr(changes, "new_services", []) or []) | ||||||||||||||||
num_deleted = len(getattr(changes, "deleted_services", []) or []) | ||||||||||||||||
num_renamed = len(old_names) | ||||||||||||||||
num_changed_params = len( | ||||||||||||||||
getattr(changes, "changed_parameters_of_service", []) or []) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
|
||||||||||||||||
# collect which services had parameter changes (unique) | ||||||||||||||||
for param_detail in getattr(changes, "changed_parameters_of_service", []) or []: | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
services_changed_set.add(param_detail.service.short_name) | ||||||||||||||||
|
||||||||||||||||
# if anything changed in this variant mark it as changed | ||||||||||||||||
if num_new or num_deleted or num_renamed or num_changed_params: | ||||||||||||||||
variants_changed_count += 1 | ||||||||||||||||
|
||||||||||||||||
summary_results.append({ | ||||||||||||||||
"file_a": os.path.basename(file_a), | ||||||||||||||||
"file_b": os.path.basename(file_b), | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
"diag_layer": changes.diag_layer, | ||||||||||||||||
"diag_layer_type": changes.diag_layer_type, | ||||||||||||||||
"num_variants_added": len(variants_added), | ||||||||||||||||
"num_variants_changed": variants_changed_count, | ||||||||||||||||
"num_variants_deleted": len(variants_deleted), | ||||||||||||||||
"num_new_services": len(changes.new_services), | ||||||||||||||||
"num_deleted_services": len(changes.deleted_services), | ||||||||||||||||
"num_renamed_services": len(changes.changed_name_of_service[0]), | ||||||||||||||||
"num_changed_parameters": len(changes.changed_parameters_of_service) | ||||||||||||||||
}) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would add here only the change metrics for services as
Add at the end of loop
Add after the loop
|
||||||||||||||||
services_a = {srv.short_name for srv in layer_a.services} | ||||||||||||||||
services_b = {srv.short_name for srv in layer_b.services} | ||||||||||||||||
print("Services in file A:", services_a) | ||||||||||||||||
print("Services in file B:", services_b) | ||||||||||||||||
|
||||||||||||||||
print("New services:", services_b - services_a) | ||||||||||||||||
print("Deleted services:", services_a - services_b) | ||||||||||||||||
print_dl_metrics([layer_a, layer_b]) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Services are defined per diagnostic layer, as well as the function
Suggested change
|
||||||||||||||||
|
||||||||||||||||
print(json.dumps(summary_results, indent=4)) | ||||||||||||||||
if args.output: | ||||||||||||||||
with open(args.output, "w") as f: | ||||||||||||||||
json.dump(summary_results, f, indent=4) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Idea: |
||||||||||||||||
print_change_metrics(summary_results) | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't there already a function which compares two complete PDX files? why not calling that here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @andlaus I have reused the compare_dianostic_layer() function to compare different pdx files
Suggested change
Thanks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @vinothk-master, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variants
andDiag Layer
refer to the same object, therefore I wouldn't print the comparison details for eachDiag Layer
. See suggestion for table design here.