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/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 into their named parameters.",
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) -> None:
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 & print services by hex-data, or name. Can also decode the request.",
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
- odxdb: Database,
19
- print_global_negative_responses: bool = False,
20
- print_services: bool = False,
21
- print_dops: bool = False,
22
- print_params: bool = False,
23
- print_comparams: bool = False,
24
- print_pre_condition_states: bool = False,
25
- print_state_transitions: bool = False,
26
- print_audiences: bool = False,
27
- allow_unknown_bit_lengths: bool = False,
28
- variants: Optional[str] = None,
29
- service_filter: Callable[[DiagComm], bool] = lambda x: True,
30
- ) -> None:
31
-
32
- diag_layer_names = variants if variants else [dl.short_name for dl in odxdb.diag_layers]
33
-
34
- for dl_sn in diag_layer_names:
35
- dl = odxdb.diag_layers[dl_sn]
36
- if not dl:
37
- print(f"The variant '{dl_sn}' could not be found!")
38
- continue
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(f" CAN receive ID for protocol '{proto.short_name}': 0x{can_rx_id:x}")
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(f" CAN send ID for protocol '{proto.short_name}': 0x{can_tx_id:x}")
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(f"The global negative responses of '{dl.short_name}' are: ")
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
- print(f" {gnr}")
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(f"The services of '{dl.short_name}' are: ")
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(f"The DOPs of the {dl.variant_type} '{dl.short_name}' are: ")
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
- print(" " + str(dop).replace("\n", "\n "))
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
@@ -4,6 +4,7 @@ from pathlib import Path
4
4
  from typing import List, Optional
5
5
  from xml.etree import ElementTree
6
6
  from zipfile import ZipFile
7
+
7
8
  from packaging.version import Version
8
9
 
9
10
  from .comparamspec import ComparamSpec
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
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '6.4.3'
16
- __version_tuple__ = version_tuple = (6, 4, 3)
15
+ __version__ = version = '6.5.0'
16
+ __version_tuple__ = version_tuple = (6, 5, 0)