Skip to content
Snippets Groups Projects
Commit e8aecd3f authored by Bryant Mairs's avatar Bryant Mairs
Browse files

Added generation option to disable XML validation.

Useful when generating a lot of code and the XML files are known to be good, but it's still left on by default.
Extended support for disabling validation to the mavgenerate GUI.
Removed some redundant code from mavgenerate and made more code from mavgen reusable.
parent a3d9e58d
No related branches found
No related tags found
No related merge requests found
...@@ -23,7 +23,7 @@ Released under GNU GPL version 3 or later ...@@ -23,7 +23,7 @@ Released under GNU GPL version 3 or later
import os import os
import re import re
# Python 2.x and 3.x compatability # Python 2.x and 3.x compatibility
try: try:
from tkinter import * from tkinter import *
import tkinter.filedialog import tkinter.filedialog
...@@ -40,7 +40,9 @@ except ImportError as ex: ...@@ -40,7 +40,9 @@ except ImportError as ex:
del tkMessageBox del tkMessageBox
sys.path.append(os.path.join('pymavlink','generator')) sys.path.append(os.path.join('pymavlink','generator'))
from mavgen import *
import mavgen
import mavparse
title = "MAVLink Generator" title = "MAVLink Generator"
error_limit = 5 error_limit = 5
...@@ -85,11 +87,11 @@ class Application(Frame): ...@@ -85,11 +87,11 @@ class Application(Frame):
# Create the Lang box # Create the Lang box
self.language_value = StringVar() self.language_value = StringVar()
self.language_choices = [ "C", "Python", "CS", "Javascript", "WLua" ] self.language_choices = mavgen.supportedLanguages
self.language_label = Label( self, text="Lang" ) self.language_label = Label( self, text="Language" )
self.language_label.grid(row=2, column=0) self.language_label.grid(row=2, column=0)
self.language_menu = OptionMenu(self,self.language_value,*self.language_choices) self.language_menu = OptionMenu(self,self.language_value,*self.language_choices)
self.language_value.set(self.language_choices[0]) self.language_value.set(mavgen.DEFAULT_LANGUAGE)
self.language_menu.config(width=10) self.language_menu.config(width=10)
self.language_menu.grid(row=2, column=1,sticky=W) self.language_menu.grid(row=2, column=1,sticky=W)
...@@ -97,19 +99,30 @@ class Application(Frame): ...@@ -97,19 +99,30 @@ class Application(Frame):
# Create the Protocol box # Create the Protocol box
self.protocol_value = StringVar() self.protocol_value = StringVar()
self.protocol_choices = [ "v0.9", "v1.0" ] self.protocol_choices = [mavparse.PROTOCOL_0_9, mavparse.PROTOCOL_1_0]
self.protocol_label = Label( self, text="Protocol") self.protocol_label = Label( self, text="Protocol")
self.protocol_label.grid(row=3, column=0) self.protocol_label.grid(row=3, column=0)
self.protocol_menu = OptionMenu(self,self.protocol_value,*self.protocol_choices) self.protocol_menu = OptionMenu(self,self.protocol_value,*self.protocol_choices)
self.protocol_value.set(self.protocol_choices[1]) self.protocol_value.set(mavgen.DEFAULT_WIRE_PROTOCOL)
self.protocol_menu.config(width=10) self.protocol_menu.config(width=10)
self.protocol_menu.grid(row=3, column=1,sticky=W) self.protocol_menu.grid(row=3, column=1,sticky=W)
#----------------------------------------
# Create the Validate box
self.validate_value = BooleanVar()
self.validate_label = Label( self, text="Validate")
self.validate_label.grid(row=4, column=0)
self.validate_button = Checkbutton(self, variable=self.validate_value, onvalue=True, offvalue=False)
self.validate_value.set(mavgen.DEFAULT_VALIDATE)
self.validate_button.config(width=10)
self.validate_button.grid(row=4, column=1,sticky=W)
#---------------------------------------- #----------------------------------------
# Create the generate button # Create the generate button
self.generate_button = Button ( self, text="Generate", command=self.generateHeaders) self.generate_button = Button ( self, text="Generate", command=self.generateHeaders)
self.generate_button.grid(row=4,column=1) self.generate_button.grid(row=5,column=1)
"""\ """\
Open a file selection window to choose the XML message definition. Open a file selection window to choose the XML message definition.
...@@ -137,7 +150,7 @@ class Application(Frame): ...@@ -137,7 +150,7 @@ class Application(Frame):
# Verify settings # Verify settings
rex = re.compile(".*\\.xml$", re.IGNORECASE) rex = re.compile(".*\\.xml$", re.IGNORECASE)
if not self.xml_value.get(): if not self.xml_value.get():
tkinter.messagebox.showerror('Error Generating Headers','An XML message defintion file must be specified.') tkinter.messagebox.showerror('Error Generating Headers','An XML message definition file must be specified.')
return return
if not self.out_value.get(): if not self.out_value.get():
...@@ -149,15 +162,12 @@ class Application(Frame): ...@@ -149,15 +162,12 @@ class Application(Frame):
if not tkinter.messagebox.askokcancel('Overwrite Headers?','The output directory \'{0}\' already exists. Headers may be overwritten if they already exist.'.format(self.out_value.get())): if not tkinter.messagebox.askokcancel('Overwrite Headers?','The output directory \'{0}\' already exists. Headers may be overwritten if they already exist.'.format(self.out_value.get())):
return return
# Verify XML file with schema (or do this in mavgen)
# TODO write XML schema (XDS)
# Generate headers # Generate headers
opts = MavgenOptions(self.language_value.get(), self.protocol_value.get()[1:], self.out_value.get(), error_limit); opts = mavgen.Opts(self.out_value.get(), wire_protocol=self.protocol_value.get(), language=self.language_value.get(), validate=self.validate_value.get(), error_limit=error_limit);
args = [self.xml_value.get()] args = [self.xml_value.get()]
try: try:
mavgen(opts,args) mavgen.mavgen(opts,args)
tkinter.messagebox.showinfo('Successfully Generated Headers', 'Headers generated succesfully.') tkinter.messagebox.showinfo('Successfully Generated Headers', 'Headers generated successfully.')
except Exception as ex: except Exception as ex:
exStr = formatErrorMessage(str(ex)); exStr = formatErrorMessage(str(ex));
...@@ -170,7 +180,7 @@ Format the mavgen exceptions by removing 'ERROR: '. ...@@ -170,7 +180,7 @@ Format the mavgen exceptions by removing 'ERROR: '.
def formatErrorMessage(message): def formatErrorMessage(message):
reObj = re.compile(r'^(ERROR):\s+',re.M); reObj = re.compile(r'^(ERROR):\s+',re.M);
matches = re.findall(reObj, message); matches = re.findall(reObj, message);
prefix = ("An error occurred in mavgen:" if len(matches) == 1 else "Errors occured in mavgen:\n") prefix = ("An error occurred in mavgen:" if len(matches) == 1 else "Errors occurred in mavgen:\n")
message = re.sub(reObj, '\n', message); message = re.sub(reObj, '\n', message);
return prefix + message return prefix + message
...@@ -179,20 +189,6 @@ def formatErrorMessage(message): ...@@ -179,20 +189,6 @@ def formatErrorMessage(message):
# End of Application class # End of Application class
# --------------------------------- # ---------------------------------
"""\
This class mimicks an ArgumentParser Namespace since mavgen only
accepts an object for its opts argument.
"""
class MavgenOptions:
def __init__(self,language,protocol,output,error_limit):
self.language = language
self.wire_protocol = protocol
self.output = output
self.error_limit = error_limit;
# End of MavgenOptions class
# ---------------------------------
# --------------------------------- # ---------------------------------
# Start # Start
......
...@@ -13,17 +13,17 @@ try: ...@@ -13,17 +13,17 @@ try:
except Exception: except Exception:
from pymavlink.generator import mavparse from pymavlink.generator import mavparse
try:
from lib.genxmlif import GenXmlIfError
from lib.minixsv import pyxsval
performValidation = True
except Exception:
print("Unable to load XML validator libraries. XML validation will not be performed")
performValidation = False
# XSD schema file # XSD schema file
schemaFile = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mavschema.xsd") schemaFile = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mavschema.xsd")
# Set defaults for generating MAVLink code
DEFAULT_WIRE_PROTOCOL = mavparse.PROTOCOL_1_0
DEFAULT_LANGUAGE = 'Python'
DEFAULT_ERROR_LIMIT = 200
DEFAULT_VALIDATE = True
# List the supported languages. This is done globally because it's used by the GUI wrapper too
supportedLanguages = ["C", "CS", "JavaScript", "Python", "WLua"]
def mavgen(opts, args) : def mavgen(opts, args) :
"""Generate mavlink message formatters and parsers (C and Python ) using options """Generate mavlink message formatters and parsers (C and Python ) using options
...@@ -33,8 +33,24 @@ def mavgen(opts, args) : ...@@ -33,8 +33,24 @@ def mavgen(opts, args) :
xml = [] xml = []
# Enable validation by default, disabling it if explicitly requested
if opts.validate:
try:
from lib.genxmlif import GenXmlIfError
from lib.minixsv import pyxsval
except Exception:
print("WARNING: Unable to load XML validator libraries. XML validation will not be performed")
opts.validate = False
def mavgen_validate(fname, schema, errorLimitNumber) :
"""Uses minixsv to validate an XML file with a given XSD schema file. We define mavgen_validate
here because it relies on the XML libs that were loaded in mavgen(), so it can't be called standalone"""
# use default values of minixsv, location of the schema file must be specified in the XML file
domTreeWrapper = pyxsval.parseAndValidate(fname, xsdFile=schema, errorLimit=errorLimitNumber)
# Process all XML files, validating them as necessary.
for fname in args: for fname in args:
if performValidation: if opts.validate:
print("Validating %s" % fname) print("Validating %s" % fname)
mavgen_validate(fname, schemaFile, opts.error_limit); mavgen_validate(fname, schemaFile, opts.error_limit);
else: else:
...@@ -49,7 +65,7 @@ def mavgen(opts, args) : ...@@ -49,7 +65,7 @@ def mavgen(opts, args) :
fname = os.path.join(os.path.dirname(x.filename), i) fname = os.path.join(os.path.dirname(x.filename), i)
## Validate XML file with XSD file if possible. ## Validate XML file with XSD file if possible.
if performValidation: if opts.validate:
print("Validating %s" % fname) print("Validating %s" % fname)
mavgen_validate(fname, schemaFile, opts.error_limit); mavgen_validate(fname, schemaFile, opts.error_limit);
else: else:
...@@ -106,11 +122,12 @@ def mavgen(opts, args) : ...@@ -106,11 +122,12 @@ def mavgen(opts, args) :
# build all the dialects in the dialects subpackage # build all the dialects in the dialects subpackage
class Opts: class Opts:
def __init__(self, wire_protocol, output): def __init__(self, output, wire_protocol=DEFAULT_WIRE_PROTOCOL, language=DEFAULT_LANGUAGE, validate=DEFAULT_VALIDATE, error_limit=DEFAULT_ERROR_LIMIT):
self.wire_protocol = wire_protocol self.wire_protocol = wire_protocol
self.error_limit = 200 self.error_limit = error_limit
self.language = 'Python' self.language = language
self.output = output self.output = output
self.validate = validate
def mavgen_python_dialect(dialect, wire_protocol): def mavgen_python_dialect(dialect, wire_protocol):
'''generate the python code on the fly for a MAVLink dialect''' '''generate the python code on the fly for a MAVLink dialect'''
...@@ -126,7 +143,7 @@ def mavgen_python_dialect(dialect, wire_protocol): ...@@ -126,7 +143,7 @@ def mavgen_python_dialect(dialect, wire_protocol):
xml = os.path.join(dialects, 'v10', dialect + '.xml') xml = os.path.join(dialects, 'v10', dialect + '.xml')
if not os.path.exists(xml): if not os.path.exists(xml):
xml = os.path.join(mdef, 'v1.0', dialect + '.xml') xml = os.path.join(mdef, 'v1.0', dialect + '.xml')
opts = Opts(wire_protocol, py) opts = Opts(py, wire_protocol)
import StringIO import StringIO
# throw away stdout while generating # throw away stdout while generating
...@@ -139,26 +156,17 @@ def mavgen_python_dialect(dialect, wire_protocol): ...@@ -139,26 +156,17 @@ def mavgen_python_dialect(dialect, wire_protocol):
sys.stdout = stdout_saved sys.stdout = stdout_saved
raise raise
sys.stdout = stdout_saved sys.stdout = stdout_saved
def mavgen_validate(fname, schema, errorLimitNumber) :
"""Uses minixsv to validate an XML file with a given XSD schema file."""
# use default values of minixsv, location of the schema file must be specified in the XML file
domTreeWrapper = pyxsval.parseAndValidate(fname, xsdFile=schema, errorLimit=errorLimitNumber)
# domTree is a minidom document object
domTree = domTreeWrapper.getTree()
if __name__ == "__main__": if __name__ == "__main__":
from optparse import OptionParser from optparse import OptionParser
supportedLanguages = ["C", "CS", "JavaScript", "Python", "WLua"]
parser = OptionParser("%prog [options] <XML files>") parser = OptionParser("%prog [options] <XML files>")
parser.add_option("-o", "--output", dest="output", default="mavlink", help="output directory.") parser.add_option("-o", "--output", dest="output", default="mavlink", help="output directory.")
parser.add_option("--lang", dest="language", choices=supportedLanguages, default="Python", help="language of generated code, one of: {0} [default: %default]".format(supportedLanguages)) parser.add_option("--lang", dest="language", choices=supportedLanguages, default=DEFAULT_LANGUAGE, help="language of generated code, one of: {0} [default: %default]".format(supportedLanguages))
parser.add_option("--wire-protocol", dest="wire_protocol", choices=[mavparse.PROTOCOL_0_9, mavparse.PROTOCOL_1_0], default=mavparse.PROTOCOL_1_0, help="MAVLink protocol version: '0.9' or '1.0'. [default: %default]") parser.add_option("--wire-protocol", dest="wire_protocol", choices=[mavparse.PROTOCOL_0_9, mavparse.PROTOCOL_1_0], default=DEFAULT_WIRE_PROTOCOL, help="MAVLink protocol version: '0.9' or '1.0'. [default: %default]")
parser.add_option("--error-limit", dest="error_limit", default=200, help="maximum number of validation errors.") parser.add_option("--no-validate", action="store_false", dest="validate", default=DEFAULT_VALIDATE, help="Do not perform XML validation. Can speed up code generation if XML files are known to be correct.")
parser.add_option("--error-limit", dest="error_limit", default=DEFAULT_ERROR_LIMIT, help="maximum number of validation errors to display")
(opts, args) = parser.parse_args() (opts, args) = parser.parse_args()
if len(args) < 1: if len(args) < 1:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment