|
23 | 23 | from pathlib import Path |
24 | 24 | from typing import Any, Generator, Iterable, Iterator |
25 | 25 |
|
26 | | -import colorama |
27 | | - |
28 | 26 | # The following import needs care when importing node |
29 | 27 | from objdictgen import eds_utils, gen_cfile, jsonod, maps, nosis |
30 | 28 | from objdictgen.maps import OD, ODMapping, ODMappingList |
|
33 | 31 |
|
34 | 32 | log = logging.getLogger('objdictgen') |
35 | 33 |
|
36 | | -Fore = colorama.Fore |
37 | | -Style = colorama.Style |
38 | | - |
39 | 34 |
|
40 | 35 | # ------------------------------------------------------------------------------ |
41 | 36 | # Definition of Node Object |
@@ -1000,198 +995,6 @@ def _warn(text: str): |
1000 | 995 | subvals["name"] = f"Subindex {idx}" |
1001 | 996 | _warn(f"FIX: Set name to '{subvals['name']}'") |
1002 | 997 |
|
1003 | | - # -------------------------------------------------------------------------- |
1004 | | - # Printing and output |
1005 | | - # -------------------------------------------------------------------------- |
1006 | | - |
1007 | | - def GetPrintEntryHeader( |
1008 | | - self, index: int, unused=False, compact=False, raw=False, |
1009 | | - entry: TIndexEntry|None = None |
1010 | | - ) -> tuple[str, dict[str, str]]: |
1011 | | - |
1012 | | - # Get the information about the index if it wasn't passed along |
1013 | | - if not entry: |
1014 | | - entry = self.GetIndexEntry(index, withbase=True) |
1015 | | - obj = entry["object"] |
1016 | | - |
1017 | | - # Get the flags for the entry |
1018 | | - flags: set[str] = set() |
1019 | | - for group in entry["groups"]: |
1020 | | - v = { |
1021 | | - "built-in": None, |
1022 | | - "user": "User", |
1023 | | - "ds302": "DS-302", |
1024 | | - "profile": "Profile", |
1025 | | - }.get(group, group) |
1026 | | - if v: |
1027 | | - flags.add(v) |
1028 | | - if obj.get('need'): |
1029 | | - flags.add("Mandatory") |
1030 | | - if entry.get("params", {}).get("callback"): |
1031 | | - flags.add('CB') |
1032 | | - if "dictionary" not in entry: |
1033 | | - if "ds302" in entry["groups"] or "profile" in entry["groups"]: |
1034 | | - flags.add("Unused") |
1035 | | - else: |
1036 | | - flags.add("Missing") |
1037 | | - |
1038 | | - # Skip printing if the entry is unused and we are not printing unused |
1039 | | - if 'Unused' in flags and not unused: |
1040 | | - return '', {} |
1041 | | - |
1042 | | - # Replace flags for formatting |
1043 | | - for _, flag in enumerate(flags.copy()): |
1044 | | - if flag == 'Missing': |
1045 | | - flags.discard('Missing') |
1046 | | - flags.add(Fore.RED + ' *MISSING* ' + Style.RESET_ALL) |
1047 | | - |
1048 | | - # Print formattings |
1049 | | - idx = (index - entry.get("base", index)) // obj.get("incr", 1) + 1 |
1050 | | - t_name = obj['name'] |
1051 | | - if not raw: |
1052 | | - t_name = maps.eval_name(t_name, idx=idx, sub=0) |
1053 | | - t_flags = ', '.join(flags) |
1054 | | - t_string = maps.ODStructTypes.to_string(obj['struct']) or '???' |
1055 | | - |
1056 | | - # ** PRINT PARAMETER ** |
1057 | | - return "{pre}{key} {name} {struct}{flags}", { |
1058 | | - 'key': f"{Fore.LIGHTGREEN_EX}0x{index:04x} ({index}){Style.RESET_ALL}", |
1059 | | - 'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}", |
1060 | | - 'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}", |
1061 | | - 'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '', |
1062 | | - 'pre': ' ' if not compact else '', |
1063 | | - } |
1064 | | - |
1065 | | - def GetPrintEntry( |
1066 | | - self, keys: list[int]|None = None, short=False, compact=False, |
1067 | | - unused=False, verbose=False, raw=False, |
1068 | | - ) -> Generator[str, None, None]: |
1069 | | - """ |
1070 | | - Generator for printing the dictionary values |
1071 | | - """ |
1072 | | - |
1073 | | - # Get the indexes to print and determine the order |
1074 | | - keys = keys or self.GetAllIndices(sort=True) |
1075 | | - |
1076 | | - index_range = None |
1077 | | - for k in keys: |
1078 | | - |
1079 | | - # Get the index entry information |
1080 | | - param = self.GetIndexEntry(k, withbase=True) |
1081 | | - obj = param["object"] |
1082 | | - |
1083 | | - # Get the header for the entry |
1084 | | - line, fmt = self.GetPrintEntryHeader( |
1085 | | - k, unused=unused, compact=compact, entry=param, raw=raw |
1086 | | - ) |
1087 | | - if not line: |
1088 | | - continue |
1089 | | - |
1090 | | - # Print the parameter range header |
1091 | | - ir = maps.INDEX_RANGES.get_index_range(k) |
1092 | | - if index_range != ir: |
1093 | | - index_range = ir |
1094 | | - if not compact: |
1095 | | - yield Fore.YELLOW + ir.description + Style.RESET_ALL |
1096 | | - |
1097 | | - # Yield the parameter header |
1098 | | - yield line.format(**fmt) |
1099 | | - |
1100 | | - # Omit printing sub index data if: |
1101 | | - if short: |
1102 | | - continue |
1103 | | - |
1104 | | - # Fetch the dictionary values and the parameters, if present |
1105 | | - if k in self.Dictionary: |
1106 | | - values = self.GetEntry(k, aslist=True, compute=not raw) |
1107 | | - else: |
1108 | | - values = ['__N/A__'] * len(obj["values"]) |
1109 | | - if k in self.ParamsDictionary: |
1110 | | - params = self.GetParamsEntry(k, aslist=True) |
1111 | | - else: |
1112 | | - params = [maps.DEFAULT_PARAMS] * len(obj["values"]) |
1113 | | - # For mypy to ensure that values and entries are lists |
1114 | | - assert isinstance(values, list) and isinstance(params, list) |
1115 | | - |
1116 | | - infos = [] |
1117 | | - for i, (value, param) in enumerate(zip(values, params)): |
1118 | | - |
1119 | | - # Prepare data for printing |
1120 | | - info = self.GetSubentryInfos(k, i) |
1121 | | - typename = self.GetTypeName(info['type']) |
1122 | | - |
1123 | | - # Type specific formatting of the value |
1124 | | - if value == "__N/A__": |
1125 | | - t_value = f'{Fore.LIGHTBLACK_EX}N/A{Style.RESET_ALL}' |
1126 | | - elif isinstance(value, str): |
1127 | | - length = len(value) |
1128 | | - if typename == 'DOMAIN': |
1129 | | - value = value.encode('unicode_escape').decode() |
1130 | | - t_value = '"' + value + f'" ({length})' |
1131 | | - elif i and index_range and index_range.name in ('rpdom', 'tpdom'): |
1132 | | - # FIXME: In PDO mappings, the value is ints |
1133 | | - assert isinstance(value, int) |
1134 | | - index, subindex, _ = self.GetMapIndex(value) |
1135 | | - try: |
1136 | | - pdo = self.GetSubentryInfos(index, subindex) |
1137 | | - t_v = f"{value:x}" |
1138 | | - t_value = f"0x{t_v[0:4]}_{t_v[4:6]}_{t_v[6:]} {Fore.LIGHTCYAN_EX}{pdo['name']}{Style.RESET_ALL}" |
1139 | | - except ValueError: |
1140 | | - suffix = ' ???' if value else '' |
1141 | | - t_value = f"0x{value:x}{suffix}" |
1142 | | - elif i and value and (k in (4120, ) or 'COB ID' in info["name"]): |
1143 | | - t_value = f"0x{value:x}" |
1144 | | - else: |
1145 | | - t_value = str(value) |
1146 | | - |
1147 | | - # Add comment if present |
1148 | | - t_comment = param['comment'] or '' |
1149 | | - if t_comment: |
1150 | | - t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}" |
1151 | | - |
1152 | | - # Omit printing the first element unless specifically requested |
1153 | | - if (not verbose and i == 0 |
1154 | | - and obj['struct'] & OD.MultipleSubindexes |
1155 | | - and not t_comment |
1156 | | - ): |
1157 | | - continue |
1158 | | - |
1159 | | - # Print formatting |
1160 | | - infos.append({ |
1161 | | - 'i': f"{Fore.GREEN}{i:02d}{Style.RESET_ALL}", |
1162 | | - 'access': info['access'], |
1163 | | - 'pdo': 'P' if info['pdo'] else ' ', |
1164 | | - 'name': info['name'], |
1165 | | - 'type': f"{Fore.LIGHTBLUE_EX}{typename}{Style.RESET_ALL}", |
1166 | | - 'value': t_value, |
1167 | | - 'comment': t_comment, |
1168 | | - 'pre': fmt['pre'], |
1169 | | - }) |
1170 | | - |
1171 | | - # Must skip the next step if list is empty, as the first element is |
1172 | | - # used for the header |
1173 | | - if not infos: |
1174 | | - continue |
1175 | | - |
1176 | | - # Calculate the max width for each of the columns |
1177 | | - w = { |
1178 | | - col: max(len(str(row[col])) for row in infos) or '' |
1179 | | - for col in infos[0] |
1180 | | - } |
1181 | | - |
1182 | | - # Generate a format string based on the calculcated column widths |
1183 | | - # Legitimate use of % as this is making a string containing format specifiers |
1184 | | - fmt = "{pre} {i:%ss} {access:%ss} {pdo:%ss} {name:%ss} {type:%ss} {value:%ss} {comment}" % ( |
1185 | | - w["i"], w["access"], w["pdo"], w["name"], w["type"], w["value"] |
1186 | | - ) |
1187 | | - |
1188 | | - # Print each line using the generated format string |
1189 | | - for infoentry in infos: |
1190 | | - yield fmt.format(**infoentry) |
1191 | | - |
1192 | | - if not compact and infos: |
1193 | | - yield "" |
1194 | | - |
1195 | 998 |
|
1196 | 999 | # Register node with gnosis |
1197 | 1000 | nosis.add_class_to_store('Node', Node) |
0 commit comments