Ejemplo n.º 1
0
    def clear(self):
        """Sets a boolean option to false"""
        if self.type in ["config", "menuconfig"]:
            config = data.get_config(self.value)
            if len(config['selected_by']) > 0:
                # menuconfig shouldn't mark set by user if option can't be changed
                return

            if config['datatype'] == 'bool':
                set_config(self.value, False)
Ejemplo n.º 2
0
def set_config_selectifs(key):
    c = data.get_config(key)
    value = c['value']
    if "select_if" in c:
        for k in c["select_if"]:
            if expr.condexpr_value(k[1]):
                force_config(k[0], value, key)
            else:
                # No longer forced, so turn off if previously forced
                force_config(k[0], False, key)
Ejemplo n.º 3
0
def enforce_dependent_values(stage,
                             fix_bools=False,
                             error_level=logging.WARNING):
    """
    Check that values are consistently set, specifically with respect
    to whether the dependencies are correct.

    This function is called when we expect the values to be
    consistent. i.e. after reading in a new config, or prior to
    writing it out. It is called prior to plugin execution, to try and
    ensure the plugins see consistent state.

    For non-boolean configs (string, int), set their value to default
    ("", 0) if the config's dependencies are not met. This can happen
    where a user sets the value of the config, and then changes
    another config resulting in the dependency being disabled.

    Boolean values are treated specially. Normally they will be kept
    in a consistent state (wrt dependencies) by set_config(). However
    they can be forced by a 'select' statement even when the
    dependencies are not met. This indicates there is a problem with
    the Mconfig that needs to be fixed. This function will only reset
    Boolean values to n if specifically requested by fix_bools=True.
    This is only expected to be used after reading in a config file.
    That file may have been written with a different Mconfig that
    allowed the selection.

    The error_level determines the log level at which bool
    inconsistencies are reported. When set to logging.ERROR this forces
    the user to fix the Mconfig.
    """
    for i in data.get_config_list():
        c = data.get_config(i)
        if can_enable(c):
            continue
        if c['datatype'] == 'bool' and c['value'] is True:
            if len(c['selected_by']) > 0:
                msg = "{0}unmet direct dependencies: {1} depends on {2}, " \
                      "but is selected by [{3}].".format(stage, i,
                                                         c['depends'][1],
                                                         ",".join(c['selected_by']))
                if error_level is logging.ERROR:
                    msg += " Update the Mconfig so that this can't happen"
                logger.log(error_level, msg)
            else:
                raise Exception("Unmet direct dependencies without select")

            if fix_bools:
                set_config_internal(i, False)

        elif c['datatype'] == 'string':
            set_config_internal(i, '')
        elif c['datatype'] == 'int':
            set_config_internal(i, 0)
Ejemplo n.º 4
0
def validate_configs():
    """
    Ensure that the types in 'default' statements are correct,
    and that the configs referred to in 'select' statements are boolean.
    """
    config_list = data.get_config_list()
    for k in config_list:
        c = data.get_config(k)
        if "default_cond" in c:
            for i in c['default_cond']:
                check_type(k, c, i['expr'])
        if "default" in c:
            check_type(k, c, c["default"])
        if "select_if" in c:
            for k in c["select_if"]:
                try:
                    c1 = data.get_config(k[0])
                except KeyError:
                    logger.warning("Ignoring unknown configuration option %s" %
                                   k[0])
                    continue
                if c1['datatype'] != "bool":
                    logger.error(
                        'Select option must have type bool but got type %s instead'
                        % c1['datatype'])
        if "select" in c:
            for k in c["select"]:
                try:
                    c1 = data.get_config(k)
                except KeyError:
                    logger.warning("Ignoring unknown configuration option %s" %
                                   k)
                    continue
                if c1['datatype'] != "bool":
                    logger.error(
                        'Select option must have type bool but got type %s instead'
                        % c1['datatype'])
Ejemplo n.º 5
0
def get_user_set_options():
    """
    Return all the options which have been set by the user
    """
    user_set_options = []
    for (i_type, i_symbol) in data.iter_symbols_menuorder():
        if i_type in ["config", "menuconfig"]:
            c = data.get_config(i_symbol)
            if c['is_user_set']:
                value = c['value']
                if c['datatype'] == "bool":
                    value = "y" if c['value'] else "n"
                source = c['source'] if "source" in c else ""
                user_set_options.append((i_symbol, value, source))
    return user_set_options
