Skip to content

Commit 0caf5fe

Browse files
authored
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.
1 parent ef4d76e commit 0caf5fe

File tree

2 files changed

+57
-15
lines changed

2 files changed

+57
-15
lines changed

Diff for: src/canmatrix/formats/sym.py

+18-12
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
import canmatrix.utils
3939

4040
logger = logging.getLogger(__name__)
41-
enum_dict = {} # type: typing.Dict[str, str]
42-
enums = "{ENUMS}\n"
4341

4442

4543
def default_float_factory(value): # type: (typing.Any) -> decimal.Decimal
@@ -101,8 +99,6 @@ def format_float(f): # type: (typing.Any) -> str
10199

102100

103101
def create_signal(db, signal): # type: (canmatrix.CanMatrix, canmatrix.Signal) -> str
104-
global enums
105-
global enum_dict
106102
output = ""
107103
if sys.version_info > (3, 0):
108104
quote_name = not signal.name.isidentifier()
@@ -159,12 +155,7 @@ def create_signal(db, signal): # type: (canmatrix.CanMatrix, canmatrix.Signal)
159155
val_tab_name = signal.name
160156

161157
output += "/e:%s " % val_tab_name
162-
if val_tab_name not in enum_dict:
163-
enum_dict[val_tab_name] = "enum " + val_tab_name + "(" + ', '.join(
164-
'%s="%s"' %
165-
(key, val) for (
166-
key, val) in sorted(
167-
signal.values.items())) + ")"
158+
168159

169160
default = signal.initial_value # type: ignore
170161
min_ok = signal.min is None or default >= signal.min
@@ -182,17 +173,31 @@ def create_signal(db, signal): # type: (canmatrix.CanMatrix, canmatrix.Signal)
182173
output += "\n"
183174
return output
184175

176+
def create_enum_from_signal_values(signal):
177+
enum_dict = {}
178+
if len(signal.values) > 0:
179+
val_tab_name = signal.enumeration
180+
if val_tab_name is None:
181+
val_tab_name = signal.name
182+
183+
if val_tab_name not in enum_dict:
184+
enum_dict[val_tab_name] = "enum " + val_tab_name + "(" + ', '.join(
185+
'%s="%s"' %
186+
(key, val) for (
187+
key, val) in sorted(
188+
signal.values.items())) + ")"
189+
return enum_dict
185190

186191
def dump(db, f, **options): # type: (canmatrix.CanMatrix, typing.IO, **typing.Any) -> None
187192
"""
188193
export canmatrix-object as .sym file (compatible to PEAK-Systems)
189194
"""
190-
global enum_dict
191-
global enums
192195
sym_encoding = options.get('symExportEncoding', 'iso-8859-1')
193196
ignore_encoding_errors = options.get("ignoreExportEncodingErrors", "")
194197

195198
enum_dict = {}
199+
for enum_name, enum_values in db.value_tables.items():
200+
enum_dict[enum_name] = "enum {}({})".format(enum_name, ', '.join('{}="{}"'.format(*items) for items in sorted(enum_values.items())))
196201
enums = "{ENUMS}\n"
197202

198203
header = """\
@@ -308,6 +313,7 @@ def send_receive(for_frame):
308313
output += "CycleTime=" + str(frame.effective_cycle_time) + "\n"
309314
for signal in frame.signals:
310315
output += create_signal(db, signal)
316+
enum_dict.update(create_enum_from_signal_values(signal))
311317
output += "\n"
312318
enums += '\n'.join(sorted(enum_dict.values()))
313319
# write output file

Diff for: src/canmatrix/tests/test_sym.py

+39-3
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,49 @@ def test_enums_read(enum_str, enum_dict, enum_label):
212212
{{ENUMS}}
213213
{}
214214
'''.format(enum_str).encode('utf-8'),
215-
)
215+
)
216216

217217
matrix = canmatrix.formats.sym.load(f)
218218
assert matrix.load_errors == [], "Failed to load canmatrix, when testing enum case : '{}'".format(enum_label)
219219
assert matrix.value_tables == enum_dict, "Enum not parsed correctly : '{}'".format(enum_label)
220-
f_out = io.BytesIO()
221-
canmatrix.formats.sym.dump(matrix, f_out)
220+
221+
222+
def test_enums_export():
223+
f = io.BytesIO('''\
224+
FormatVersion=5.0 // Do not edit this line!
225+
Title="An Example Title"
226+
227+
{ENUMS}
228+
enum Animal(0="Dog",1="Cat",2="Fox")
229+
230+
{SENDRECEIVE}
231+
232+
[Frame1]
233+
ID=000h
234+
DLC=8
235+
Var=Signal1 unsigned 0,16
236+
'''.encode('utf-8'),
237+
)
238+
239+
matrix = canmatrix.formats.sym.load(f)
240+
assert matrix.load_errors == [], "Failed to load canmatrix"
241+
242+
# Add an enum to Signal1
243+
matrix.frame_by_name("Frame1").signal_by_name("Signal1").enumeration = "Plants"
244+
matrix.frame_by_name("Frame1").signal_by_name("Signal1").values = {0: "Grass", 1: "Flower", 2: "Tree"}
245+
246+
# Export and reimport
247+
f_out = io.BytesIO()
248+
canmatrix.formats.sym.dump(matrix, f_out)
249+
f_in = io.BytesIO(f_out.getvalue())
250+
new_matrix = canmatrix.formats.sym.load(f_in)
251+
252+
# Check that Enums from Enums table exported and reimported correctly
253+
assert new_matrix.value_tables["Animal"] == {0: "Dog", 1: "Cat", 2: "Fox"}
254+
255+
# Check that Enums from a Signal.Values property exported and reimported correctly
256+
assert new_matrix.value_tables["Plants"] == {0: "Grass", 1: "Flower", 2: "Tree"}
257+
222258

223259

224260
def test_types_read():

0 commit comments

Comments
 (0)