odxtools 6.4.3__py3-none-any.whl → 6.5.0__py3-none-any.whl
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.
- odxtools/basicstructure.py +7 -3
- odxtools/cli/_print_utils.py +210 -25
- odxtools/cli/compare.py +730 -0
- odxtools/cli/decode.py +1 -1
- odxtools/cli/find.py +13 -4
- odxtools/cli/list.py +74 -40
- odxtools/cli/main.py +1 -1
- odxtools/database.py +1 -0
- odxtools/diagcodedtype.py +2 -0
- odxtools/version.py +2 -2
- {odxtools-6.4.3.dist-info → odxtools-6.5.0.dist-info}/METADATA +388 -47
- {odxtools-6.4.3.dist-info → odxtools-6.5.0.dist-info}/RECORD +16 -15
- {odxtools-6.4.3.dist-info → odxtools-6.5.0.dist-info}/LICENSE +0 -0
- {odxtools-6.4.3.dist-info → odxtools-6.5.0.dist-info}/WHEEL +0 -0
- {odxtools-6.4.3.dist-info → odxtools-6.5.0.dist-info}/entry_points.txt +0 -0
- {odxtools-6.4.3.dist-info → odxtools-6.5.0.dist-info}/top_level.txt +0 -0
odxtools/cli/decode.py
CHANGED
@@ -84,7 +84,7 @@ def add_subparser(subparsers: "argparse._SubParsersAction") -> None:
|
|
84
84
|
" For more information use:",
|
85
85
|
" odxtools decode -h",
|
86
86
|
]),
|
87
|
-
help="Find & print service by hex-data. Can also decode the hex-data to
|
87
|
+
help="Find & print service by hex-data. Can also decode the hex-data to its named parameters.",
|
88
88
|
formatter_class=argparse.RawTextHelpFormatter,
|
89
89
|
)
|
90
90
|
_parser_utils.add_pdx_argument(parser)
|
odxtools/cli/find.py
CHANGED
@@ -26,7 +26,8 @@ def print_summary(odxdb: Database,
|
|
26
26
|
service_names: List[str],
|
27
27
|
ecu_variants: Optional[List[str]] = None,
|
28
28
|
allow_unknown_bit_lengths: bool = False,
|
29
|
-
print_params: bool = False
|
29
|
+
print_params: bool = False,
|
30
|
+
plumbing_output: bool = False) -> None:
|
30
31
|
ecu_names = ecu_variants if ecu_variants else [ecu.short_name for ecu in odxdb.ecus]
|
31
32
|
service_db: Dict[str, DiagService] = {}
|
32
33
|
service_ecus: Dict[str, List[str]] = {}
|
@@ -60,7 +61,7 @@ def print_summary(odxdb: Database,
|
|
60
61
|
print_pre_condition_states=True,
|
61
62
|
print_state_transitions=True,
|
62
63
|
print_audiences=True,
|
63
|
-
|
64
|
+
plumbing_output=plumbing_output)
|
64
65
|
elif isinstance(service, SingleEcuJob):
|
65
66
|
print(f"SingleEcuJob: {service.odx_id}")
|
66
67
|
else:
|
@@ -79,7 +80,7 @@ def add_subparser(subparsers: "argparse._SubParsersAction") -> None:
|
|
79
80
|
" For more information use:",
|
80
81
|
" odxtools find -h",
|
81
82
|
]),
|
82
|
-
help="Find &
|
83
|
+
help="Find & display services by their name",
|
83
84
|
formatter_class=argparse.RawTextHelpFormatter,
|
84
85
|
)
|
85
86
|
_parser_utils.add_pdx_argument(parser)
|
@@ -120,6 +121,14 @@ def add_subparser(subparsers: "argparse._SubParsersAction") -> None:
|
|
120
121
|
help="Relax output formatting rules (allow unknown bitlengths for ascii representation)",
|
121
122
|
)
|
122
123
|
|
124
|
+
parser.add_argument(
|
125
|
+
"-po",
|
126
|
+
"--plumbing-output",
|
127
|
+
action="store_true",
|
128
|
+
required=False,
|
129
|
+
help="Print full objects instead of selected and formatted attributes",
|
130
|
+
)
|
131
|
+
|
123
132
|
|
124
133
|
def run(args: argparse.Namespace) -> None:
|
125
134
|
odxdb = _parser_utils.load_file(args)
|
@@ -131,4 +140,4 @@ def run(args: argparse.Namespace) -> None:
|
|
131
140
|
service_names=args.service_names,
|
132
141
|
print_params=not args.no_details,
|
133
142
|
allow_unknown_bit_lengths=args.relaxed_output,
|
134
|
-
|
143
|
+
plumbing_output=args.plumbing_output)
|
odxtools/cli/list.py
CHANGED
@@ -2,40 +2,57 @@
|
|
2
2
|
import argparse
|
3
3
|
from typing import Callable, List, Optional
|
4
4
|
|
5
|
+
from rich import print
|
6
|
+
|
5
7
|
from ..database import Database
|
6
8
|
from ..diagcomm import DiagComm
|
7
9
|
from ..diaglayer import DiagLayer
|
8
10
|
from ..diagservice import DiagService
|
9
11
|
from ..singleecujob import SingleEcuJob
|
10
12
|
from . import _parser_utils
|
11
|
-
from ._print_utils import format_desc, print_diagnostic_service
|
13
|
+
from ._print_utils import format_desc, print_diagnostic_service, print_dl_metrics
|
12
14
|
|
13
15
|
# name of the tool
|
14
16
|
_odxtools_tool_name_ = "list"
|
15
17
|
|
16
18
|
|
17
|
-
def print_summary(
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
19
|
+
def print_summary(odxdb: Database,
|
20
|
+
print_global_negative_responses: bool = False,
|
21
|
+
print_services: bool = False,
|
22
|
+
print_dops: bool = False,
|
23
|
+
print_params: bool = False,
|
24
|
+
print_comparams: bool = False,
|
25
|
+
print_pre_condition_states: bool = False,
|
26
|
+
print_state_transitions: bool = False,
|
27
|
+
print_audiences: bool = False,
|
28
|
+
allow_unknown_bit_lengths: bool = False,
|
29
|
+
variants: Optional[List[str]] = None,
|
30
|
+
service_filter: Callable[[DiagComm], bool] = lambda x: True,
|
31
|
+
plumbing_output: bool = False) -> None:
|
32
|
+
|
33
|
+
diag_layer_names = [dl.short_name for dl in odxdb.diag_layers]
|
34
|
+
diag_layers: List[DiagLayer] = []
|
35
|
+
|
36
|
+
if variants is None:
|
37
|
+
variants = diag_layer_names
|
38
|
+
|
39
|
+
for name in variants:
|
40
|
+
if name in diag_layer_names:
|
41
|
+
diag_layers.append([x for x in odxdb.diag_layers if x.short_name == name][0])
|
42
|
+
|
43
|
+
else:
|
44
|
+
print(f"The variant '{name}' could not be found!")
|
45
|
+
return
|
46
|
+
|
47
|
+
if diag_layers:
|
48
|
+
print("\n")
|
49
|
+
print(f"Overview of diagnostic layers: ")
|
50
|
+
print_dl_metrics(diag_layers)
|
51
|
+
|
52
|
+
for dl in diag_layers:
|
53
|
+
print("\n")
|
54
|
+
print(f"[green]Diagnostic layer:[/green] '[bold white]{dl.short_name}[/bold white]'")
|
55
|
+
print(f" [blue]Variant Type[/blue]: {dl.variant_type.value}")
|
39
56
|
|
40
57
|
assert isinstance(dl, DiagLayer)
|
41
58
|
all_services: List[DiagComm] = sorted(dl.services, key=lambda x: x.short_name)
|
@@ -43,31 +60,35 @@ def print_summary(
|
|
43
60
|
data_object_properties = dl.diag_data_dictionary_spec.data_object_props
|
44
61
|
comparams = dl.comparams
|
45
62
|
|
46
|
-
print(f"{dl.variant_type} '{dl.short_name}'")
|
47
|
-
print(
|
48
|
-
f" num services: {len(all_services)}, num DOPs: {len(data_object_properties)}, num communication parameters: {len(comparams)}."
|
49
|
-
)
|
50
|
-
|
51
63
|
for proto in dl.protocols:
|
52
64
|
if (can_rx_id := dl.get_can_receive_id(proto.short_name)) is not None:
|
53
|
-
print(
|
65
|
+
print(
|
66
|
+
f" [blue]CAN receive ID[/blue] for protocol '{proto.short_name}': 0x{can_rx_id:x}"
|
67
|
+
)
|
54
68
|
|
55
69
|
if (can_tx_id := dl.get_can_send_id(proto.short_name)) is not None:
|
56
|
-
print(
|
70
|
+
print(
|
71
|
+
f" [blue]CAN send ID[/blue] for protocol '{proto.short_name}': 0x{can_tx_id:x}"
|
72
|
+
)
|
57
73
|
|
58
74
|
if dl.description:
|
59
75
|
desc = format_desc(dl.description, ident=2)
|
60
|
-
print(f" Description: " + desc)
|
76
|
+
print(f" [blue]Description[/blue]: " + desc)
|
61
77
|
|
62
78
|
if print_global_negative_responses and dl.global_negative_responses:
|
63
|
-
print(
|
79
|
+
print("\n")
|
80
|
+
print(f"The [blue]global negative responses[/blue] of '{dl.short_name}' are: ")
|
64
81
|
for gnr in dl.global_negative_responses:
|
65
|
-
|
82
|
+
if plumbing_output:
|
83
|
+
print(f" {gnr}")
|
84
|
+
else:
|
85
|
+
print(f" {gnr.short_name}")
|
66
86
|
|
67
87
|
if print_services and len(all_services) > 0:
|
68
88
|
services = [s for s in all_services if service_filter(s)]
|
69
89
|
if len(services) > 0:
|
70
|
-
print(
|
90
|
+
print("\n")
|
91
|
+
print(f"The [blue]services[/blue] of '{dl.short_name}' are: ")
|
71
92
|
for service in services:
|
72
93
|
if isinstance(service, DiagService):
|
73
94
|
print_diagnostic_service(
|
@@ -77,21 +98,26 @@ def print_summary(
|
|
77
98
|
print_state_transitions=print_state_transitions,
|
78
99
|
print_audiences=print_audiences,
|
79
100
|
allow_unknown_bit_lengths=allow_unknown_bit_lengths,
|
80
|
-
|
101
|
+
plumbing_output=plumbing_output)
|
81
102
|
elif isinstance(service, SingleEcuJob):
|
82
|
-
print(f" Single ECU job: {service.odx_id}")
|
103
|
+
print(f" [blue]Single ECU job[/blue]: {service.odx_id}")
|
83
104
|
else:
|
84
105
|
print(f" Unidentifiable service: {service}")
|
85
106
|
|
86
107
|
if print_dops and len(data_object_properties) > 0:
|
87
|
-
print(
|
108
|
+
print("\n")
|
109
|
+
print(f"The [blue]DOPs[/blue] of the {dl.variant_type.value} '{dl.short_name}' are: ")
|
88
110
|
for dop in sorted(
|
89
111
|
data_object_properties, key=lambda x: (type(x).__name__, x.short_name)):
|
90
|
-
|
112
|
+
if plumbing_output:
|
113
|
+
print(" " + str(dop).replace("\n", "\n "))
|
114
|
+
else:
|
115
|
+
print(" " + str(dop.short_name).replace("\n", "\n "))
|
91
116
|
|
92
117
|
if print_comparams and len(comparams) > 0:
|
118
|
+
print("\n")
|
93
119
|
print(
|
94
|
-
f"The communication parameters of the {dl.variant_type.value} '{dl.short_name}' are: "
|
120
|
+
f"The [blue]communication parameters[/blue] of the {dl.variant_type.value} '{dl.short_name}' are: "
|
95
121
|
)
|
96
122
|
for com_param in comparams:
|
97
123
|
print(f" {com_param.short_name}: {com_param.value}")
|
@@ -178,6 +204,14 @@ def add_subparser(subparsers: "argparse._SubParsersAction") -> None:
|
|
178
204
|
help="Print a list of all diagnostic services and DOPs specified in the pdx",
|
179
205
|
)
|
180
206
|
|
207
|
+
parser.add_argument(
|
208
|
+
"-po",
|
209
|
+
"--plumbing-output",
|
210
|
+
action="store_true",
|
211
|
+
required=False,
|
212
|
+
help="Print full objects instead of selected and formatted attributes",
|
213
|
+
)
|
214
|
+
|
181
215
|
|
182
216
|
def run(args: argparse.Namespace) -> None:
|
183
217
|
odxdb = _parser_utils.load_file(args)
|
@@ -201,4 +235,4 @@ def run(args: argparse.Namespace) -> None:
|
|
201
235
|
print_state_transitions=args.all,
|
202
236
|
print_audiences=args.all,
|
203
237
|
allow_unknown_bit_lengths=args.all,
|
204
|
-
|
238
|
+
plumbing_output=args.plumbing_output)
|
odxtools/cli/main.py
CHANGED
@@ -9,7 +9,7 @@ from .dummy_sub_parser import DummyTool
|
|
9
9
|
# import the tool modules which can be loaded. if a tool
|
10
10
|
# can't be loaded, add a dummy one
|
11
11
|
tool_modules: List[Any] = []
|
12
|
-
for tool_name in ["list", "browse", "snoop", "find", "decode"]:
|
12
|
+
for tool_name in ["list", "browse", "snoop", "find", "decode", "compare"]:
|
13
13
|
try:
|
14
14
|
tool_modules.append(importlib.import_module(f".{tool_name}", package="odxtools.cli"))
|
15
15
|
except Exception as e:
|
odxtools/database.py
CHANGED
odxtools/diagcodedtype.py
CHANGED
@@ -142,6 +142,8 @@ class DiagCodedType(abc.ABC):
|
|
142
142
|
"""Convert the internal_value to bytes."""
|
143
143
|
# Check that bytes and strings actually fit into the bit length
|
144
144
|
if base_data_type == DataType.A_BYTEFIELD:
|
145
|
+
if isinstance(internal_value, bytearray):
|
146
|
+
internal_value = bytes(internal_value)
|
145
147
|
if not isinstance(internal_value, bytes):
|
146
148
|
odxraise()
|
147
149
|
if 8 * len(internal_value) > bit_length:
|
odxtools/version.py
CHANGED