Ejemplo n.º 6
0
def test_condexpr_evaluation(caplog, tmpdir, inputdata, result, error):
    mconfig_file = tmpdir.join("Mconfig")

    mconfig = template_condexpr_mconfig.format(**inputdata)
    mconfig_file.write(mconfig, "wt")

    data.init(str(mconfig_file), False)
    c = data.get_config("OPTION")
    general.set_initial_values()

    val = expr.condexpr_value(c['default_cond'][0]['cond'])

    if error is not None:
        assert error in caplog.text
    else:
        assert val == result
        assert caplog.text == ""
Ejemplo n.º 7
0
def config_to_json():
    properties = dict()

    for key in data.get_config_list():
        c = data.get_config(key)
        key = key.lower()
        datatype = c["datatype"]
        value = c["value"]

        if datatype not in ["bool", "int", "string"]:
            logger.error("Invalid config type: %s (with value '%s')\n" %
                         (datatype, str(value)))

        if datatype == "int":
            value = int(value)

        properties[key] = {"ignore": c["bob_ignore"] == 'y', "value": value}

    return properties
Ejemplo n.º 8
0
def check_value_as_requested(key, requested_value, later_keys, later_values):
    try:
        opt = get_config(key)
    except KeyError:
        logger.error("unknown configuration option \"%s\"" % key)
        return

    final_value = opt['value']

    if opt['datatype'] == 'int':
        final_value = str(final_value)
    elif opt['datatype'] == 'bool':
        final_value = 'y' if final_value else 'n'

    if final_value == requested_value:
        return

    # See if the argument was overridden by a later argument
    last_idx = rindex(later_keys, key)
    if last_idx != -1 and later_values[last_idx] != requested_value:
        logger.error("%s=%s was overridden by later argument %s=%s", key,
                     requested_value, key, later_values[last_idx])
        return

    if not can_enable(opt):
        depends = opt['depends']
        logger.error("%s=%s was ignored; its dependencies were not met: %s",
                     key, requested_value,
                     format_dependency_list(depends, skip_parens=True))
        return

    # Check this *after* dependencies. This allows users to investigate why an
    # option with unmet dependencies wasn't enabled, even if it isn't user-settable.
    if not opt.get("title"):
        logger.error(
            "%s=%s was ignored; it has no title, so is not user-settable "
            "(%s has no unmet dependencies)", key, requested_value, key)
        return

    logger.error("%s=%s was ignored or overriden. Value is '%s' %s %s", key,
                 requested_value, final_value, type(requested_value),
                 type(final_value))
Ejemplo n.º 9
0
def set_config_if_prompt(key, value, is_user_set=True):
    """
    Used to set the option value from the command line, and through
    profile files. Only options that have prompts (indicating they are
    user-settable) can be set.
    """

    logger.debug("Trying to set %s %s" % (key, value))
    try:
        c = data.get_config(key)
    except KeyError:
        logger.warning("Ignoring unknown configuration option %s" % key)
        return
    c['is_new'] = False
    logger.debug(c)
    if 'title' in c:
        logger.debug("Setting %s : %s " % (key, value))
        if c['datatype'] == 'bool':
            value = True if value == 'y' else False
        set_config(key, value, is_user_set)
Ejemplo n.º 10
0
def config_to_json():
    properties = dict()

    for key in data.get_config_list():
        c = data.get_config(key)
        key = key.lower()
        datatype = c["datatype"]
        value = c["value"]

        if datatype == "bool":
            properties[key] = value
        elif datatype == "int":
            properties[key] = int(value)
        elif datatype == "string":
            properties[key] = value
        else:
            logger.error("Invalid config type: %s (with value '%s')\n" %
                         (datatype, str(value)))

    return properties
Ejemplo n.º 11
0
 def get_help(self):
     if self.type in ["config", "menuconfig"]:
         config = data.get_config(self.value)
         text = self.value + ": " + config['title'] + "\n\n"
         if "help" in config:
             text += config['help']
         else:
             text += "No help available"
         return text
     elif self.type in ["choice"]:
         choice = data.get_choice_group(self.value)
         text = choice['title'] + "\n\n"
         if "help" in choice:
             text += choice['help']
         else:
             text += "No help available"
         return text
     elif self.type in ["menu"]:
         config = data.get_menu(self.value)
         if 'help' in config:
             return config['help']
     return "No help available"
