2424
2525XLS_HEADER_MAGIC = b'\xD0 \xCF \x11 \xE0 \xA1 \xB1 \x1A \xE1 '
2626
27+ SYMBOL_NAME_SCRUBBER = re .compile (r'\W|^(?=\d)' )
28+
2729
2830def header (header , indent = 0 ):
29- return '%s%s' % (' ' * indent , (' %s ' % header ).center (78 - indent , '#' ))
31+ return '%s# %s' % (' ' * indent , (' %s ' % header ).center (78 - indent , '*' ))
32+
33+
34+ def scrub_symbol_name (symbol_name ):
35+ return SYMBOL_NAME_SCRUBBER .sub ('_' , symbol_name )
3036
3137
3238PROFILE_HEADER_FIRST_PART = "%s\n %s" % (
@@ -44,6 +50,16 @@ def header(header, indent=0):
4450 BASE_TYPES,
4551)'''
4652
53+ # This allows to prepend the declaration of some message numbers to the
54+ # generated file.
55+ # E.g. 'hr' -> MESG_NUM_HR = 132
56+ MESSAGE_NUM_DECLARATIONS = ()
57+
58+ # This allows to prepend the declaration of some field numbers of specific
59+ # messages to the generated file.
60+ # E.g. 'hr.event_timestamp' -> FIELD_NUM_HR_EVENT_TIMESTAMP = 9
61+ FIELD_NUM_DECLARATIONS = ()
62+
4763SPECIAL_FIELD_DECLARATIONS = "FIELD_TYPE_TIMESTAMP = Field(name='timestamp', type=FIELD_TYPES['date_time'], def_num=" + str (FIELD_NUM_TIMESTAMP ) + ", units='s')"
4864
4965IGNORE_TYPE_VALUES = (
@@ -158,6 +174,22 @@ def __str__(self):
158174 s += '}'
159175 return s
160176
177+ def get_by_name (self , mesg_name ):
178+ for mesg in self .messages :
179+ if mesg .name == mesg_name :
180+ return mesg
181+
182+ raise ValueError ('message "%s" not found' % mesg_name )
183+
184+ def get_field_by_name (self , mesg_name , field_name ):
185+ mesg = self .get_by_name (mesg_name )
186+
187+ for field in mesg .fields :
188+ if field .name == field_name :
189+ return mesg , field
190+
191+ raise ValueError ('field "%s" not found in message "%s"' % (field_name , mesg_name ))
192+
161193
162194class MessageInfo (namedtuple ('MessageInfo' , ('name' , 'num' , 'group_name' , 'fields' , 'comment' ))):
163195 def get (self , field_name ):
@@ -525,6 +557,27 @@ def main(input_xls_or_zip, output_py_path=None):
525557 type_list = parse_types (types_rows )
526558 message_list = parse_messages (messages_rows , type_list )
527559
560+ mesg_num_declarations = []
561+ for mesg_name in MESSAGE_NUM_DECLARATIONS :
562+ mesg_info = message_list .get_by_name (mesg_name )
563+
564+ mesg_num_declarations .append ('MESG_NUM_%s = %s' % (
565+ scrub_symbol_name (mesg_name ).upper (),
566+ str (mesg_info .num ) if mesg_info else 'None' ))
567+
568+ field_num_declarations = [
569+ 'FIELD_NUM_TIMESTAMP = ' + str (FIELD_NUM_TIMESTAMP )]
570+ for field_fqn in FIELD_NUM_DECLARATIONS :
571+ mesg_name , field_name = field_fqn .split ('.' , maxsplit = 1 )
572+ mesg_info , field_info = message_list .get_field_by_name (mesg_name , field_name )
573+
574+ field_decl = 'FIELD_NUM_%s_%s = %s' % (
575+ scrub_symbol_name (mesg_name ).upper (),
576+ scrub_symbol_name (field_name ).upper (),
577+ str (field_info .num ))
578+
579+ field_num_declarations .append (field_decl )
580+
528581 output = '\n ' .join ([
529582 "\n %s" % PROFILE_HEADER_FIRST_PART ,
530583 header ('EXPORTED PROFILE FROM %s ON %s' % (
@@ -535,9 +588,17 @@ def main(input_xls_or_zip, output_py_path=None):
535588 len (type_list .types ), sum (len (ti .values ) for ti in type_list .types ),
536589 len (message_list .messages ), sum (len (mi .fields ) for mi in message_list .messages ),
537590 )),
538- '' , IMPORT_HEADER , '\n ' ,
591+ '' , IMPORT_HEADER
592+ ]) + '\n '
593+
594+ if mesg_num_declarations :
595+ output += '\n \n ' + '\n ' .join (mesg_num_declarations ) + '\n '
596+ if field_num_declarations :
597+ output += '\n \n ' + '\n ' .join (field_num_declarations ) + '\n '
598+
599+ output += '\n \n ' + '\n ' .join ([
539600 str (type_list ), '\n ' ,
540- SPECIAL_FIELD_DECLARTIONS , '\n ' ,
601+ SPECIAL_FIELD_DECLARATIONS , '\n ' ,
541602 str (message_list ), ''
542603 ])
543604
0 commit comments