Esempio n. 1
0
class Context(object):
    """
        Base class for parsing contexts
    """

    CTYPE = Util.create_enum("CONDITION", "CONFIG")

    def __init__(self, manifest_parser, prev_context, line_info, ctype):
        """Initializes shared context info"""

        self.manifest_parser = manifest_parser
        self.ctype = ctype

        if prev_context is None:
            self.level = 0
            self.line_info = "<invalid>"
        else:
            # Derive context from previous
            self.level = prev_context.level + 1
            self.line_info = line_info

        # Link to the previous context
        self.prev_context = prev_context

    def get_ctype(self):
        """Returns the context type"""
        return self.ctype

    def has_parameters(self):
        """Returns whether this type of context has parameters"""
        if self.ctype == Context.CTYPE.CONDITION:
            return False

        return True
Esempio n. 2
0
 def test_create_enum(self):
     testEnum = Util.create_enum("a", "b", "c", "d")
     self.assertEqual(testEnum.a, 0)
     self.assertEqual(testEnum.b, 1)
     self.assertEqual(testEnum.c, 2)
     self.assertEqual(testEnum.d, 3)
     self.assertEqual(testEnum.COUNT, 4)
     self.assertEqual(testEnum.enum_id, ("a", "b", "c", "d"))
Esempio n. 3
0
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

from GlobifestLib import Log, Util

ROOT = Util.create_enum("DEPENDENCY", "SOURCE")


class Project(object):
    """
        Encapsulates information necessary to build with various configurations.

        The project has one or more layers, and each layer has one or more variants.  Layers are
        configs structured in priority order, with higher priority layers overriding settings
        defined in lower layers.

        Variants are individual options chosen within each layer, so that only one is active at
        any time.

        See project-format.md for further details.
    """
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

from GlobifestLib import StatefulParser, Util

BOUNDED_STATE = Util.create_enum("LBOUND", "RBOUND", "DONE")


class BoundedStatefulParser(StatefulParser.Base):
    """
        Parser which extracts text between two boundary characters

        @note This parser also tracks strings, which override boundary detection
    """
    def __init__(self,
                 text,
                 lbound,
                 rbound=None,
                 flags=0,
                 string_delims="\"'",
                 string_escape="\\"):
Esempio n. 5
0
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

import os
import tkinter
import tkinter.filedialog
import tkinter.messagebox
import tkinter.ttk

from Globiconfig import CheckBoxCombo, CheckBoxText, FilterText
from GlobifestLib import Builder, DefTree, Log, ManifestParser, Util

ACCEL = Util.create_enum("CONTROL")

ACCELERATOR = [Util.Container(text="Ctrl", bind="Control")]

G_ID = Util.create_enum("FRM_MAIN")

PADDING = 5
STICKY_FILL = tkinter.N + tkinter.W + tkinter.E + tkinter.S
PANE_0_MINWIDTH = 100
PANE_1_MINWIDTH = 100
WINDOW_MINWIDTH = 300
WINDOW_MINHEIGHT = 200
DIVIDER_WIDTH = 4

assert (PANE_0_MINWIDTH + PANE_1_MINWIDTH) <= WINDOW_MINWIDTH
Esempio n. 6
0
class Context(object):
    """
        Encapsulates contextual information for a nesting level
    """

    CTYPE = Util.create_enum("DEPENDENCY", "LAYER", "PROJECT")

    def __init__(self,
                 project_parser,
                 prev_context=None,
                 line_info=None,
                 ctx=None):
        """Initialize the top (file-scope) nesting level"""

        self.project_parser = project_parser

        if prev_context is None:
            self.level = 0
            self.line_info = "<invalid>"
        else:
            # Derive context from previous
            self.level = prev_context.level + 1
            self.line_info = line_info

        # Link to the previous context
        self.prev_context = prev_context

        # Set up context-specific values
        self.ctx = ctx or Util.Container(ctype=None)
        assert hasattr(self.ctx, "ctype")

    def get_ctype(self):
        """Return the context type"""
        return self.ctx.ctype

    def is_complete(self):
        """Return whether context has all required information"""
        if self.ctx.ctype == Context.CTYPE.PROJECT:
            self.validate_project()
        elif self.ctx.ctype == Context.CTYPE.LAYER:
            self.validate_layer()
        elif self.ctx.ctype == Context.CTYPE.DEPENDENCY:
            self.validate_dependency()
        else:
            assert self.ctx.ctype is not None
            return False
        return True

    def is_unique_element(self, elements, name):
        """Return whether name is in elements, and is not already stored in ctx"""

        if name not in elements.keys():
            self.project_parser.log_error("Invalid parameter: {}".format(name))

        if self.ctx[elements[name]] is not None:
            self.project_parser.log_error("Redefinition of {}".format(name))

        return True

    def process_param(self, name, value):
        """Process a parameter in context"""
        if self.ctx.ctype == Context.CTYPE.PROJECT:
            self.project_parser.log_error("Projects have no parameters")
        elif self.ctx.ctype == Context.CTYPE.DEPENDENCY:
            self.process_param_dependency(name, value)
        elif self.ctx.ctype == Context.CTYPE.LAYER:
            self.process_param_layer(name, value)

    def process_param_dependency(self, name, value):
        """Process a dependency parameter (action)"""
        if not value:
            self.project_parser.log_error("Bad parameter: {}".format(value))

        action = Importer.create_action(name, value)
        if action is not None:
            self.ctx.actions.append(action)
        else:
            self.project_parser.debug("not found: {}".format(name))

    def process_param_layer(self, name, value):
        """Process a layer parameter"""
        if not value:
            self.project_parser.log_error("Bad parameter: {}".format(value))

        if name == "variant":
            if re.fullmatch(IDENTIFIER_NAME, value):
                self.ctx.variants.append(value)
            else:
                self.project_parser.log_error(
                    "Invalid identifier: {}".format(value))
        elif self.is_unique_element(LAYER_ELEMENTS, name):
            # No additional validation required for these elements
            self.ctx[LAYER_ELEMENTS[name]] = value
        else:
            self.project_parser.debug("not found: {}".format(name))

    def validate_dependency(self):
        """Validate the final state of a dependency context"""
        # Validate required fields
        if not self.ctx.actions:
            self.project_parser.log_error(
                "Dependency {} has no actions".format(
                    self.ctx.dependency_name))

    def validate_layer(self):
        """Validate the final state of a layer context"""
        # Set defaults
        if not self.ctx.prefix:
            self.ctx.prefix = self.ctx.layer_name + "_"
        if not self.ctx.suffix:
            self.ctx.suffix = ".cfg"

        # Validate required fields
        if not self.ctx.variants:
            self.project_parser.log_error("Layer {} has no variants".format(
                self.ctx.layer_name))

    def validate_project(self):
        """Validate the final state of a project context"""
        # Validate required fields
        if not self.ctx.prj_name:
            self.project_parser.log_error("Missing project name")
