[yocto] [PATCH 3/8] yocto-bsp: add templating engine

Darren Hart dvhart at linux.intel.com
Fri Mar 2 08:57:10 PST 2012



On 03/01/2012 11:01 PM, tom.zanussi at intel.com wrote:
> From: Tom Zanussi <tom.zanussi at 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.zanussi at 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.zanussi at 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



More information about the yocto mailing list