From 0caf5fe0c80259bb8ac9e4709c973c7d965d849d Mon Sep 17 00:00:00 2001 From: Seneda Date: Tue, 12 May 2020 20:20:17 +0100 Subject: [PATCH] Fix sym.dump to export the value_table into the {ENUMS} field of the (#481) .sym file. Refactor to remove the use of global variables "enum_dict" and "enums" Add a test which checks that enums in the original .sym file and enums which appear as values on a signal are exported to the .sym file. --- src/canmatrix/formats/sym.py | 30 +++++++++++++---------- src/canmatrix/tests/test_sym.py | 42 ++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/canmatrix/formats/sym.py b/src/canmatrix/formats/sym.py index 75678647..b9557d5a 100644 --- a/src/canmatrix/formats/sym.py +++ b/src/canmatrix/formats/sym.py @@ -38,8 +38,6 @@ import canmatrix.utils logger = logging.getLogger(__name__) -enum_dict = {} # type: typing.Dict[str, str] -enums = "{ENUMS}\n" def default_float_factory(value): # type: (typing.Any) -> decimal.Decimal @@ -101,8 +99,6 @@ def format_float(f): # type: (typing.Any) -> str def create_signal(db, signal): # type: (canmatrix.CanMatrix, canmatrix.Signal) -> str - global enums - global enum_dict output = "" if sys.version_info > (3, 0): quote_name = not signal.name.isidentifier() @@ -159,12 +155,7 @@ def create_signal(db, signal): # type: (canmatrix.CanMatrix, canmatrix.Signal) val_tab_name = signal.name output += "/e:%s " % val_tab_name - if val_tab_name not in enum_dict: - enum_dict[val_tab_name] = "enum " + val_tab_name + "(" + ', '.join( - '%s="%s"' % - (key, val) for ( - key, val) in sorted( - signal.values.items())) + ")" + default = signal.initial_value # type: ignore min_ok = signal.min is None or default >= signal.min @@ -182,17 +173,31 @@ def create_signal(db, signal): # type: (canmatrix.CanMatrix, canmatrix.Signal) output += "\n" return output +def create_enum_from_signal_values(signal): + enum_dict = {} + if len(signal.values) > 0: + val_tab_name = signal.enumeration + if val_tab_name is None: + val_tab_name = signal.name + + if val_tab_name not in enum_dict: + enum_dict[val_tab_name] = "enum " + val_tab_name + "(" + ', '.join( + '%s="%s"' % + (key, val) for ( + key, val) in sorted( + signal.values.items())) + ")" + return enum_dict def dump(db, f, **options): # type: (canmatrix.CanMatrix, typing.IO, **typing.Any) -> None """ export canmatrix-object as .sym file (compatible to PEAK-Systems) """ - global enum_dict - global enums sym_encoding = options.get('symExportEncoding', 'iso-8859-1') ignore_encoding_errors = options.get("ignoreExportEncodingErrors", "") enum_dict = {} + for enum_name, enum_values in db.value_tables.items(): + enum_dict[enum_name] = "enum {}({})".format(enum_name, ', '.join('{}="{}"'.format(*items) for items in sorted(enum_values.items()))) enums = "{ENUMS}\n" header = """\ @@ -308,6 +313,7 @@ def send_receive(for_frame): output += "CycleTime=" + str(frame.effective_cycle_time) + "\n" for signal in frame.signals: output += create_signal(db, signal) + enum_dict.update(create_enum_from_signal_values(signal)) output += "\n" enums += '\n'.join(sorted(enum_dict.values())) # write output file diff --git a/src/canmatrix/tests/test_sym.py b/src/canmatrix/tests/test_sym.py index cb99d691..ff899745 100644 --- a/src/canmatrix/tests/test_sym.py +++ b/src/canmatrix/tests/test_sym.py @@ -212,13 +212,49 @@ def test_enums_read(enum_str, enum_dict, enum_label): {{ENUMS}} {} '''.format(enum_str).encode('utf-8'), - ) + ) matrix = canmatrix.formats.sym.load(f) assert matrix.load_errors == [], "Failed to load canmatrix, when testing enum case : '{}'".format(enum_label) assert matrix.value_tables == enum_dict, "Enum not parsed correctly : '{}'".format(enum_label) - f_out = io.BytesIO() - canmatrix.formats.sym.dump(matrix, f_out) + + +def test_enums_export(): + f = io.BytesIO('''\ +FormatVersion=5.0 // Do not edit this line! +Title="An Example Title" + +{ENUMS} +enum Animal(0="Dog",1="Cat",2="Fox") + +{SENDRECEIVE} + +[Frame1] +ID=000h +DLC=8 +Var=Signal1 unsigned 0,16 +'''.encode('utf-8'), + ) + + matrix = canmatrix.formats.sym.load(f) + assert matrix.load_errors == [], "Failed to load canmatrix" + + # Add an enum to Signal1 + matrix.frame_by_name("Frame1").signal_by_name("Signal1").enumeration = "Plants" + matrix.frame_by_name("Frame1").signal_by_name("Signal1").values = {0: "Grass", 1: "Flower", 2: "Tree"} + + # Export and reimport + f_out = io.BytesIO() + canmatrix.formats.sym.dump(matrix, f_out) + f_in = io.BytesIO(f_out.getvalue()) + new_matrix = canmatrix.formats.sym.load(f_in) + + # Check that Enums from Enums table exported and reimported correctly + assert new_matrix.value_tables["Animal"] == {0: "Dog", 1: "Cat", 2: "Fox"} + + # Check that Enums from a Signal.Values property exported and reimported correctly + assert new_matrix.value_tables["Plants"] == {0: "Grass", 1: "Flower", 2: "Tree"} + def test_types_read():