On 03/01/2012 11:01 PM, tom.zanu...@intel.com wrote: > From: Tom Zanussi <tom.zanu...@intel.com> > > The main implementation of the Yocto BSP templating engine, > essentially containing the internal implementation of the 'yocto-bsp > create' and yocto-bsp list' commands. > > Signed-off-by: Tom Zanussi <tom.zanu...@intel.com> > --- > scripts/lib/bsp/engine.py | 1336 > +++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 1336 insertions(+), 0 deletions(-) > create mode 100644 scripts/lib/bsp/engine.py > > diff --git a/scripts/lib/bsp/engine.py b/scripts/lib/bsp/engine.py > new file mode 100644 > index 0000000..7bf3e92 > --- /dev/null > +++ b/scripts/lib/bsp/engine.py > @@ -0,0 +1,1336 @@ > +# ex:ts=4:sw=4:sts=4:et > +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- > +# > +# Copyright 2012 Intel Corporation > +# Authored-by: Tom Zanussi <tom.zanu...@intel.com>
same comments here... > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License version 2 as > +# published by the Free Software Foundation. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License along > +# with this program; if not, write to the Free Software Foundation, Inc., > +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + > +import os > +import sys > +from abc import ABCMeta, abstractmethod > +from tags import * > +import shlex > +import json > + This looks like a healthy list of dependencies. Do we need to augment the required packages list? > +class Line(): > + """ > + Generic (abstract) container representing a line that will appear > + in the BSP-generating program. > + """ > + __metaclass__ = ABCMeta Oh, I didn't know about that. My ABCs have been rather amateur by comparison. Nice. > + > + def __init__(self, line): > + self.line = line > + self.generated_line = "" > + > + @abstractmethod > + def gen(self, context = None): > + """ > + Generate the final executable line that will appear in the > + BSP-generation program. > + """ > + pass > + > + def escape(self, line): > + """ > + Escape single and double quotes and backslashes until I find > + something better (re.escape() escapes way too much) > + """ > + return line.replace("\\", "\\\\").replace("\"", "\\\"").replace("'", > "\\'") > + > + def parse_error(self, msg, lineno, line): > + raise SyntaxError("%s: %s" % (msg, line)) > + Very nicely pythonic Tom. Classes, PyDoc, decorators, exceptions. Nice work! > + > +class NormalLine(Line): > + """ > + Container for normal (non-tag) lines. > + """ > + def __init__(self, line): > + Line.__init__(self, line) > + self.is_filename = False > + self.is_dirname = False > + self.out_filebase = None > + > + def gen(self, context = None): > + if self.is_filename: > + line = "of = open(\"" + os.path.join(self.out_filebase, > self.escape(self.line)) + "\", \"w\")" > + elif self.is_dirname: > + dirname = os.path.join(self.out_filebase, self.escape(self.line)) > + line = "if not os.path.exists(\"" + dirname + "\"): os.mkdir(\"" > + dirname + "\")" > + else: > + line = "of.write(\"" + self.escape(self.line) + "\\n\")" > + return line > + > + > +class CodeLine(Line): > + """ > + Container for Python code tag lines. > + """ > + def __init__(self, line): > + Line.__init__(self, line) > + > + def gen(self, context = None): > + return self.line > + > + > +class Assignment: > + """ > + Representation of everything we know about {{=name }} tags. > + Instances of these are used by Assignment lines. > + """ > + def __init__(self, start, end, name): > + self.start = start > + self.end = end > + self.name = name > + > + > +class AssignmentLine(NormalLine): > + """ > + Container for normal lines containing assignment tags. Assignment > + tags must be in ascending order of 'start' value. > + """ > + def __init__(self, line): > + NormalLine.__init__(self, line) > + self.assignments = [] > + > + def add_assignment(self, start, end, name): > + self.assignments.append(Assignment(start, end, name)) > + > + def gen(self, context = None): > + line = self.escape(self.line) > + > + for assignment in self.assignments: > + replacement = "\" + " + assignment.name + " + \"" > + idx = line.find(ASSIGN_TAG) > + line = line[:idx] + replacement + line[idx + assignment.end - > assignment.start:] > + if self.is_filename: > + return "of = open(\"" + os.path.join(self.out_filebase, line) + > "\", \"w\")" > + elif self.is_dirname: > + dirname = os.path.join(self.out_filebase, line) > + return "if not os.path.exists(\"" + dirname + "\"): os.mkdir(\"" > + dirname + "\")" > + else: > + return "of.write(\"" + line + "\\n\")" > + > + > +class InputLine(Line): > + """ > + Base class for Input lines. > + """ > + def __init__(self, props, tag, lineno): > + Line.__init__(self, tag) > + self.props = props > + self.lineno = lineno > + > + try: > + self.prio = int(props["prio"]) > + except KeyError: > + self.prio = sys.maxint > + > + def gen(self, context = None): > + try: > + depends_on = self.props["depends-on"] > + try: > + depends_on_val = self.props["depends-on-val"] > + except KeyError: > + self.parse_error("No 'depends-on-val' for 'depends-on' > property", > + self.lineno, self.line) > + except KeyError: > + pass > + > + > +class EditBoxInputLine(InputLine): > + """ > + Base class for 'editbox' Input lines. > + > + props: > + name: example - "Load address" > + msg: example - "Please enter the load address" > + result: > + Sets the value of the variable specified by 'name' to > + whatever the user typed. > + """ > + def __init__(self, props, tag, lineno): > + InputLine.__init__(self, props, tag, lineno) > + > + def query_user(self): > + msg = self.props["name"] > + if not msg: > + self.parse_error("No input 'msg' property found", > + self.lineno, self.line) > + > + return self.show_prompt(msg) > + > + def gen(self, context = None): > + InputLine.gen(self, context) > + name = self.props["name"] > + if not name: > + self.parse_error("No input 'name' property found", > + self.lineno, self.line) > + msg = self.props["msg"] > + if not msg: > + self.parse_error("No input 'msg' property found", > + self.lineno, self.line) > + > + line = name + " = default(raw_input(" + msg + " ), " + name + ")" > + > + return line > + > + > +class BooleanInputLine(InputLine): > + """ > + Base class for boolean Input lines. > + props: > + name: example - "keyboard" > + msg: example - "Got keyboard?" > + result: > + Sets the value of the variable specified by 'name' to "yes" or "no" > + example - keyboard = "yes" > + """ > + def __init__(self, props, tag, lineno): > + InputLine.__init__(self, props, tag, lineno) > + > + def query_user(self): > + msg = self.props["name"] > + if not msg: > + self.parse_error("No input 'msg' property found", > + self.lineno, self.line) > + > + return self.show_prompt(msg) > + > + def gen(self, context = None): > + InputLine.gen(self, context) > + name = self.props["name"] > + if not name: > + self.parse_error("No input 'name' property found", > + self.lineno, self.line) > + msg = self.props["msg"] > + if not msg: > + self.parse_error("No input 'msg' property found", > + self.lineno, self.line) > + > + line = name + " = boolean(raw_input(\"" + msg + " \"), " + name + ")" > + > + return line > + > + > +class ListInputLine(InputLine): > + """ > + Base class for List-based Input lines. e.g. Choicelist, Checklist > + """ > + __metaclass__ = ABCMeta > + > + def __init__(self, props, tag, lineno): > + InputLine.__init__(self, props, tag, lineno) > + self.choices = [] > + > + def gen_choicepair_list(self): > + """generate a list of 2-item val:desc lists from self.choices""" Nitpic, initial caps and period. > + if not self.choices: > + return None > + > + choicepair_list = list() > + > + for choice in self.choices: > + choicepair = [] > + choicepair.append(choice.val) > + choicepair.append(choice.desc) > + choicepair_list.append(choicepair) > + > + return choicepair_list > + > + def gen_degenerate_choicepair_list(self, choices): > + """generate a list of 2-item val:desc with val=desc from passed-in > choices""" Nitpic, initial caps and period. > + choicepair_list = list() > + > + for choice in choices: > + choicepair = [] > + choicepair.append(choice) > + choicepair.append(choice) > + choicepair_list.append(choicepair) > + > + return choicepair_list > + > + def exec_listgen_fn(self, context = None): > + """ > + execute the list-generating function contained as a string in > + the "gen" property. Nitpic, initial caps. And I'm stopping here. It looks really good, but it is a bit more than I can review very closely right now. So I'd only have superficial comments, which aren't so helpful right now. Nice work! -- Darren Hart Intel Open Source Technology Center Yocto Project - Linux Kernel _______________________________________________ yocto mailing list yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/yocto