@@ -206,6 +206,7 @@ def format_od_header(
206206def format_od_object (
207207 node : Node , index : int , * , short = False ,
208208 unused = False , verbose : int = 0 , raw = False ,
209+ widths : dict [str , int ]| None = None
209210) -> Generator [str , None , None ]:
210211 """Return the print formatting for an object dictionary entry."""
211212
@@ -214,12 +215,12 @@ def format_od_object(
214215 obj = param ["object" ]
215216
216217 # Get the header for the entry and output it unless it is empty
217- line , fmt = format_od_header (
218+ line , fields = format_od_header (
218219 node , index , unused = unused , verbose = verbose , entry = param , raw = raw
219220 )
220221 if not line :
221222 return
222- yield line .format (** fmt )
223+ yield line .format (** fields )
223224
224225 # Get the index range title
225226 index_range = maps .INDEX_RANGES .get_index_range (index )
@@ -231,9 +232,11 @@ def format_od_object(
231232 # Fetch the dictionary values and the parameters, if present
232233 if index in node .Dictionary :
233234 values = node .GetEntry (index , aslist = True , compute = not raw )
235+ raw_values = node .GetEntry (index , aslist = True , compute = False )
234236 else :
235237 # Fill the values with N/A if the entry is not present
236238 values = ['__N/A__' ] * len (obj ["values" ])
239+ raw_values = values
237240
238241 if index in node .ParamsDictionary :
239242 # FIXME: Is there a risk that this return less than the length of
@@ -243,16 +246,22 @@ def format_od_object(
243246 params = [maps .DEFAULT_PARAMS ] * len (values )
244247
245248 # For mypy to ensure that values and entries are lists
246- assert isinstance (values , list ) and isinstance (params , list )
249+ assert isinstance (values , list ) and isinstance (raw_values , list ) and isinstance ( params , list )
247250
248251 infos = []
249252 # The strict=True will capture if the values and params are not the same
250- for i , (value , param ) in enumerate (zip (values , params , strict = True )):
253+ for i , (value , raw_value , param ) in enumerate (zip (values , raw_values , params , strict = True )):
251254
252255 # Prepare data for printing
253256 info = node .GetSubentryInfos (index , i )
254257 typename = node .GetTypeName (info ['type' ])
255258
259+ # Adding +NODEID text?
260+ if 'COB ID' in info ["name" ] and isinstance (raw_value , str ) and "$NODEID" in raw_value and not node .ID :
261+ t_node = f"{ Fore .GREEN } +NODEID{ Style .RESET_ALL } "
262+ else :
263+ t_node = ''
264+
256265 # Type specific formatting of the value
257266 if value == "__N/A__" :
258267 t_value = f'{ Fore .LIGHTBLACK_EX } N/A{ Style .RESET_ALL } '
@@ -272,8 +281,13 @@ def format_od_object(
272281 except ValueError :
273282 suffix = ' ???' if value else ''
274283 t_value = f"0x{ value :x} { suffix } "
284+ elif index_range and index_range .name in ('rpdop' , 'tpdop' ):
285+ assert isinstance (value , int )
286+ t_value = f"0x{ value :x} { t_node } " if 'COB ID' in info ["name" ] else f"{ value } { t_node } "
287+ if i == 1 and value & 0x80000000 :
288+ t_value += f" { Fore .LIGHTYELLOW_EX } <DISABLED>{ Style .RESET_ALL } "
275289 elif i and value and (index in (4120 , ) or 'COB ID' in info ["name" ]):
276- t_value = f"0x{ value :x} "
290+ t_value = f"0x{ value :x} { t_node } "
277291 else :
278292 t_value = str (value )
279293
@@ -298,7 +312,7 @@ def format_od_object(
298312 'type' : f"{ Fore .LIGHTBLUE_EX } { typename } { Style .RESET_ALL } " ,
299313 'value' : t_value ,
300314 'comment' : t_comment ,
301- 'pre' : fmt ['pre' ],
315+ 'pre' : fields ['pre' ],
302316 })
303317
304318 # Must skip the next step if list is empty, as the first element is
@@ -307,14 +321,18 @@ def format_od_object(
307321 return
308322
309323 # Calculate the max width for each of the columns
310- w = {
311- col : max (len (str (row [col ])) for row in infos ) or ''
312- for col in infos [0 ]
324+ if widths is None :
325+ widths = {}
326+ colwidths = {
327+ col : max (max (len (str (row [col ])) for row in infos ), widths .get (col , 0 ))
328+ for col in list (infos [0 ]) + list (widths .keys ())
313329 }
330+ widths .update (colwidths )
314331
315332 # Generate a format string based on the calculcated column widths
316333 # Legitimate use of % as this is making a string containing format specifiers
317- fmt = "{pre} {i:%ss} {access:%ss} {pdo:%ss} {name:%ss} {type:%ss} {value:%ss} {comment}" % (
334+ w = {k : v or '' for k , v in colwidths .items ()}
335+ fmt = "{pre} {i:%ss} {access:%ss} {pdo:%ss} {name:%ss} {type:%ss} {value:%ss} {comment}" % ( # type: ignore
318336 w ["i" ], w ["access" ], w ["pdo" ], w ["name" ], w ["type" ], w ["value" ]
319337 )
320338
@@ -416,11 +434,19 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TD
416434 text1 = text2 = []
417435 entry1 : TIndexEntry = {}
418436 entry2 : TIndexEntry = {}
437+
438+ # Run through the formatting to get the width for the columns
439+ widths : dict [str , int ] = {}
440+ if index in keys1 :
441+ list (format_od_object (od1 , index , unused = True , verbose = verbose , widths = widths ))
442+ if index in keys2 :
443+ list (format_od_object (od2 , index , unused = True , verbose = verbose , widths = widths ))
444+
419445 if index in keys1 :
420- text1 = list (format_od_object (od1 , index , unused = True , verbose = verbose ))
446+ text1 = list (format_od_object (od1 , index , unused = True , verbose = verbose , widths = widths ))
421447 entry1 = od1 .GetIndexEntry (index )
422448 if index in keys2 :
423- text2 = list (format_od_object (od2 , index , unused = True , verbose = verbose ))
449+ text2 = list (format_od_object (od2 , index , unused = True , verbose = verbose , widths = widths ))
424450 entry2 = od2 .GetIndexEntry (index )
425451
426452 if data_mode :
0 commit comments