Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/Tools/autotest/param_metadata/xmlemit.py
Views: 1799
from lxml import etree12from emit import Emit3from param import known_param_fields, known_units4import re56# Emit ArduPilot documentation in an machine readable XML format7class XmlEmit(Emit):8def __init__(self, *args, **kwargs):9Emit.__init__(self, *args, **kwargs)10self.wiki_fname = 'apm.pdef.xml'11self.f = open(self.wiki_fname, mode='w')12self.preamble = '''<?xml version="1.0" encoding="utf-8"?>13<!-- Dynamically generated list of documented parameters (generated by param_parse.py) -->14'''15self.f.write(self.preamble)16self.paramfile = etree.Element('paramfile')17self.vehicles = etree.SubElement(self.paramfile, 'vehicles')18self.libraries = etree.SubElement(self.paramfile, 'libraries')19self.current_element = self.vehicles2021def close(self):22# etree.indent(self.paramfile) # not available on thor, Ubuntu 16.0423pretty_xml = etree.tostring(self.paramfile, pretty_print=True, encoding='unicode')24self.f.write(pretty_xml)25self.f.close()2627def emit_comment(self, s):28self.f.write("<!-- " + s + " -->")2930def start_libraries(self):31self.current_element = self.libraries3233def add_xml_subtree_for_param_field(self, param, xml_param, field, new_element_name, item_name):34'''assumes that "field" is a comma-separated list of items,35creates a subtree with those elements within'''36xml_values = etree.SubElement(xml_param, new_element_name)37values = (param.__dict__[field]).split(',')38nv_unsorted = {}39for value in values:40v = value.split(':')41if len(v) != 2:42raise ValueError("Bad value (%s)" % v)43# i.e. numeric value, string label44if v[0] in nv_unsorted:45raise ValueError("%s already exists" % v[0])46nv_unsorted[v[0]] = v[1]4748all_keys = nv_unsorted.keys()49if hasattr(param, 'SortValues'):50sort = getattr(param, 'SortValues').lower()51zero_at_top = False52if sort == 'alphabeticalzeroattop':53zero_at_top = True54else:55raise ValueError("Unknown sort (%s)" % sort)5657all_keys = self.sorted_Values_keys(nv_unsorted, zero_at_top=zero_at_top)5859for key in all_keys:60value = nv_unsorted[key].strip()61code = key.rstrip().strip()62xml_value = etree.SubElement(xml_values, item_name, code=code)63xml_value.text = value6465def sorted_Values_keys(self, nv_pairs, zero_at_top=False):66'''sorts name/value pairs derived from items in @Values. Sorts by67value, with special attention paid to common "Do nothing" values'''68keys = nv_pairs.keys()69def sort_key(value):70description = nv_pairs[value]71if zero_at_top:72# make sure -1 and 0 appear at the top of the list73if value == "-1":74return "0000000"75if value == "0":76return "0000001"77return description78return sorted(keys, key=sort_key)7980def emit(self, g):81xml_parameters = etree.SubElement(self.current_element, 'parameters', name=g.reference) # i.e. ArduPlane8283for param in g.params:84# Begin our parameter node85if hasattr(param, 'DisplayName'):86xml_param = etree.SubElement(xml_parameters, 'param', humanName=param.DisplayName, name=param.name) # i.e. ArduPlane (ArduPlane:FOOPARM)87else:88xml_param = etree.SubElement(xml_parameters, 'param', name=param.name)8990if hasattr(param, 'Description'):91xml_param.set('documentation', param.Description) # i.e. parameter docs92if hasattr(param, 'User'):93xml_param.set('user', param.User) # i.e. Standard or Advanced9495if hasattr(param, 'Calibration'):96xml_param.set('calibration', param.Calibration)9798# Add values as chidren of this node99for field in param.__dict__.keys():100if not self.should_emit_field(param, field):101continue102if field not in ['name', 'DisplayName', 'Description', 'User', 'SortValues'] and field in known_param_fields:103# we emit Bitmask as both a sub-element (so that104# consumers don't need to parse the Bimask list),105# but also as a text so we don't break existing106# implementations. Contrast with "values", which107# is only emitted as a sub-element.108if field == 'Bitmask':109self.add_xml_subtree_for_param_field(110param,111xml_param,112field='Bitmask',113new_element_name='bitmask',114item_name='bit',115)116117if field == 'Values' and Emit.prog_values_field.match(param.__dict__[field]):118self.add_xml_subtree_for_param_field(119param,120xml_param,121field='Values',122new_element_name='values',123item_name='value',124)125126elif field == 'Units':127abreviated_units = param.__dict__[field]128if abreviated_units != '':129units = known_units[abreviated_units] # use the known_units dictionary to convert the abreviated unit into a full textual one130xml_field1 = etree.SubElement(xml_param, 'field', name=field) # i.e. A/s131xml_field1.text = abreviated_units132xml_field2 = etree.SubElement(xml_param, 'field', name='UnitText') # i.e. ampere per second133xml_field2.text = units134else:135xml_field = etree.SubElement(xml_param, 'field', name=field)136xml_field.text = param.__dict__[field]137138if xml_param.text is None and not len(xml_param):139xml_param.text = '\n' # add </param> on next line in case of empty element.140141142