Esempio n. 7
0
    Settings, \
    StatefulParser, \
    StateMachine, \
    Util

from GlobifestLib.StatefulParser import FLAGS as PARSERFLAGS

FILE_LABELS = ["aux_files", "sources"]

PATH_LABELS = ["prv_includes", "pub_includes"]

RAW_LABELS = ["prv_defines", "pub_defines"]

PUBLIC_LABELS = ["pub_includes", "pub_defines"]

COND_STATE = Util.create_enum("NOT_MET", "MET", "SATISFIED")

PROHIBITED_GENERATORS = [Generators.CustomGenerator.FORMAT_TYPE]


class ConfigsOnly(Settings.Settings):
    """
        Class to use when only reading configs
    """
    def get_value(self, name):
        """Stub; should never be called"""
        Log.E("Internal error: cannot return value",
              err_type=Log.ERROR.RUNTIME)

    def has_value(self, name):
        """Stub; returns True"""
Esempio n. 8
0
    """

    OP_TEXT = "&&"
    LOGICAL_OP = "and"


class OpLogicalOr(OpLogicalBase):
    """
        Base class for OR operation
    """

    OP_TEXT = "||"
    LOGICAL_OP = "or"


RESERVED_IDENT = Util.create_enum("VALUE", "CLASS", "COUNT")

RESERVED_IDENT_MAP = Util.Container(TRUE=(True, BoolToken),
                                    FALSE=(False, BoolToken))

assert RESERVED_IDENT.COUNT == len(RESERVED_IDENT_MAP)


class Settings(Log.Debuggable):
    """
        Encapsulates a set of configuration values
    """
    def __init__(self, configs=Util.Container(), debug_mode=False):
        Log.Debuggable.__init__(self, debug_mode)

        # Add the configs through extend() for validation
Esempio n. 9
0
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

import re

from GlobifestLib import Log, Util

PARAM_TYPE = Util.create_enum("BOOL", "STRING", "INT", "FLOAT", "ENUM")

SCOPE_TRIM_RE = re.compile("^/|/$")


def no_sort(items):
    """Stub for Scope.walk() method without any sorting"""
    return items


def validate_type(ptype):
    """Returns the ptype validated as a PARAM_TYPE value, or None if invalid"""
    if not isinstance(ptype, str):
        return None

    ucase = ptype.upper()
Esempio n. 10
0
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

from GlobifestLib import Log, StateMachine, Util

PARSE_STATUS = Util.create_enum("INCOMPLETE", "FINISHED", "ERROR")

FLAGS = Util.create_flag_enum("MULTI_LEVEL", "DEBUG")


class StatefulParser(StateMachine.Base):
    """
        Helper class for parsing text using a state machine
    """
    def __init__(self, text="", flags=0):
        """
            Initialize the class

            @param text Initial text to add to the parser
            @type text str
        """
Esempio n. 11
0
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

import inspect
import io
import os
import sys

from GlobifestLib import Util

# Level constants
LEVEL = Util.create_enum("NONE", "INFO", "DEBUG", "EXTREME", "COUNT")

# Error types
ERROR = Util.create_enum("BUILD", "INPUT", "RUNTIME", "COUNT")


class GlobifestException(Exception):
    """Exception class used for all exceptions generated by Globifest"""
    def __init__(self, err_type, msg):
        Exception.__init__(self)
        self.err_type = err_type
        self.msg = msg

    def __str__(self):
        return self.msg