123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056 |
- #!/usr/bin/env python
- 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 <XML_FILE>\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=<PATH> 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 <NAME>=<VALUE>
- Allows to set new values to configuration parameters from the
- command line, overwriting the values from the XML file.
- <NAME> 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 <XML_FILE> 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 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 += '</' + element.capitalize() + '>\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 += '</' + self.__class__.__name__ + '>\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 '<?xml version="1.0"?>\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<var>[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 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, 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 tkFileDialog
- import tkMessageBox
- 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>', _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>', _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 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 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 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 = tkFileDialog.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 tkMessageBox.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"
- tkMessageBox.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])
- # If a platform was given on the command line, try to set it
- if 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()
|