Ejemplo n.º 12
0
def _condexpr_value(e):
    """Evaluate the value of the input expression.
    """
    assert type(e) == tuple
    assert len(e) in [2, 3]

    if len(e) == 3:
        if e[0] in ARITH_SET:
            return _expr_value(e)

        left = _condexpr_value(e[1])
        right = _condexpr_value(e[2])
        if type(left) != type(right):
            # Boolean result expected
            return False
        elif e[0] == 'and':
            return left and right
        elif e[0] == 'or':
            return left or right
        elif e[0] == '=':
            return left == right
        elif e[0] == '!=':
            return left != right
        elif e[0] == '>':
            return left > right
        elif e[0] == '>=':
            return left >= right
        elif e[0] == '<':
            return left < right
        elif e[0] == '<=':
            return left <= right
    elif e[0] == 'not':
        return not _condexpr_value(e[1])
    elif e[0] in ['string', 'number', 'boolean']:
        return e[1]
    elif e[0] == 'identifier':
        return get_config(e[1])['value']

    raise Exception("Unexpected depend list: " + str(e))
def force_config(key, value, source):
    try:
        c = data.get_config(key)
    except KeyError:
        logger.warn("Ignoring unknown configuration option %s" % key)
        return

    if value is True:
        if source in c['selected_by']:
            return
        c['selected_by'].add(source)
    elif source in c['selected_by']:
        c['selected_by'].remove(source)
    else:
        # Option wasn't previously forced, so don't change it
        return

    if len(c['selected_by']) > 0:
        set_config_internal(key, True)
    elif 'requested_value' in c:
        set_config(key, c['requested_value'])
    else:
        update_defaults(key)
Ejemplo n.º 14
0
def menu_parse():
    menus = {None: []}
    for i in data.get_menu_list():
        menus[i] = []

    menuconfig_stack = []
    depends_stack = []

    for (i_type, i_symbol) in data.iter_symbols_menuorder():
        if i_type == "config":
            config = data.get_config(i_symbol)
            inmenu = config.get('inmenu')

            if 'title' not in config:
                # No title, so we don't display it
                continue

            while len(depends_stack) > 0:
                if expr.check_depends(config.get('depends'),
                                      depends_stack[-1]):
                    break
                depends_stack.pop()

            while len(menuconfig_stack) > 0:
                if expr.check_depends(config.get('depends'),
                                      menuconfig_stack[-1]):
                    inmenu = menuconfig_stack[-1]
                    break
                menuconfig_stack.pop()
                depends_stack = []

            if 'choice_group' in config:
                inmenu = config['choice_group']

            config['depends_indent'] = len(depends_stack)

            menus[inmenu].append(MenuItem('config', i_symbol))

            depends_stack.append(i_symbol)
        elif i_type == "menuconfig":
            config = data.get_config(i_symbol)
            inmenu = config.get('inmenu')

            while len(menuconfig_stack) > 0:
                if expr.check_depends(config.get('depends'),
                                      menuconfig_stack[-1]):
                    inmenu = menuconfig_stack[-1]
                    break
                menuconfig_stack.pop()

            menuconfig_stack.append(i_symbol)
            menus[i_symbol] = []

            menus[inmenu].append(MenuItem('menuconfig', i_symbol))
        elif i_type == "menu":
            menu = data.get_menu(i_symbol)
            inmenu = menu.get('inmenu')

            menuconfig_stack = []

            menus[inmenu].append(MenuItem('menu', i_symbol))
        elif i_type == "choice":
            inmenu = data.get_choice_group(i_symbol).get('inmenu')

            menus[i_symbol] = []

            menus[inmenu].append(MenuItem('choice', i_symbol))
        else:
            raise Exception("Unexpected menu item: type {}, symbol {}".format(
                i_type, i_symbol))
    return menus
Ejemplo n.º 15
0
 def get_title(self):
     return data.get_config(self.value).get('title')
Ejemplo n.º 16
0
 def needs_inputbox(self):
     if self.type == "config":
         config = data.get_config(self.value)
         return config['datatype'] in ["string", "int"]
     return False
