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/rstemit.py
Views: 1799
#!/usr/bin/env python1from __future__ import print_function2import re3from param import known_param_fields, known_units4from emit import Emit5try:6from cgi import escape as cescape7except Exception:8from html import escape as cescape91011# Emit docs in a RST format12class RSTEmit(Emit):13def blurb(self):14return """This is a complete list of the parameters which can be set (e.g. via the MAVLink protocol) to control vehicle behaviour. They are stored in persistent storage on the vehicle.1516This list is automatically generated from the latest ardupilot source code, and so may contain parameters which are not yet in the stable released versions of the code.17""" # noqa1819def toolname(self):20return "Tools/autotest/param_metadata/param_parse.py"2122def output_fname(self):23return 'Parameters.rst'2425def __init__(self, *args, **kwargs):26Emit.__init__(self, *args, **kwargs)27self.f = open(self.output_fname(), mode='w')28self.spacer = re.compile("^", re.MULTILINE)29self.rstescape = re.compile("([^a-zA-Z0-9\n ])")30self.emitted_sitl_heading = False31parameterlisttype = "Complete Parameter List"32parameterlisttype += "\n" + "=" * len(parameterlisttype)33self.preamble = """.. Dynamically generated list of documented parameters34.. This page was generated using {toolname}3536.. DO NOT EDIT373839.. _parameters:4041{parameterlisttype}4243{blurb}4445""".format(blurb=self.escape(self.blurb()),46parameterlisttype=parameterlisttype,47toolname=self.escape(self.toolname()))48self.t = ''4950def escape(self, s):51ret = re.sub(self.rstescape, r"\\\g<1>", s)52return ret5354def close(self):55self.f.write(self.preamble)56self.f.write(self.t)57self.f.close()5859def start_libraries(self):60pass6162def tablify_row(self, rowheading, row, widths, height):63joiner = "|"6465row_lines = [x.split("\n") for x in row]66for row_line in row_lines:67row_line.extend([""] * (height - len(row_line)))68if rowheading is not None:69rowheading_lines = rowheading.split("\n")70rowheading_lines.extend([""] * (height - len(rowheading_lines)))7172out_lines = []73for i in range(0, height):74out_line = ""75if rowheading is not None:76rowheading_line = rowheading_lines[i]77out_line += joiner + " " + rowheading_line + " " * (widths[0] - len(rowheading_line) - 1)78joiner = "#"79j = 080for item in row_lines:81widthnum = j82if rowheading is not None:83widthnum += 184line = item[i]85out_line += joiner + " " + line + " " * (widths[widthnum] - len(line) - 1)86joiner = "|"87j += 188out_line += "|"89out_lines.append(out_line)90return "\n".join(out_lines)9192def tablify_longest_row_length(self, rows, rowheadings, headings):93check_width_rows = rows[:]94if headings is not None:95check_width_rows.append(headings)96longest_row_length = 097for row in check_width_rows:98if len(row) > longest_row_length:99longest_row_length = len(row)100if rowheadings is not None:101longest_row_length += 1102return longest_row_length103104def longest_line_in_string(self, string):105longest = 0106for line in string.split("\n"):107if len(line) > longest:108longest = len(line)109return longest110111def tablify_calc_row_widths_heights(self, rows, rowheadings, headings):112rows_to_check = []113if headings is not None:114rows_to_check.append(headings)115rows_to_check.extend(rows[:])116117heights = [0] * len(rows_to_check)118119longest_row_length = self.tablify_longest_row_length(rows, rowheadings, headings)120widths = [0] * longest_row_length121122all_rowheadings = []123if rowheadings is not None:124if headings is not None:125all_rowheadings.append("")126all_rowheadings.extend(rowheadings)127128for rownum in range(0, len(rows_to_check)):129row = rows_to_check[rownum]130values_to_check = []131if rowheadings is not None:132values_to_check.append(all_rowheadings[rownum])133values_to_check.extend(row[:])134colnum = 0135for value in values_to_check:136height = len(value.split("\n"))137if height > heights[rownum]:138heights[rownum] = height139longest_line = self.longest_line_in_string(value)140width = longest_line + 2 # +2 for leading/trailing ws141if width > widths[colnum]:142widths[colnum] = width143colnum += 1144return (widths, heights)145146def tablify(self, rows, headings=None, rowheadings=None):147148(widths, heights) = self.tablify_calc_row_widths_heights(rows, rowheadings, headings)149150# create dividing lines151bar = ""152heading_bar = ""153for width in widths:154bar += "+"155heading_bar += "+"156bar += "-" * width157heading_bar += "=" * width158bar += "+"159heading_bar += "+"160161# create table162ret = bar + "\n"163if headings is not None:164rowheading = None165if rowheadings is not None:166rowheading = ""167ret += self.tablify_row(rowheading, headings, widths, heights[0]) + "\n"168ret += heading_bar + "\n"169for i in range(0, len(rows)):170rowheading = None171height = i172if rowheadings is not None:173rowheading = rowheadings[i]174if headings is not None:175height += 1176ret += self.tablify_row(rowheading, rows[i], widths, heights[height]) + "\n"177ret += bar + "\n"178179return ret180181def render_prog_values_field(self, render_info, param, field):182values = (param.__dict__[field]).split(',')183rows = []184for value in values:185v = [x.strip() for x in value.split(':')]186rows.append(v)187return self.tablify(rows, headings=render_info["headings"])188189def render_table_headings(self, ret, row, headings, field_table_info, field, param):190row.append(self.render_prog_values_field(field_table_info[field], param, field))191return ''192193def emit(self, g):194# make only a single group for SIM_ parameters195do_emit_heading = True196if g.reference.startswith("SIM_"):197if self.emitted_sitl_heading:198do_emit_heading = False199self.emitted_sitl_heading = True200tag = "Simulation Parameters"201reference = "parameters_sim"202else:203tag = '%s Parameters' % self.escape(g.reference)204reference = "parameters_" + g.reference205206field_table_info = {207"Values": {208"headings": ['Value', 'Meaning'],209},210"Bitmask": {211"headings": ['Bit', 'Meaning'],212},213}214215ret = ""216if do_emit_heading:217ret = """218219.. _{reference}:220221{tag}222{underline}223""".format(tag=tag, underline="-" * len(tag),224reference=reference)225226for param in g.params:227if getattr(param, "Legacy", False):228# do not emit legacy parameters to the Wiki229continue230if not hasattr(param, 'DisplayName') or not hasattr(param, 'Description'):231continue232d = param.__dict__233234# Get param path if defined (i.e. is duplicate parameter)235param_path = getattr(param, 'path', '')236237name = param.name.split(':')[-1]238239tag_param_path = ' (%s)' % param_path if param_path else ''240tag = '%s%s: %s' % (self.escape(name), self.escape(tag_param_path), self.escape(param.DisplayName),)241242tag = tag.strip()243reference = param.name244# remove e.g. "ArduPlane:" from start of parameter name:245reference = reference.split(":")[-1]246if param_path:247reference += '__' + param_path248249ret += """250251.. _{reference}:252253{tag}254{tag_underline}255""".format(tag=tag, tag_underline='~' * len(tag), reference=reference)256257if d.get('User', None) == 'Advanced':258ret += '\n| *Note: This parameter is for advanced users*'259if d.get('RebootRequired', None) == 'True':260ret += '\n| *Note: Reboot required after change*'261elif 'RebootRequired' in d and d.get('RebootRequired') != 'True':262raise Exception("Bad RebootRequired metadata tag value for {} in {}".format(d.get('name'),d.get('real_path')))263ret += "\n\n%s\n" % self.escape(param.Description)264265headings = []266row = []267for field in sorted(param.__dict__.keys()):268if not self.should_emit_field(param, field):269continue270if (field not in ['name', 'DisplayName', 'Description', 'User', 'SortValues', 'RebootRequired'] and271field in known_param_fields):272headings.append(field)273if field in field_table_info and Emit.prog_values_field.match(param.__dict__[field]):274ret += self.render_table_headings(ret, row, headings, field_table_info, field, param)275elif field == "Range":276(param_min, param_max) = (param.__dict__[field]).split(' ')277row.append("%s to %s" % (param_min, param_max,))278elif field == 'Units':279abbreviated_units = param.__dict__[field]280if abbreviated_units != '':281# use the known_units dictionary to282# convert the abbreviated unit into a full283# textual one:284units = known_units[abbreviated_units]285row.append(cescape(units))286else:287row.append(cescape(param.__dict__[field]))288if len(row):289ret += "\n\n" + self.tablify([row], headings=headings) + "\n\n"290self.t += ret + "\n"291292293def table_test():294e = RSTEmit()295print("Test 1")296print(e.tablify([["A", "B"], ["C", "D"]]))297298print("Test 2")299print(e.tablify([["A", "B"], ["CD\nE", "FG"]]))300301print("Test 3")302print(e.tablify([["A", "B"], ["CD\nEF", "GH"]], rowheadings=["r1", "row2"]))303304print("Test 4")305print(e.tablify([["A", "B"], ["CD\nEF", "GH"]], headings=["c1", "col2"]))306307print("Test 5")308print(e.tablify([["A", "B"], ["CD\nEF", "GH"]], headings=["c1", "col2"], rowheadings=["r1", "row2"]))309310311if __name__ == '__main__':312table_test()313314315