#!/usr/bin/env python3 import sys import os import errno import getopt import stat import re import operator from xml.etree import ElementTree, ElementInclude import xml.sax def info(message, level=1): """ @brief Print info to stdout @param message string to print """ if VERBOSE >= level: sys.stderr.write("*II* %s\n" % message) def warning(message): """ @brief Print warning to stdout @param message string to print """ if ERROR_ON_WARNING: error(message) if WARNING: sys.stderr.write("*WW* %s\n" % message) def error(message): """ @brief Print error to stdout @param message string to print """ print("*EE* %s " % message) sys.exit(1) def usage(myname): print("\nUsage: %s OPTIONS \n" % myname) print("Read configuration from an XML file and create config files.") print(""" %s reads a data base of configuration parameters from an XML file. Subsequently, a number of template files are processed in order to create configuration files (targets). See ec-conf User Guide for more information.""" % myname) print(""" Options: -h|--help Print this help screen. -p|--platform Set the active platform. -l|--list-platforms Lists all platforms, which are defined in the XML file, on stdout. -d|--prefix= Creates the directory PATH (if non-existing) and writes all target files within that directory. Also sets a configuration parameter named PLT:ACTIVE:PREFIXDIR for use in the template files. -o|--overwrite-parameter = Allows to set new values to configuration parameters from the command line, overwriting the values from the XML file. must be given in the form 'COMPONENT_TYPE:COMPONENT_NAME:PARAMETER_NAME' corresponding to the place-holder syntax of ec-conf. See ec-conf user guide for details. Multiple parameters can be overwritten by repeating this option. -x|--write-xml Writes the content of in XML format to stdout. This can be used to normalise the XML file and for test purposes. -g|--gui Starts the graphical user interface. Turns off -x and -l. -v|--verbose Produces verbose output (stderr). To increase verbosity, use more than once. -w|--no-warning Turns off warnings (however, errors are displayed). -e|--error-on-warning Turns warnings into errors (i.e. ec-conf will stop). """) sys.exit(2) class TextNode(object): """Represents an XML node that contains only text, i.e. is not named and has no child nodes""" def __init__(self): self.text = "" def add_text(self, content): self.text += content class NamedNode(object): """Represents an XML node with a certain type according to the document definition. Base class for Configuration, Translation, Platform, Model, and Parameter""" def __init__(self, attr=None): self.name = None self.description = None if attr: if 'name' in list(attr.keys()): self.name = attr['name'] info('Create named node: ' + self.name + ' (' + self.__class__.__name__ + ')', level=2) def set(self, key, value): self.__dict__.__setitem__(key, value) def xml(self, level=0): """Provides XML representation of the NamedNode as a string""" tabwidth = 4 xml_string = ' ' * level * tabwidth xml_string += '<' + self.__class__.__name__ if 'name' in self.__dict__ and self.name: xml_string += ' name="' + self.name + '"' xml_string += '>\n' for element in 'description', 'template', 'target', 'properties', 'type', 'value': if element in self.__dict__: xml_string += ' ' * (level + 1) * tabwidth xml_string += '<' + element.capitalize() + '>' if self.__dict__[element]: xml_string += self.__dict__[element] xml_string += '\n' if level <= 1: xml_string += '\n' for element in 'translation', 'platform', 'model', 'parameter': if element in self.__dict__: for child_element in self.__dict__[element]: xml_string += child_element.xml(level + 1) xml_string += ' ' * level * tabwidth xml_string += '\n' if level > 0 and level <= 2: xml_string += '\n' return xml_string def plt(self, name=None): """Provides short-hand access to the Platform member with name 'name'.""" if 'platform' in self.__dict__: if name: for plt in self.platform: if plt.name == name: return plt else: return self.platform return None def mod(self, name=None): """Provides short-hand access to the Model member with name 'name'.""" if 'model' in self.__dict__: if name: for mod in self.model: if mod.name == name: return mod else: return self.model return None def par(self, name=None): """Provides short-hand access to the Parameter member with name 'name'.""" if 'parameter' in self.__dict__: if name: for par in self.parameter: if par.name == name: return par else: return self.parameter return None class Translation(NamedNode): """Represents a Translation element of the XML document type""" def __init__(self, attr): super(Translation, self).__init__(attr) self.template = None self.target = None self.properties = '' self.is_active = 1 def set_target(self, target): self.target = target class Platform(NamedNode): """Represents a Platform element of the XML document type""" def __init__(self, attr): super(Platform, self).__init__(attr) self.parameter = [] self.translation = [] class Model(NamedNode): """Represents a Parameter element of the XML document type""" def __init__(self, attr): super(Model, self).__init__(attr) self.parameter = [] class Parameter(NamedNode): """Represents a Parameter element of the XML document type""" def __init__(self, attr): super(Parameter, self).__init__(attr) self.type = None self.value = None class Configuration(NamedNode, xml.sax.handler.ContentHandler): """Represents a Parameter element (which is the root element) of the XML document type""" def __init__(self): self.translation = [] self.platform = [] self.model = [] self.xml_file = None self.active_platform = None self.__stack = [] self.__types = {'Translation': Translation, 'Platform': Platform, 'Model': Model, 'Parameter': Parameter} def xml(self, level=0): return '\n\n' \ + super(Configuration, self).xml(level) def startElement(self, tag, attributes): info("Processing XML element '" + str(tag) + "'", level=3) if self.__stack: if tag in self.__types: info("Adding NamedNode for element '" + str(tag) + "'", level=3) self.__stack.append(self.__types[tag](attributes)) else: info("Adding TextNode for element '" + str(tag) + "'", level=3) self.__stack.append(TextNode()) else: self.__stack.append(self) def characters(self, content): if isinstance(self.__stack[-1], TextNode): self.__stack[-1].add_text(content) def endElement(self, tag): element = self.__stack.pop() if self.__stack: if isinstance(element, TextNode): self.__stack[-1].__dict__[tag.lower()] = element.text else: self.__stack[-1].__dict__[tag.lower()].append(element) def parse(self, file): info("Parsing XML file '%s'" % file) # A short helper function for xml.etree.ElementInclude.include # that parses include files and catches parse errors def include_loader(href, parse, encoding=None): if parse != "xml": error("Only XML includes allowed in xi:include! (see file '%s')" % href) try: with open(href) as file: data = ElementTree.parse(file).getroot() except IOError as e: error("Can't open include file '%s' for parsing: %s" % (href, e)) except ElementTree.ParseError as e: error("XML parse error in include file '%s': %s" % (href, e)) return data # First parsing stage with xml.etree for include processing try: tree = ElementTree.parse(file) except IOError: error("Can't open file '%s' for parsing" % file) except ElementTree.ParseError as e: error("XML parse error in file '%s': %s" % (file, e)) # Process XML include files tree_root = tree.getroot() ElementInclude.include(tree_root, loader=include_loader) # Second parsing stage with xml.sax to fill data structures # Since errors are catched in the first parsing stage, we assume # everything is fine here. xml.sax.parseString(ElementTree.tostring(tree_root, encoding="UTF-8"),self) info("Finished parsing '%s': Translation: %d Platform: %d Model: %d" % ( file, len(self.translation), len(self.platform), len(self.model))) self.xml_file = file def translate(self, translation): rpm_ops = { 'ADD': operator.add, 'SUB': operator.sub, 'MUL': operator.mul, 'DIV': operator.truediv, 'POW': operator.pow, 'MOD': operator.mod } subst_re = re.compile(r"\[\[\[(?P[a-zA-Z0-9_:,]+)\]\]\]") var_re = re.compile(r"^(\w{3}):([a-zA-Z0-9_]+):([a-zA-Z0-9_]+)$") def parse_var(string): # Shortcut for the 'prefixdir' parameter in template file if string.lower() == 'plt:active:prefixdir': return targetPrefixDir if targetPrefixDir else '[[[' + string + ']]]' while True: match = var_re.search(string) if not match: break (category, component, parameter) = match.groups() if category.lower() == 'plt' and component.lower() == 'active': component = self.active_platform try: string = getattr(self, category.lower())( component).par(parameter).value except BaseException: warning( "Unable to process '%s' (Line %d in '%s')" % (string, line_number, template)) return '[[[' + string + ']]]' return string def parse_rpn(string): stack = [] for token in string.split(','): token = parse_var(token) if not token: info( "Substitute expression with empty string (Line %d in '%s')" % (line_number, template)) try: result = int(token) except ValueError: try: result = float(token) except ValueError: if token in list(rpm_ops.keys()): try: result = rpm_ops[token]( stack.pop(-2), stack.pop()) except IndexError: warning( "Too few arguments to execute '%s' (Line %d in '%s')" % (token, line_number, template)) return "[[[" + string + "]]]" except BaseException: warning( "Unable to execute '%s' (Line %d in '%s')" % (token, line_number, template)) return "[[[" + string + "]]]" else: result = token stack.append(result) if len(stack) > 1: warning( "Too many operands in '%s' (Line %d in '%s')" % (string, line_number, template)) return "[[[" + string + "]]]" return result template = translation.template target = translation.target.strip() info("Translate: '%s' --> '%s'" % (template, target)) try: input = open(template, 'r') except IOError: error("Can't open template file '%s' for reading" % template) if target: if targetPrefixDir: target = os.path.join(targetPrefixDir, target) path = os.path.dirname(target) try: os.makedirs(path) info("Created target prefix directory '%s'" % path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(path): info( "Target prefix directory '%s' exists already" % (path)) else: error( "Could not create target prefix directory '%s'" % (path)) try: output = open(target, 'w') except IOError: error("Can't open target file '%s' for writing" % target) if 'executable' in translation.properties.split(','): os.chmod(target, stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR) else: output = sys.stdout line_number = 0 for line in input: line_number += 1 ptr = 0 buf = '' for match in subst_re.finditer(line): buf += line[ptr:match.start()] var = match.groupdict()['var'] try: buf += str(parse_rpn(var)) except UnicodeEncodeError as e: error('Invalid character in XML file!\n' '*EE* Look up the \\uXXXX character code from the following message:\n' '*EE* %s' % str(e)) ptr = match.end() buf += line[ptr:] output.write(buf) input.close() if target: output.close() def translate_all(self): for t in self.translation: self.translate(t) if self.active_platform: for t in self.plt(self.active_platform).translation: self.translate(t) def start_gui(cfg): import tkinter import tkinter.filedialog import tkinter.messagebox class VerticalScrolledFrame(tkinter.Frame): """A pure Tkinter scrollable frame that actually works! * Use the 'interior' attribute to place widgets inside the scrollable frame * Construct and pack/place/grid normally * This frame only allows vertical scrolling http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame """ def __init__(self, parent, *args, **kw): tkinter.Frame.__init__(self, parent, *args, **kw) # create a canvas object and a vertical scrollbar for scrolling it vscrollbar = tkinter.Scrollbar(self, orient=tkinter.VERTICAL) vscrollbar.pack( fill=tkinter.Y, side=tkinter.RIGHT, expand=tkinter.FALSE) canvas = tkinter.Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set) canvas.pack( side=tkinter.LEFT, fill=tkinter.BOTH, expand=tkinter.TRUE) vscrollbar.config(command=canvas.yview) # reset the view canvas.xview_moveto(0) canvas.yview_moveto(0) # create a frame inside the canvas which will be scrolled with it self.interior = interior = tkinter.Frame(canvas) interior_id = canvas.create_window(0, 0, window=interior, anchor=tkinter.NW) # track changes to the canvas and frame width and sync them, # also updating the scrollbar def _configure_interior(event): # update the scrollbars to match the size of the inner frame size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) if interior.winfo_reqwidth() != canvas.winfo_width(): # update the canvas's width to fit the inner frame canvas.config(width=interior.winfo_reqwidth()) interior.bind('', _configure_interior) def _configure_canvas(event): if interior.winfo_reqwidth() != canvas.winfo_width(): # update the inner frame's width to fill the canvas canvas.itemconfigure( interior_id, width=canvas.winfo_width()) canvas.bind('', _configure_canvas) return class GUI(tkinter.Tk): def __init__(self, cfg): tkinter.Tk.__init__(self) self.columnconfigure(1, weight=1) self.rowconfigure(0, pad=10) self.rowconfigure(2, weight=1) self.__cfg = cfg self.__var_list = [] self.__var_dict = {} for t in self.__cfg.translation + \ [t for p in self.__cfg.platform for t in p.translation]: v = tkinter.IntVar() v.set(1) v.trace( 'w', lambda n, i, m, t=t: t.set( 'is_active', int( self.globalgetvar(n)))) self.__add_var(v, t) self.__active_component = tkinter.StringVar() self.__status = tkinter.StringVar() self.__component_frame = None self.__parameter_frame = None self.__translation_frame = None self.__init_top_panel() self.__init_status_panel() self.__init_main_panel() self.grid_propagate(flag=0) self.__set_status( "Welcome to EC-CONF's graphical user interface!", time=3000) def __add_var(self, var, obj=None): self.__var_list.append(var) if obj: self.__var_dict[obj] = len(self.__var_list) - 1 def __set_status(self, message, time=8000): try: self.after_cancel(self.__status_after_id) except BaseException: pass self.__default_status_message = 'Basic usage: SELECT XML database' \ ' and template/target files, CONFIGURE parameters, and CREATE' \ ' the configuration files.' self.__status.set(message) self.__status_after_id = self.after( time, self.__status.set, self.__default_status_message) def __init_top_panel(self): w = tkinter.Label(text='The active platform is:') w.grid(row=0, column=0) if not self.__cfg.active_platform: self.__cfg.active_platform = self.__cfg.platform[0].name v = tkinter.StringVar() v.set(self.__cfg.active_platform) v.trace( 'w', lambda n, i, m: self.__set_status( "Active platform changed to '" + self.__cfg.active_platform + "'")) v.trace( 'w', lambda n, i, m: self.__fill_parameter_frame( self.__parameter_frame)) v.trace( 'w', lambda n, i, m: self.__fill_component_frame( self.__component_frame)) v.trace( 'w', lambda n, i, m: self.__fill_translation_frame( self.__translation_frame)) v.trace('w', lambda n, i, m: self.__cfg.set( 'active_platform', self.globalgetvar(n))) self.__add_var(v) w = tkinter.OptionMenu(None, v, * [p.name for p in self.__cfg.platform]) w.grid(row=0, column=1, sticky='W', padx=8) w = tkinter.Button(text='Select', width=10, height=2, bg='tan') w['command'] = self.__do_select w.grid(row=0, column=2, padx=8) w = tkinter.Button(text='Configure', width=10, height=2, bg='tan') w['command'] = self.__do_configure w.grid(row=0, column=3, padx=8) w = tkinter.Button( text='Create!', width=10, height=2, bg='darkgrey', fg='white') w['command'] = self.__do_create w.grid(row=0, column=4, padx=8) def __init_status_panel(self): w = tkinter.Label( textvariable=self.__status, height=2, bg='orange') w.grid(row=1, column=0, columnspan=5, sticky='EW', pady=5) def __init_main_panel(self): self.__init_select_panel() self.__init_configure_panel() self.__select_panel.grid_remove() self.__configure_panel.grid_remove() self.__active_main_panel = self.__select_panel self.__active_main_panel.grid() def __init_select_panel(self): self.__select_panel = tkinter.Frame() self.__select_panel.grid( row=2, column=0, columnspan=5, sticky='NEWS') self.__select_panel.columnconfigure(0, weight=1) self.__select_panel.rowconfigure(2, weight=1) f = tkinter.LabelFrame( self.__select_panel, text='XML database file') f.grid(sticky='NEWS') f.columnconfigure(1, weight=1) w = tkinter.Label(f, text='The current file is: ') w.grid(row=0, column=0, sticky='W') v = tkinter.StringVar() v.set(self.__cfg.xml_file) v.trace( 'w', lambda n, i, m: self.__cfg.set( 'xml_file', self.globalgetvar(n))) self.__add_var(v, 'xml_file') w = tkinter.Label(f, textvariable=v, bg='darkgrey', fg='white') w.grid(row=0, column=1, sticky='W') w = tkinter.Button(f, text='Save as', width=8) w['command'] = lambda: self.__save_as_xml_file() w.grid(row=0, column=2, sticky='E', padx=4, pady=5) w = tkinter.Button(f, text='Save', width=8) w['command'] = lambda: self.__save_xml_file() w.grid(row=0, column=3, sticky='E', padx=4, pady=5) tkinter.Frame(self.__select_panel).grid(pady=5) self.__translation_frame = tkinter.LabelFrame( self.__select_panel, text='Templates and Targets') self.__translation_frame.grid(sticky='NEWS') self.__translation_frame.columnconfigure(1, weight=1) self.__translation_frame.columnconfigure(3, weight=9) self.__fill_translation_frame(self.__translation_frame) def __init_configure_panel(self): self.__configure_panel = tkinter.Frame() self.__configure_panel.grid( row=2, column=0, columnspan=5, sticky='NEWS') self.__configure_panel.rowconfigure(0, weight=1) self.__configure_panel.columnconfigure(2, weight=1) # Component frame self.__component_frame = tkinter.LabelFrame( self.__configure_panel, text='Configurable components') self.__component_frame.grid(sticky='NEWS') self.__fill_component_frame(self.__component_frame) # Spacer frame f = tkinter.Frame(self.__configure_panel) f.grid(row=0, column=1, padx=2) # Parameter frame f = tkinter.LabelFrame( self.__configure_panel, text='Configuration parameters') f.grid(row=0, column=2, sticky='NEWS') f = VerticalScrolledFrame(f) f.pack(fill=tkinter.BOTH, expand=tkinter.TRUE) self.__parameter_frame = f.interior self.__parameter_frame.columnconfigure(2, weight=1) self.__fill_parameter_frame(self.__parameter_frame) def __fill_translation_frame(self, frame): for w in list(frame.children.values()): w.destroy() v = tkinter.IntVar() v.set(1) v.trace('w', lambda n, i, m: [self.__var_list[self.__var_dict[t]].set(self.globalgetvar(n)) for t in self.__cfg.translation + self.__cfg.plt(self.__cfg.active_platform).translation]) self.__add_var(v) w = tkinter.Checkbutton( frame, text='Activate/deactivate all', variable=v) w.grid(row=0, column=0, sticky='W', pady=5) r = 1 for t in self.__cfg.translation + \ self.__cfg.plt(self.__cfg.active_platform).translation: w = tkinter.Checkbutton( frame, text=t.description, variable=self.__var_list[self.__var_dict[t]]) w.grid(row=r, column=0, sticky='W', pady=5) w = tkinter.Label( frame, text=t.template, bg='darkgrey', fg='white') w.grid(row=r, column=1, sticky='E') w = tkinter.Label(frame, text=' --> ') w.grid(row=r, column=2) v = tkinter.StringVar() v.set(t.target) v.trace( 'w', lambda n, i, m, t=t: t.set_target( self.globalgetvar(n))) self.__add_var(v) w = tkinter.Entry(frame, textvariable=v) w.grid(row=r, column=3, sticky='EW') r += 1 def __fill_component_frame(self, frame): for w in list(frame.children.values()): w.destroy() if self.__cfg.active_platform: self.__active_component.set(self.__cfg.active_platform) w = tkinter.Label(frame, text='Active platform') w.pack(anchor='w') c = self.__cfg.plt(self.__cfg.active_platform) w = tkinter.Radiobutton( frame, text=c.name, variable=self.__active_component, value=c.name) w['command'] = lambda: self.__fill_parameter_frame( self.__parameter_frame) w.pack(anchor='w', pady=5) if self.__cfg.model: if not self.__active_component.get(): self.set(self.__cfg.model[0].name) w = tkinter.Label(frame, text='Configurable models') w.pack(anchor='w') for c in self.__cfg.model: w = tkinter.Radiobutton( frame, text=c.name, variable=self.__active_component, value=c.name) w['command'] = lambda: self.__fill_parameter_frame( self.__parameter_frame) w.pack(anchor='w', pady=5) def __fill_parameter_frame(self, frame): for w in list(frame.children.values()): w.destroy() for (name, component) in [(c.name, c) for c in self.__cfg.platform + self.__cfg.model]: if self.__active_component.get() == name: break r = 0 for p in component.par(): w = tkinter.Label( frame, text=p.description, anchor="w", width=35) w.grid(row=r, column=0, sticky='W') w = tkinter.Label(frame, text='[' + str(p.name) + ']') w.grid(row=r, column=1, sticky='W', padx=20) v = tkinter.StringVar() v.set(p.value) v.trace( 'w', lambda n, i, m, p=p: p.set( 'value', self.globalgetvar(n))) self.__add_var(v) w = tkinter.Entry(frame, textvariable=v) w.grid(row=r, column=2, sticky='EW') r += 1 self.__set_status( 'Configure parameters for component \'' + self.__active_component.get() + '\'') def __do_select(self): self.__active_main_panel.grid_remove() self.__active_main_panel = self.__select_panel self.__active_main_panel.grid() self.__set_status( 'Select the XML data base file and active translations in the panel below.') def __do_configure(self): self.__active_main_panel.grid_remove() self.__active_main_panel = self.__configure_panel self.__active_main_panel.grid() self.__set_status('Configure the configuration parameters for the' ' available components in the panel below.') def __do_create(self): fw = [] for t in self.__cfg.translation + \ self.__cfg.plt(self.__cfg.active_platform).translation: if t.is_active: self.__cfg.translate(t) fw.append(t.target) if fw: msg = 'Active target files written: ' + fw.pop() while fw: msg += ', ' + fw.pop() else: msg = 'No targets where written' self.__set_status(msg) def __save_as_xml_file(self): f = tkinter.filedialog.asksaveasfilename( title='Select a file name for saving:', filetypes=[ ('XML files', '*.xml'), ('All files', '*')]) if f: try: self.__var_list[self.__var_dict['xml_file']].set( os.path.relpath(f)) except AttributeError: self.__var_list[self.__var_dict['xml_file']].set( os.path.realpath(f)) self.__save_xml_file() else: self.__set_status("Current XML file NOT saved") def __save_xml_file(self): if os.path.isfile(self.__cfg.xml_file): msg = "The file '" + self.__cfg.xml_file + \ "' exists. Do you want to replace it?" if not tkinter.messagebox.askyesno('Save XML file', msg): return try: f = open(self.__cfg.xml_file, 'w') except IOError: msg = "The file '" + self.__cfg.xml_file + "' could not be opened for writing" tkinter.messagebox.showerror('Save XML file', msg) self.__set_status("XML database NOT saved") return f.write(self.__cfg.xml()) f.close() self.__set_status( "XML database saved to file '" + self.__cfg.xml_file + "'") root = GUI(cfg) root.title('ec-conf GUI') min_window_width = min(900, int(0.9 * root.winfo_screenwidth())) min_window_height = min(800, int(0.9 * root.winfo_screenheight())) root.minsize(min_window_width, min_window_height) root.resizable() root.mainloop() if __name__ == "__main__": # Try to get command line options and arguments try: opts, args = getopt.getopt(sys.argv[1:], "hp:gd:o:xlvwe", ["help", "platform=", "gui", "prefix=", "overwrite-parameter=", "write-xml", "list-platforms", "verbose", "no-warning", "error-on-warning"]) except getopt.GetoptError: usage(os.path.split(sys.argv[0])[-1]) # Default values, to be overwritten by command line options WARNING = True ERROR_ON_WARNING = False VERBOSE = 0 writeXML = False listPlatforms = False wantGUI = False platform = None targetPrefixDir = None overwriteParameters = [] # Parse command line options for opt, arg in opts: if opt in ('-h', '--help'): usage(os.path.split(sys.argv[0])[-1]) elif opt in ('-p', '--platform'): platform = arg elif opt in ('-g', '--gui'): wantGUI = True elif opt in ('-d', '--prefix'): targetPrefixDir = arg elif opt in ('-o', '--overwrite-parameter'): overwriteParameters.append(arg) elif opt in ('-x', '--write-xml'): writeXML = True elif opt in ('-l', '--list-platforms'): listPlatforms = True elif opt in ('-v', '--verbose'): VERBOSE += 1 elif opt in ('-w', '--no-warning'): WARNING = False elif opt in ('-e', '--error-on-warning'): ERROR_ON_WARNING = True # The XML file is all that should be left on the command line if len(args) != 1: usage(os.path.split(sys.argv[0])[-1]) # Create the Configuration object and fill the data structures by parsing # the XML file cfg = Configuration() cfg.parse(args[0]) info(args[0]) info(cfg.parse(args[0])) info(platform) # If a platform was given on the command line, try to set it if platform: info(cfg.plt(platform)) if cfg.plt(platform): cfg.active_platform = platform else: error( "Platform '%s' not defined in the configuration file '%s'" % (platform, args[0])) elif not (wantGUI or listPlatforms): warning("No active platform given") # Overwrite parameters given explicitely on the command line for arg in overwriteParameters: # split the name=value pair but make sure additional '=' are preserved name = arg.split('=')[0] value = '='.join(arg.split('=')[1:]) # Maybe we want to allow overwriting with empty values?! # if so, remove the following if block if not value: warning("Parameter '%s' in --overwrite-parameter has no value" % name) continue try: (category, component, parameter) = name.split(':') except ValueError: warning( "Malformed parameter name given to --overwrite-parameter: '%s'" % name) continue if category.lower() == 'plt' and component.lower() == 'active': component = cfg.active_platform try: getattr(cfg, category.lower())( component).par(parameter).value = value info("Overwriting parameter '%s' with value '%s'" % (name, value)) except AttributeError: warning( "Non-existing parameter name given to --overwrite-parameter: '%s'" % name) continue # Select activity to be done according to the command line options # Default is to translate all Translations in the Configuration if wantGUI: info("Starting GUI") start_gui(cfg) elif listPlatforms: if cfg.plt(): print('\n'.join([p.name for p in cfg.plt()])) else: warning("No platforms defined in XML file") elif writeXML: sys.stdout.write(cfg.xml()) else: cfg.translate_all()