2222
2323logger = logging .getLogger (__name__ )
2424
25+
2526def import_eds (source , node_id ):
2627 eds = RawConfigParser (inline_comment_prefixes = (';' ,))
2728 eds .optionxform = str
@@ -133,20 +134,22 @@ def import_eds(source, node_id):
133134 od .add_object (var )
134135 elif object_type == objectcodes .ARRAY and eds .has_option (section , "CompactSubObj" ):
135136 arr = ODArray (name , index )
136- last_subindex = ODVariable (
137- "Number of entries" , index , 0 )
137+ last_subindex = ODVariable ("Number of entries" , index , 0 )
138138 last_subindex .data_type = datatypes .UNSIGNED8
139139 arr .add_member (last_subindex )
140140 arr .add_member (build_variable (eds , section , node_id , object_type , index , 1 ))
141141 arr .storage_location = storage_location
142+ arr .custom_options = _get_custom_options (eds , section )
142143 od .add_object (arr )
143144 elif object_type == objectcodes .ARRAY :
144145 arr = ODArray (name , index )
145146 arr .storage_location = storage_location
147+ arr .custom_options = _get_custom_options (eds , section )
146148 od .add_object (arr )
147149 elif object_type == objectcodes .RECORD :
148150 record = ODRecord (name , index )
149151 record .storage_location = storage_location
152+ record .custom_options = _get_custom_options (eds , section )
150153 od .add_object (record )
151154
152155 continue
@@ -257,6 +260,25 @@ def _revert_variable(var_type, value):
257260 else :
258261 return f"0x{ value :02X} "
259262
263+ _STANDARD_OPTIONS = {
264+ "ObjectType" , "ParameterName" , "DataType" , "AccessType" ,
265+ "PDOMapping" , "LowLimit" , "HighLimit" , "DefaultValue" ,
266+ "ParameterValue" , "Factor" , "Description" , "Unit" ,
267+ "StorageLocation" , "CompactSubObj" ,
268+ # CiA 306 fields parsed explicitly:
269+ "SubNumber" ,
270+ # ObjFlags and Denotation are intentionally absent: they are not yet
271+ # parsed by this codebase, so they flow through custom_options and
272+ # survive round-trips. Proper first-class support is tracked in #654.
273+ }
274+
275+ def _get_custom_options (eds , section ):
276+ custom_options = {}
277+ for option , value in eds .items (section ):
278+ if option not in _STANDARD_OPTIONS :
279+ custom_options [option ] = value
280+ return custom_options
281+
260282
261283def build_variable (
262284 eds : RawConfigParser ,
@@ -350,6 +372,8 @@ def build_variable(
350372 var .unit = eds .get (section , "Unit" )
351373 except ValueError :
352374 pass
375+
376+ var .custom_options = _get_custom_options (eds , section )
353377 return var
354378
355379
@@ -359,6 +383,8 @@ def copy_variable(eds, section, subindex, src_var):
359383 # It is only the name and subindex that varies
360384 var .name = name
361385 var .subindex = subindex
386+ # Give the copy its own custom_options dict to avoid shared-state mutations
387+ var .custom_options = src_var .custom_options .copy ()
362388 return var
363389
364390
@@ -425,12 +451,19 @@ def export_variable(var, eds):
425451 if getattr (var , 'unit' , '' ) != '' :
426452 eds .set (section , "Unit" , var .unit )
427453
454+ for option , value in var .custom_options .items ():
455+ if option not in _STANDARD_OPTIONS :
456+ eds .set (section , option , str (value ))
457+
428458 def export_record (var , eds ):
429459 section = f"{ var .index :04X} "
430460 export_common (var , eds , section )
431461 eds .set (section , "SubNumber" , f"0x{ len (var .subindices ):X} " )
432462 ot = objectcodes .RECORD if isinstance (var , ODRecord ) else objectcodes .ARRAY
433463 eds .set (section , "ObjectType" , f"0x{ ot :X} " )
464+ for option , value in var .custom_options .items ():
465+ if option not in _STANDARD_OPTIONS :
466+ eds .set (section , option , str (value ))
434467 for i in var :
435468 export_variable (var [i ], eds )
436469
0 commit comments