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
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"))
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="\\"):
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
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")
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"""
""" 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
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()
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 """
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