Ejemplo n.º 17
0
    def get_styled_text(self, is_selected, max_width):
        text_parts = []
        if self.type == "config":
            config = data.get_config(self.value)

            indent = config.get("depends_indent") or 0
            # Display "(new)" next to menu options that have no previously selected value
            new_text = " (new)" if config.get('is_new') else ""

            show_value = display_value(config['value'], config['datatype'])
            if len(config['selected_by']) > 0:
                text_parts.append(StyledText("-"))
                text_parts.append(StyledText("%s" % show_value))
                text_parts.append(StyledText("-"))
            elif 'choice_group' in config or config['datatype'] != "bool":
                text_parts.append(StyledText("("))
                trim_to = max_width - len(
                    config['title']) - indent - len(new_text) - 3
                trim_to = max(trim_to, 8)  # we want to display something
                if trim_to >= len(show_value):
                    text_parts.append(StyledText("%s" % show_value))
                else:
                    text_parts.append(
                        StyledText("%s..." % show_value[:(trim_to - 3)]))
                text_parts.append(StyledText(")"))
            else:
                text_parts.append(StyledText("["))
                text_parts.append(StyledText("%s" % show_value))
                text_parts.append(StyledText("]"))

            if config['is_user_set']:
                text_parts[1].style = 'option_set_by_user'

            text_parts.append(
                StyledText(" %s%s%s" % ("  " *
                                        (indent), config['title'], new_text)))
        elif self.type == "menu":
            text_parts.append(StyledText("   "))
            text_parts.append(
                StyledText(" %s --->" % data.get_menu_title(self.value)))
        elif self.type == "menuconfig":
            config = data.get_config(self.value)
            is_menu_enabled = '>'
            if config['value'] is False:
                # Submenu is empty
                is_menu_enabled = '-'

            text_parts.append(StyledText("["))
            show_value = display_value(config['value'], config['datatype'])
            trim_to = max_width - len(config['title']) - 5
            trim_to = max(trim_to, 8)  # we want to display something
            if trim_to >= len(show_value):
                text_parts.append(StyledText("%s" % show_value))
            else:
                text_parts.append(
                    StyledText("%s..." % show_value[:(trim_to - 5)]))
            text_parts.append(StyledText("]"))
            text_parts.append(
                StyledText(" %s ---%s" % (config['title'], is_menu_enabled)))

            if config['is_user_set']:
                text_parts[1].style = 'option_set_by_user'
        elif self.type == "choice":
            choice = data.get_choice_group(self.value)
            current_value = ''
            for i in choice['configs']:
                if data.get_config(i)['value'] is True:
                    current_value = data.get_config(i).get('title')
                    break
            text_parts.append(StyledText("   "))
            text_parts.append(
                StyledText(" %s (%s)" % (choice['title'], current_value)))
        elif self.type == "empty":
            text_parts.append(StyledText("***"))
            text_parts.append(StyledText(" Empty Menu ***"))
        else:
            raise Exception("Unknown type (%s)" % self.type)

        text_parts[
            -1].style = 'highlight' if is_selected else get_default_style()
        return text_parts
Ejemplo n.º 18
0
 def is_menu(self):
     if self.type == "menuconfig" and data.get_config(
             self.value)['value'] is False:
         # Prevent entry to a menuconfig that is disabled
         return False
     return self.type in ["menu", "menuconfig", "choice"]
Ejemplo n.º 19
0
def get_config_string(key):
    c = data.get_config(key)
    assert c['datatype'] == 'string', \
        'Config option %s is not a string (has type %s)' % (key, c['datatype'])
    return c['value']
Ejemplo n.º 20
0
def get_config_int(key):
    c = data.get_config(key)
    assert c['datatype'] == 'int', \
        'Config option %s is not an int (has type %s)' % (key, c['datatype'])
    return int(c['value'])
Ejemplo n.º 21
0
def set_config(key, value, is_user_set=True):
    try:
        c = data.get_config(key)
    except KeyError:
        logger.warning("Ignoring unknown configuration option %s" % key)
        return

    if is_user_set:
        # Validate user input
        if c['datatype'] == 'bool':
            # Must be y or n
            if value not in [True, False]:
                logger.warning(
                    "Ignoring boolean configuration option %s with non-boolean value '%s'."
                    % (key, value))
                return
        elif c['datatype'] == 'int':
            # Must convert to an integer
            try:
                value = int(value)
            except ValueError:
                logger.warning(
                    "Ignoring integer configuration option %s with non-integer value '%s'"
                    % (key, value))
                return

    # Record user specified value even if it is (currently) impossible
    c['is_user_set'] |= is_user_set
    if is_user_set:
        if "choice_group" in c:
            group = c['choice_group']
            if value is True:
                # Record the selection for this group
                data.get_choice_group(group)['requested_value'] = key
        else:
            c['requested_value'] = value

    if c['datatype'] == 'bool':
        if value is False and len(c['selected_by']) > 0:
            # Option is forced, so cannot be turned off
            return
        if value is True and not can_enable(c):
            # Option is unavailable, so cannot be turned on. However if the
            # option is selected by another we force it on regardless
            if len(c['selected_by']) == 0:
                return

    c['value'] = value
    if is_user_set:
        c['is_new'] = False

    if "choice_group" in c:
        group = c['choice_group']
        cg = data.get_choice_group(group)

        if value is True:
            # Record the selection for this group
            cg['selected'] = key
            # Member of a choice group - unset all other items
            for k in cg['configs']:
                if k != key:
                    set_config(k, False, is_user_set=is_user_set)
                    if data.get_config(k)['value'] is True:
                        # Failed to turn the other option off, so set this to n
                        c['value'] = False
                        return
        else:
            # Check if this is the last entry in a choice being unset.
            # If there is no other option set then either this entry will be
            # set back to 'y' - or if this entry cannot be set, the best default
            # entry in the choice will be picked
            for k in cg['configs']:
                if k != key and data.get_config(k)['value'] is True:
                    break
            else:
                if can_enable(c):
                    cg['selected'] = key
                    c['value'] = True
                else:
                    # Reset current selection.
                    cg['selected'] = None
                    update_choice_default(group)

    if "select" in c:
        for k in c["select"]:
            force_config(k, value, key)

    set_config_selectifs(key)

    if "rdepends" in c:
        # Check any reverse dependencies to see if they need updating
        for k in c['rdepends']:
            c2 = data.get_config(k)
            if c2['value'] is True and not can_enable(c2):
                set_config_internal(k, False)
            elif not c2['is_user_set']:
                update_defaults(k)
            elif "choice_group" in c2:
                update_choice_default(c2['choice_group'])
            elif 'requested_value' in c2 and c2['value'] != c2[
                    'requested_value']:
                set_config(k, c2['requested_value'])

    if "rdefault" in c:
        # Check whether any default values need updating
        for k in c['rdefault']:
            update_defaults(k)

    if "rselect_if" in c:
        # Update any select_ifs that might now be valid
        for k in c['rselect_if']:
            set_config_selectifs(k)
Ejemplo n.º 22
0
def get_options_selecting(selected):
    """Return the options which select `selected`"""
    opt = data.get_config(selected)
    return opt.get("selected_by", [])
Ejemplo n.º 23
0
def set_initial_values():
    "Set all configuration objects to their default value"

    config_list = data.get_config_list()

    # Set up initial values, and set up reverse dependencies
    for k in config_list:
        c = data.get_config(k)
        c['selected_by'] = set()
        c['is_user_set'] = False
        c['is_new'] = True
        if c['datatype'] == "bool":
            c['value'] = False
        elif c['datatype'] == "int":
            c['value'] = 0
        else:
            c['value'] = ''

        for i in expr.dependency_list(c.get("depends")):
            data.get_config(i).setdefault('rdepends', []).append(k)

        if "default_cond" in c:
            for j in c['default_cond']:
                for i in expr.dependency_list(j['cond']):
                    data.get_config(i).setdefault('rdefault', []).append(k)
                value_deps = expr.dependency_list(j['expr'])
                for d in value_deps:
                    data.get_config(d).setdefault('rdefault', []).append(k)

        if "default" in c:
            value_deps = expr.dependency_list(c['default'])
            for d in value_deps:
                data.get_config(d).setdefault('rdefault', []).append(k)

        if "select_if" in c:
            for j in c['select_if']:
                for i in expr.dependency_list(j[1]):
                    data.get_config(i).setdefault('rselect_if', []).append(k)

    # Check for dependency cycles
    for k in config_list:
        c = data.get_config(k)
        if k in c.get('rdepends', []):
            logger.error("%s depends on itself" % k)
            c['rdepends'].remove(k)
        if k in c.get('rdefault', []):
            logger.error("The default value of %s depends on itself" % k)
            c['rdefault'].remove(k)

    # Set values using defaults and taking into account dependencies
    for k in config_list:
        update_defaults(k)