Example #1
0
def annotate_config_with_metadata(config, meta_config, ignore_regexes=None,
                                  metadata_properties=None):
    """Add metadata to the rose.config.ConfigNode.comments attribute.

    config -- a rose.config.ConfigNode instance, containing app or
              suite data.
    meta_config -- a rose.config.ConfigNode instance, containing
                   metadata for config.
    ignore_regexes -- (default None) a list of uncompiled regular
                      expressions - if a setting contains any of these,
                      don't include it in the annotated output.

    """

    if ignore_regexes is None:
        ignore_regexes = []
    ignore_recs = [re.compile(_) for _ in ignore_regexes]
    unset_keys = []
    for keylist, node in config.walk():
        section = keylist[0]
        option = None
        if len(keylist) > 1:
            option = keylist[1]
        id_ = rose.macro.get_id_from_section_option(section, option)
        if any(_.search(id_) for _ in ignore_recs):
            unset_keys.append(keylist)
            continue
        metadata = rose.macro.get_metadata_for_config_id(id_, meta_config)
        metadata_text = format_metadata_as_text(
            metadata, only_these_options=metadata_properties)
        metadata_lines = [" " + line for line in metadata_text.splitlines()]
        node.comments = metadata_lines + node.comments
    for keylist in unset_keys:
        config.unset(keylist)
    return config
Example #2
0
    def rename_setting(self, config, keys, new_keys, info=None):
        """Rename a setting in the configuration.

        Args:
            config (rose.config.ConfigNode): The application configuration.
            keys (list): A list defining a hierarchy of node.value 'keys'.
                A section will be a list of one keys, an option will have two.
            new_keys (list): The new hierarchy of node.value 'keys'.
            info (string - optional): A short string containing no new lines,
                describing the addition of the setting.

        Returns:
            None
        """
        section, option = self._get_section_option_from_keys(keys)
        new_section, new_option = self._get_section_option_from_keys(new_keys)
        if option is None:
            if new_option is not None:
                raise TypeError(
                    self.ERROR_RENAME_SECT_TO_OPT.format(
                        section, new_section, new_option))
        elif new_option is None:
            raise TypeError(
                self.ERROR_RENAME_OPT_TO_SECT.format(section, option,
                                                     new_section))
        node = config.get(keys)
        if node is None:
            return
        if info is None:
            if option is None:
                info = self.INFO_RENAMED_SECT.format(section, new_section)
            else:
                info = self.INFO_RENAMED_VAR.format(section, option,
                                                    new_section, new_option)
        if option is None:
            if config.get([new_section]) is not None:
                self.remove_setting(config, [new_section])
            self.add_setting(config, [new_section],
                             value=None,
                             forced=True,
                             state=node.state,
                             comments=node.comments,
                             info=info)
            for option_keys, opt_node in config.walk([section]):
                renamed_option = option_keys[1]
                self.add_setting(config, [new_section, renamed_option],
                                 value=opt_node.value,
                                 forced=True,
                                 state=opt_node.state,
                                 comments=opt_node.comments,
                                 info=info)
        else:
            self.add_setting(config,
                             new_keys,
                             value=node.value,
                             forced=True,
                             state=node.state,
                             comments=node.comments,
                             info=info)
        self.remove_setting(config, keys)
Example #3
0
def pretty_format_config(config):
    """Improve configuration prettiness."""
    for section in config.value.keys():
        keylist = [section]
        scheme = keylist[0]
        if ":" in scheme:
            scheme = scheme.split(":", 1)[0]
        try:
            scheme_module = getattr(rose.formats, scheme)
            pretty_format_keys = getattr(scheme_module, "pretty_format_keys")
            pretty_format_value = getattr(scheme_module, "pretty_format_value")
        except AttributeError:
            continue
        new_keylist = pretty_format_keys(keylist)
        if new_keylist != keylist:
            node = config.get(keylist)
            config.unset(keylist)
            config.set(new_keylist, node.value, node.state, node.comments)
            section = new_keylist[0]
        for keylist, node in list(config.walk([section])):
            values = rose.variable.array_split(node.value, ",")
            node.value = pretty_format_value(values)   
            new_keylist = pretty_format_keys(keylist)
            if new_keylist != keylist:
                config.unset(keylist)
                config.set(new_keylist, node.value, node.state, node.comments)
Example #4
0
 def remove_setting(self, config, keys, info=None):
     """Remove a setting from the configuration."""
     section, option = self._get_section_option_from_keys(keys)
     if option is None:
         if config.get([section]) is None:
             return False
         option_node_pairs = config.walk([section])
         for opt_keys, option_node in option_node_pairs:
             opt = opt_keys[1]
             self._remove_setting(config, [section, opt], info)
     return self._remove_setting(config, [section, option], info)
Example #5
0
 def remove_setting(self, config, keys, info=None):
     """Remove a setting from the configuration."""
     section, option = self._get_section_option_from_keys(keys)
     if option is None:
         if config.get([section]) is None:
             return False
         option_node_pairs = config.walk([section])
         for opt_keys, option_node in option_node_pairs:
             opt = opt_keys[1]
             self._remove_setting(config, [section, opt], info)
     return self._remove_setting(config, [section, option], info)
Example #6
0
    def transform(self, config, meta_config=None):
        """Apply metadata trigger expressions to variables."""
        self.reports = []
        meta_config = self._load_meta_config(config, meta_config)
        self._setup_triggers(meta_config)
        self.enabled_dict = {}
        self.ignored_dict = {}
        enabled = rose.config.ConfigNode.STATE_NORMAL
        trig_ignored = rose.config.ConfigNode.STATE_SYST_IGNORED
        user_ignored = rose.config.ConfigNode.STATE_USER_IGNORED
        state_map = {
            enabled: 'enabled     ',
            trig_ignored: 'trig-ignored',
            user_ignored: 'user-ignored'
        }
        id_list = []
        prev_ignoreds = {trig_ignored: [], user_ignored: []}
        for keylist, node in config.walk():
            if len(keylist) == 1:
                n_id = keylist[0]
            else:
                n_id = self._get_id_from_section_option(*keylist)
            id_list.append(n_id)
            if node.state in prev_ignoreds:
                prev_ignoreds[node.state].append(n_id)

        ranked_ids = self._get_ranked_trigger_ids()
        for _, var_id in sorted(ranked_ids):
            self.update(var_id, config, meta_config)

        # Report any discrepancies in ignored status.
        for var_id in id_list:
            section, option = self._get_section_option_from_id(var_id)
            node = config.get([section, option])
            old, new = None, None
            if var_id in self.ignored_dict:
                node.state = trig_ignored
                if not any(var_id in v for v in prev_ignoreds.values()):
                    old, new = state_map[enabled], state_map[trig_ignored]
            elif var_id in prev_ignoreds[trig_ignored]:
                node.state = enabled
                old, new = state_map[trig_ignored], state_map[enabled]
            elif (var_id in prev_ignoreds[user_ignored]
                  and var_id in self._trigger_involved_ids):
                node.state = enabled
                old, new = state_map[user_ignored], state_map[enabled]
            if old != new:
                info = self.WARNING_STATE_CHANGED.format(old, new)
                if option is None:
                    value = None
                else:
                    value = node.value
                self.add_report(section, option, value, info)
        return config, self.reports
Example #7
0
    def add_setting(self, config, keys, value=None, forced=False, state=None, comments=None, info=None):
        """Add a setting to the configuration."""
        section, option = self._get_section_option_from_keys(keys)
        id_ = self._get_id_from_section_option(section, option)
        if option is not None and value is None:
            value = ""
        if info is None:
            if option is None:
                info = self.INFO_ADDED_SECT
            else:
                info = self.INFO_ADDED_VAR.format(repr(value))

        # Search for existing conflicting settings.
        found_setting = False
        if config.get([section, option]) is None:
            strip_dupl = rose.macro.REC_ID_STRIP
            for keys, node in config.walk():
                existing_section = keys[0]
                existing_base_section = rose.macro.REC_ID_STRIP.sub("", existing_section)
                if len(keys) == 1:
                    existing_option = None
                    existing_base_option = None
                else:
                    existing_option = keys[1]
                    existing_base_option = rose.macro.REC_ID_STRIP_DUPL.sub("", existing_option)
                if option is None:
                    # For section 'foo', look for 'foo', 'foo{bar}', 'foo(1)'.
                    if existing_section == section or existing_base_section == section:
                        found_setting = True
                        break
                # For option 'foo', look for 'foo', 'foo(1)'.
                elif existing_section == section and (existing_option == option or existing_base_option == option):
                    found_setting = True
                    break
        else:
            found_setting = True

        # If already added, quit, unless "forced".
        if found_setting:
            if forced:
                # If forced, override the existing properties.
                return self.change_setting_value(config, keys, value, state, comments, info)
            return False

        # Add parent section if missing.
        if option is not None and config.get([section]) is None:
            self.add_setting(config, [section])
        if value is not None and not isinstance(value, basestring):
            text = "New value {0} for {1} is not a string"
            raise ValueError(text.format(repr(value), id_))

        # Set (add) the section/option.
        config.set([section, option], value=value, state=state, comments=comments)
        self.add_report(section, option, value, info)
Example #8
0
    def transform(self, config, meta_config=None):
        """Apply metadata trigger expressions to variables."""
        self.reports = []
        meta_config = self._load_meta_config(config, meta_config)
        self._setup_triggers(meta_config)
        self.enabled_dict = {}
        self.ignored_dict = {}
        enabled = rose.config.ConfigNode.STATE_NORMAL
        trig_ignored = rose.config.ConfigNode.STATE_SYST_IGNORED
        user_ignored = rose.config.ConfigNode.STATE_USER_IGNORED
        state_map = {enabled: 'enabled     ',
                     trig_ignored: 'trig-ignored',
                     user_ignored: 'user-ignored'}
        id_list = []
        prev_ignoreds = {trig_ignored: [], user_ignored: []}
        for keylist, node in config.walk():
            if len(keylist) == 1:
                n_id = keylist[0]
            else:
                n_id = self._get_id_from_section_option(*keylist)
            id_list.append(n_id)
            if node.state in prev_ignoreds:
                prev_ignoreds[node.state].append(n_id)

        ranked_ids = self._get_ranked_trigger_ids()
        for rank, var_id in sorted(ranked_ids):
            self.update(var_id, config, meta_config)

        # Report any discrepancies in ignored status.
        for var_id in id_list:
            section, option = self._get_section_option_from_id(var_id)
            node = config.get([section, option])
            old, new = None, None
            if var_id in self.ignored_dict:
                node.state = trig_ignored
                if not any([var_id in v for k, v in prev_ignoreds.items()]):
                    old, new = state_map[enabled], state_map[trig_ignored]
            elif var_id in prev_ignoreds[trig_ignored]:
                node.state = enabled
                old, new = state_map[trig_ignored], state_map[enabled]
            elif (var_id in prev_ignoreds[user_ignored] and
                  var_id in self._trigger_involved_ids):
                node.state = enabled
                old, new = state_map[user_ignored], state_map[enabled]
            if old != new:
                info = self.WARNING_STATE_CHANGED.format(old, new)
                if option is None:
                    value = None
                else:
                    value = node.value
                self.add_report(section, option, value, info)
        return config, self.reports
Example #9
0
File: macro.py Project: kaday/rose
def standard_format_config(config):
    """Standardise any degenerate representations e.g. namelist repeats."""
    for keylist, node in config.walk():
        if len(keylist) == 2:
            scheme, option = keylist
            if ":" in scheme:
                scheme = scheme.split(":", 1)[0]
            try:
                scheme_module = getattr(rose.formats, scheme)
                standard_format = getattr(scheme_module, "standard_format")
            except AttributeError:
                continue
            values = rose.variable.array_split(node.value, ",")
            node.value = standard_format(values)
Example #10
0
def pretty_format_config(config):
    """Improve configuration prettiness."""
    for keylist, node in config.walk():
        if len(keylist) == 2:
            scheme, option = keylist
            if ":" in scheme:
                scheme = scheme.split(":", 1)[0]
            try:
                scheme_module = getattr(rose.formats, scheme)
                pretty_format = getattr(scheme_module, "pretty_format")
            except AttributeError:
                continue
            values = rose.variable.array_split(node.value, ",")
            node.value = pretty_format(values)
Example #11
0
def metadata_gen(config, meta_config=None, auto_type=False, prop_map=None):
    """Automatically guess the metadata for an application configuration."""
    if prop_map is None:
        prop_map = {}
    rose.macro.standard_format_config(config)
    if meta_config is None:
        meta_config = rose.config.ConfigNode()
    for keylist, node in config.walk():
        sect = keylist[0]
        if len(keylist) == 1:
            option = None
        else:
            option = keylist[1]
        if sect in [rose.CONFIG_SECT_CMD]:
            continue
        if keylist == [rose.CONFIG_SECT_TOP, rose.CONFIG_OPT_META_TYPE]:
            continue
        meta_sect = rose.macro.REC_ID_STRIP.sub("", sect)
        modifier_sect = rose.macro.REC_ID_STRIP_DUPL.sub("", sect)
        if sect and option is None:
            if (modifier_sect != meta_sect and modifier_sect != sect
                    and meta_config.get([modifier_sect]) is None
                    and auto_type):
                meta_config.set([modifier_sect, rose.META_PROP_DUPLICATE],
                                rose.META_PROP_VALUE_TRUE)
            if meta_config.get([meta_sect]) is not None:
                continue
            meta_config.set([meta_sect])
            if meta_sect != sect and auto_type:
                # Add duplicate = true at base and modifier level (if needed).
                meta_config.set([meta_sect, rose.META_PROP_DUPLICATE],
                                rose.META_PROP_VALUE_TRUE)
            for prop_key, prop_value in prop_map.items():
                meta_config.set([meta_sect, prop_key], prop_value)
        if option is None:
            continue
        meta_key = rose.macro.REC_ID_STRIP_DUPL.sub('', option)
        meta_opt = meta_sect + "=" + meta_key
        if meta_config.get([meta_opt]) is not None:
            continue
        meta_config.set([meta_opt])
        for prop_key, prop_value in prop_map.items():
            meta_config.set([meta_opt, prop_key], prop_value)
        if auto_type:
            opt_type, length = type_gen(node.value)
            if opt_type is not None:
                meta_config.set([meta_opt, rose.META_PROP_TYPE], opt_type)
            if int(length) > 1:
                meta_config.set([meta_opt, rose.META_PROP_LENGTH], length)
    return meta_config
Example #12
0
File: macro.py Project: csimag/rose
def standard_format_config(config):
    """Standardise any degenerate representations e.g. namelist repeats."""
    for keylist, node in config.walk():
        if len(keylist) == 2:
            scheme, option = keylist
            if ":" in scheme:
                scheme = scheme.split(":", 1)[0]
            try:
                scheme_module = getattr(rose.formats, scheme)
                standard_format = getattr(scheme_module, "standard_format")
            except AttributeError:
                continue
            values = rose.variable.array_split(node.value, ",")
            node.value = standard_format(values)
Example #13
0
def metadata_gen(config, meta_config=None, auto_type=False, prop_map=None):
    """Automatically guess the metadata for an application configuration."""
    if prop_map is None:
        prop_map = {}
    rose.macro.standard_format_config(config)
    if meta_config is None:
        meta_config = rose.config.ConfigNode()
    for keylist, node in config.walk():
        sect = keylist[0]
        if len(keylist) == 1:
            option = None
        else:
            option = keylist[1]
        if sect in [rose.CONFIG_SECT_CMD]:
            continue
        if keylist == [rose.CONFIG_SECT_TOP, rose.CONFIG_OPT_META_TYPE]:
            continue
        meta_sect = rose.macro.REC_ID_STRIP.sub("", sect)
        modifier_sect = rose.macro.REC_ID_STRIP_DUPL.sub("", sect)
        if sect and option is None:
            if (modifier_sect != meta_sect and
                    modifier_sect != sect and
                    meta_config.get([modifier_sect]) is None and auto_type):
                meta_config.set([modifier_sect, rose.META_PROP_DUPLICATE],
                                rose.META_PROP_VALUE_TRUE)
            if meta_config.get([meta_sect]) is not None:
                continue
            meta_config.set([meta_sect])
            if meta_sect != sect and auto_type:
                # Add duplicate = true at base and modifier level (if needed).
                meta_config.set([meta_sect, rose.META_PROP_DUPLICATE],
                                rose.META_PROP_VALUE_TRUE)
            for prop_key, prop_value in prop_map.items():
                meta_config.set([meta_sect, prop_key], prop_value)
        if option is None:
            continue
        meta_key = rose.macro.REC_ID_STRIP_DUPL.sub('', option)
        meta_opt = meta_sect + "=" + meta_key
        if meta_config.get([meta_opt]) is not None:
            continue
        meta_config.set([meta_opt])
        for prop_key, prop_value in prop_map.items():
            meta_config.set([meta_opt, prop_key], prop_value)
        if auto_type:
            opt_type, length = type_gen(node.value)
            if opt_type is not None:
                meta_config.set([meta_opt, rose.META_PROP_TYPE], opt_type)
            if int(length) > 1:
                meta_config.set([meta_opt, rose.META_PROP_LENGTH], length)
    return meta_config
Example #14
0
    def rename_setting(self, config, keys, new_keys, info=None):
        """Rename a setting in the configuration.

        Args:
            config (rose.config.ConfigNode): The application configuration.
            keys (list): A list defining a hierarchy of node.value 'keys'.
                A section will be a list of one keys, an option will have two.
            new_keys (list): The new hierarchy of node.value 'keys'.
            info (string - optional): A short string containing no new lines,
                describing the addition of the setting.

        Returns:
            None
        """
        section, option = self._get_section_option_from_keys(keys)
        new_section, new_option = self._get_section_option_from_keys(new_keys)
        if option is None:
            if new_option is not None:
                raise TypeError(self.ERROR_RENAME_SECT_TO_OPT.format(
                    section, new_section, new_option))
        elif new_option is None:
            raise TypeError(self.ERROR_RENAME_OPT_TO_SECT.format(
                section, option, new_section))
        node = config.get(keys)
        if node is None:
            return
        if info is None:
            if option is None:
                info = self.INFO_RENAMED_SECT.format(section, new_section)
            else:
                info = self.INFO_RENAMED_VAR.format(section, option,
                                                    new_section, new_option)
        if option is None:
            if config.get([new_section]) is not None:
                self.remove_setting(config, [new_section])
            self.add_setting(config, [new_section], value=None, forced=True,
                             state=node.state, comments=node.comments,
                             info=info)
            for option_keys, opt_node in config.walk([section]):
                renamed_option = option_keys[1]
                self.add_setting(config, [new_section, renamed_option],
                                 value=opt_node.value, forced=True,
                                 state=opt_node.state,
                                 comments=opt_node.comments, info=info)
        else:
            self.add_setting(config, new_keys, value=node.value, forced=True,
                             state=node.state, comments=node.comments,
                             info=info)
        self.remove_setting(config, keys)
Example #15
0
 def rename_setting(self, config, keys, new_keys, info=None):
     """Rename a setting in the configuration."""
     section, option = self._get_section_option_from_keys(keys)
     new_section, new_option = self._get_section_option_from_keys(new_keys)
     if option is None:
         if new_option is not None:
             raise TypeError(
                 self.ERROR_RENAME_SECT_TO_OPT.format(
                     section, new_section, new_option))
     elif new_option is None:
         raise TypeError(
             self.ERROR_RENAME_OPT_TO_SECT.format(section, option,
                                                  new_section))
     node = config.get(keys)
     if node is None:
         return
     if info is None:
         if option is None:
             info = self.INFO_RENAMED_SECT.format(section, new_section)
         else:
             info = self.INFO_RENAMED_VAR.format(section, option,
                                                 new_section, new_option)
     if option is None:
         if config.get([new_section]) is not None:
             self.remove_setting(config, [new_section])
         self.add_setting(config, [new_section],
                          value=None,
                          forced=True,
                          state=node.state,
                          comments=node.comments,
                          info=info)
         for option_keys, opt_node in config.walk([section]):
             renamed_option = option_keys[1]
             self.add_setting(config, [new_section, renamed_option],
                              value=opt_node.value,
                              forced=True,
                              state=opt_node.state,
                              comments=opt_node.comments,
                              info=info)
     else:
         self.add_setting(config,
                          new_keys,
                          value=node.value,
                          forced=True,
                          state=node.state,
                          comments=node.comments,
                          info=info)
     self.remove_setting(config, keys)
Example #16
0
    def get_stashmaster_meta_lookup_dict(self):
        """Return a nested dictionary with STASHmaster metadata.

        This stores metadata about STASHmaster fields and their values.
        Field metadata is stored as field_name => metadata_property =>
        metadata_value. Field value metadata (for a particular value of
        a field) is under (field_name + "=" + value) =>
        metadata_property => metadata_value.

        For example, if the nested dictionary is called
        'stash_meta_dict':
        stash_meta_dict["grid"]["title"]
        would be something like:
        "Grid code"
        and:
        stash_meta_dict["grid=2"]["description"]
        would be something like:
        "A grid code of 2 means...."

        """
        if self.STASHMASTER_META_PATH is None:
            return {}
        try:
            config = rose.config_tree.ConfigTreeLoader().load(
                self.STASHMASTER_META_PATH,
                self.STASHMASTER_META_FILENAME).node
        except (rose.config.ConfigSyntaxError, IOError, OSError) as e:
            rose.reporter.Reporter()(
                "Error loading STASHmaster metadata resource: " +
                type(e).__name__ + ": " + str(e) + "\n",
                kind=rose.reporter.Reporter.KIND_ERR,
                level=rose.reporter.Reporter.FAIL
            )
            return {}
        stash_meta_dict = {}
        for keys, node in config.walk(no_ignore=True):
            if len(keys) == 2:
                address = keys[0].replace("stashmaster:", "", 1)
                prop = keys[1]
                stash_meta_dict.setdefault(address, {})
                stash_meta_dict[address][prop] = node.value
        return stash_meta_dict
Example #17
0
    def get_stashmaster_meta_lookup_dict(self):
        """Return a nested dictionary with STASHmaster metadata.

        This stores metadata about STASHmaster fields and their values.
        Field metadata is stored as field_name => metadata_property =>
        metadata_value. Field value metadata (for a particular value of
        a field) is under (field_name + "=" + value) =>
        metadata_property => metadata_value.

        For example, if the nested dictionary is called
        'stash_meta_dict':
        stash_meta_dict["grid"]["title"]
        would be something like:
        "Grid code"
        and:
        stash_meta_dict["grid=2"]["description"]
        would be something like:
        "A grid code of 2 means...."

        """
        if self.STASHMASTER_META_PATH is None:
            return {}
        try:
            config = rose.config_tree.ConfigTreeLoader().load(
                self.STASHMASTER_META_PATH,
                self.STASHMASTER_META_FILENAME).node
        except (rose.config.ConfigSyntaxError, IOError, OSError) as e:
            rose.reporter.Reporter()(
                "Error loading STASHmaster metadata resource: " +
                type(e).__name__ + ": " + str(e) + "\n",
                kind=rose.reporter.Reporter.KIND_ERR,
                level=rose.reporter.Reporter.FAIL
            )
            return {}
        stash_meta_dict = {}
        for keys, node in config.walk(no_ignore=True):
            if len(keys) == 2:
                address = keys[0].replace("stashmaster:", "", 1)
                prop = keys[1]
                stash_meta_dict.setdefault(address, {})
                stash_meta_dict[address][prop] = node.value
        return stash_meta_dict
Example #18
0
    def remove_setting(self, config, keys, info=None):
        """Remove a setting from the configuration.

        Args:
            config (rose.config.ConfigNode): The application configuration.
            keys (list): A list defining a hierarchy of node.value 'keys'.
                A section will be a list of one keys, an option will have two.
            info (string - optional): A short string containing no new lines,
                describing the addition of the setting.

        Returns:
            None
        """
        section, option = self._get_section_option_from_keys(keys)
        if option is None:
            if config.get([section]) is None:
                return False
            option_node_pairs = config.walk([section])
            for opt_keys, _ in option_node_pairs:
                opt = opt_keys[1]
                self._remove_setting(config, [section, opt], info)
        return self._remove_setting(config, [section, option], info)
Example #19
0
 def rename_setting(self, config, keys, new_keys, info=None):
     """Rename a setting in the configuration."""
     section, option = self._get_section_option_from_keys(keys)
     new_section, new_option = self._get_section_option_from_keys(new_keys)
     if option is None:
         if new_option is not None:
             raise TypeError(self.ERROR_RENAME_SECT_TO_OPT.format(section, new_section, new_option))
     elif new_option is None:
         raise TypeError(self.ERROR_RENAME_OPT_TO_SECT.format(section, option, new_section))
     node = config.get(keys)
     if node is None:
         return
     if info is None:
         if option is None:
             info = self.INFO_RENAMED_SECT.format(section, new_section)
         else:
             info = self.INFO_RENAMED_VAR.format(section, option, new_section, new_option)
     if option is None:
         if config.get([new_section]) is not None:
             self.remove_setting(config, [new_section])
         self.add_setting(
             config, [new_section], value=None, forced=True, state=node.state, comments=node.comments, info=info
         )
         for option_keys, opt_node in config.walk([section]):
             renamed_option = option_keys[1]
             self.add_setting(
                 config,
                 [new_section, renamed_option],
                 value=opt_node.value,
                 forced=True,
                 state=opt_node.state,
                 comments=opt_node.comments,
                 info=info,
             )
     else:
         self.add_setting(
             config, new_keys, value=node.value, forced=True, state=node.state, comments=node.comments, info=info
         )
     self.remove_setting(config, keys)
Example #20
0
    def remove_setting(self, config, keys, info=None):
        """Remove a setting from the configuration.

        Args:
            config (rose.config.ConfigNode): The application configuration.
            keys (list): A list defining a hierarchy of node.value 'keys'.
                A section will be a list of one keys, an option will have two.
            info (string - optional): A short string containing no new lines,
                describing the addition of the setting.

        Returns:
            None
        """
        section, option = self._get_section_option_from_keys(keys)
        if option is None:
            if config.get([section]) is None:
                return False
            option_node_pairs = config.walk([section])
            for opt_keys, _ in option_node_pairs:
                opt = opt_keys[1]
                self._remove_setting(config, [section, opt], info)
        return self._remove_setting(config, [section, option], info)
Example #21
0
File: macro.py Project: kaday/rose
def combine_opt_config_map(config_map):
    """Combine optional configurations with a main configuration."""
    new_combined_config_map = {}
    main_config = config_map[None]
    for conf_key, config in config_map.items():
        if conf_key is None:
            new_combined_config_map[None] = copy.deepcopy(config)
            continue
        new_config = copy.deepcopy(main_config)
        for keylist, subnode in config.walk():
            old_subnode = new_config.get(keylist)
            if (isinstance(subnode.value, dict) and
                    old_subnode is not None and
                    isinstance(old_subnode.value, dict)):
                old_subnode.state = subnode.state
                old_subnode.comments = subnode.comments
            else:
                new_config.set(
                    keylist, value=copy.deepcopy(subnode.value),
                    state=subnode.state, comments=subnode.comments
                )
        new_combined_config_map[conf_key] = new_config
    return new_combined_config_map
Example #22
0
def annotate_config_with_metadata(config,
                                  meta_config,
                                  ignore_regexes=None,
                                  metadata_properties=None):
    """Add metadata to the rose.config.ConfigNode.comments attribute.

    config -- a rose.config.ConfigNode instance, containing app or
              suite data.
    meta_config -- a rose.config.ConfigNode instance, containing
                   metadata for config.
    ignore_regexes -- (default None) a list of uncompiled regular
                      expressions - if a setting contains any of these,
                      don't include it in the annotated output.

    """

    if ignore_regexes is None:
        ignore_regexes = []
    ignore_recs = [re.compile(_) for _ in ignore_regexes]
    unset_keys = []
    for keylist, node in config.walk():
        section = keylist[0]
        option = None
        if len(keylist) > 1:
            option = keylist[1]
        id_ = rose.macro.get_id_from_section_option(section, option)
        if any([_.search(id_) for _ in ignore_recs]):
            unset_keys.append(keylist)
            continue
        metadata = rose.macro.get_metadata_for_config_id(id_, meta_config)
        metadata_text = format_metadata_as_text(
            metadata, only_these_options=metadata_properties)
        metadata_lines = [" " + line for line in metadata_text.splitlines()]
        node.comments = metadata_lines + node.comments
    for keylist in unset_keys:
        config.unset(keylist)
    return config
Example #23
0
    def add_setting(self,
                    config,
                    keys,
                    value=None,
                    forced=False,
                    state=None,
                    comments=None,
                    info=None):
        """Add a setting to the configuration."""
        section, option = self._get_section_option_from_keys(keys)
        id_ = self._get_id_from_section_option(section, option)
        if option is not None and value is None:
            value = ""
        if info is None:
            if option is None:
                info = self.INFO_ADDED_SECT
            else:
                info = self.INFO_ADDED_VAR.format(repr(value))

        # Search for existing conflicting settings.
        conflict_id = None
        found_setting = False
        if config.get([section, option]) is None:
            strip_dupl = rose.macro.REC_ID_STRIP
            for key in config.get_value():
                existing_section = key
                if not existing_section.startswith(section):
                    continue
                existing_base_section = (rose.macro.REC_ID_STRIP.sub(
                    "", existing_section))
                if option is None:
                    # For section 'foo', look for 'foo', 'foo{bar}', 'foo(1)'.
                    found_setting = (existing_section == section
                                     or existing_base_section == section)
                else:
                    # For 'foo=bar', don't allow sections 'foo(1)', 'foo{bar}'.
                    found_setting = (existing_section != section
                                     and existing_base_section == section)
                if found_setting:
                    conflict_id = existing_section
                    break
                if option is not None:
                    for keys, node in config.walk([existing_section]):
                        existing_option = keys[1]
                        existing_base_option = (
                            rose.macro.REC_ID_STRIP_DUPL.sub(
                                "", existing_option))
                        # For option 'foo', look for 'foo', 'foo(1)'.
                        if (existing_section == section
                                and (existing_option == option
                                     or existing_base_option == option)):
                            found_setting = True
                            conflict_id = self._get_id_from_section_option(
                                existing_section, existing_option)
                            break
                    if found_setting:
                        break
        else:
            found_setting = True
            conflict_id = None

        # If already added, quit, unless "forced".
        if found_setting:
            if forced and (conflict_id is None or id_ == conflict_id):
                # If forced, override settings for an identical id.
                return self.change_setting_value(config, keys, value, state,
                                                 comments, info)
            if conflict_id:
                self.add_report(section,
                                option,
                                value,
                                self.WARNING_ADD_CLASH.format(
                                    id_, conflict_id),
                                is_warning=True)
            return False

        # Add parent section if missing.
        if option is not None and config.get([section]) is None:
            self.add_setting(config, [section])
        if value is not None and not isinstance(value, basestring):
            text = "New value {0} for {1} is not a string"
            raise ValueError(text.format(repr(value), id_))

        # Set (add) the section/option.
        config.set([section, option],
                   value=value,
                   state=state,
                   comments=comments)
        self.add_report(section, option, value, info)
Example #24
0
    def add_setting(self,
                    config,
                    keys,
                    value=None,
                    forced=False,
                    state=None,
                    comments=None,
                    info=None):
        """Add a setting to the configuration.

        Args:
            config (rose.config.ConfigNode): The application configuration.
            keys (list): A list defining a hierarchy of node.value 'keys'.
                A section will be a list of one keys, an option will have two.
            value (string - optional): String denoting the new setting value.
                Required for options but not for settings.
            forced (bool - optional)
                If True override value if the setting already exists.
            state (str - optional):
                The state of the new setting - should be one of the
                ``rose.config.ConfigNode`` states e.g.
                ``rose.config.ConfigNode.STATE_USER_IGNORED``. Defaults to
                ``rose.config.ConfigNode.STATE_NORMAL``.
            comments (list - optional): List of comment lines (strings) for
                the new setting or ``None``.
            info (string - optional): A short string containing no new lines,
                describing the addition of the setting.

        Returns:
            None
        """
        section, option = self._get_section_option_from_keys(keys)
        id_ = self._get_id_from_section_option(section, option)
        if option is not None and value is None:
            value = ""
        if info is None:
            if option is None:
                info = self.INFO_ADDED_SECT
            else:
                info = self.INFO_ADDED_VAR.format(repr(value))

        # Search for existing conflicting settings.
        conflict_id = None
        found_setting = False
        if config.get([section, option]) is None:
            for key in config.get_value():
                existing_section = key
                if not existing_section.startswith(section):
                    continue
                existing_base_section = (rose.macro.REC_ID_STRIP.sub(
                    "", existing_section))
                if option is None:
                    # For section 'foo', look for 'foo', 'foo{bar}', 'foo(1)'.
                    found_setting = (existing_section == section
                                     or existing_base_section == section)
                else:
                    # For 'foo=bar', don't allow sections 'foo(1)', 'foo{bar}'.
                    found_setting = (existing_section != section
                                     and existing_base_section == section)
                if found_setting:
                    conflict_id = existing_section
                    break
                if option is not None:
                    for keys, _ in config.walk([existing_section]):
                        existing_option = keys[1]
                        existing_base_option = (
                            rose.macro.REC_ID_STRIP_DUPL.sub(
                                "", existing_option))
                        # For option 'foo', look for 'foo', 'foo(1)'.
                        if (existing_section == section
                                and (existing_option == option
                                     or existing_base_option == option)):
                            found_setting = True
                            conflict_id = self._get_id_from_section_option(
                                existing_section, existing_option)
                            break
                    if found_setting:
                        break
        else:
            found_setting = True
            conflict_id = None

        # If already added, quit, unless "forced".
        if found_setting:
            if forced and (conflict_id is None or id_ == conflict_id):
                # If forced, override settings for an identical id.
                return self.change_setting_value(config, keys, value, state,
                                                 comments, info)
            if conflict_id:
                self.add_report(section,
                                option,
                                value,
                                self.WARNING_ADD_CLASH.format(
                                    id_, conflict_id),
                                is_warning=True)
            return False

        # Add parent section if missing.
        if option is not None and config.get([section]) is None:
            self.add_setting(config, [section])
        if value is not None and not isinstance(value, basestring):
            text = "New value {0} for {1} is not a string"
            raise ValueError(text.format(repr(value), id_))

        # Set (add) the section/option.
        config.set([section, option],
                   value=value,
                   state=state,
                   comments=comments)
        self.add_report(section, option, value, info)
Example #25
0
    def add_setting(self,
                    config,
                    keys,
                    value=None,
                    forced=False,
                    state=None,
                    comments=None,
                    info=None):
        """Add a setting to the configuration."""
        section, option = self._get_section_option_from_keys(keys)
        id_ = self._get_id_from_section_option(section, option)
        if option is not None and value is None:
            value = ""
        if info is None:
            if option is None:
                info = self.INFO_ADDED_SECT
            else:
                info = self.INFO_ADDED_VAR.format(repr(value))

        # Search for existing conflicting settings.
        found_setting = False
        if config.get([section, option]) is None:
            strip_dupl = rose.macro.REC_ID_STRIP
            for keys, node in config.walk():
                existing_section = keys[0]
                existing_base_section = (rose.macro.REC_ID_STRIP.sub(
                    "", existing_section))
                if len(keys) == 1:
                    existing_option = None
                    existing_base_option = None
                else:
                    existing_option = keys[1]
                    existing_base_option = (rose.macro.REC_ID_STRIP_DUPL.sub(
                        "", existing_option))
                if option is None:
                    # For section 'foo', look for 'foo', 'foo{bar}', 'foo(1)'.
                    if (existing_section == section
                            or existing_base_section == section):
                        found_setting = True
                        break
                # For option 'foo', look for 'foo', 'foo(1)'.
                elif (existing_section == section
                      and (existing_option == option
                           or existing_base_option == option)):
                    found_setting = True
                    break
        else:
            found_setting = True

        # If already added, quit, unless "forced".
        if found_setting:
            if forced:
                # If forced, override the existing properties.
                return self.change_setting_value(config, keys, value, state,
                                                 comments, info)
            return False

        # Add parent section if missing.
        if option is not None and config.get([section]) is None:
            self.add_setting(config, [section])
        if value is not None and not isinstance(value, basestring):
            text = "New value {0} for {1} is not a string"
            raise ValueError(text.format(repr(value), id_))

        # Set (add) the section/option.
        config.set([section, option],
                   value=value,
                   state=state,
                   comments=comments)
        self.add_report(section, option, value, info)
Example #26
0
    def add_setting(self, config, keys, value=None, forced=False,
                    state=None, comments=None, info=None):
        """Add a setting to the configuration."""
        section, option = self._get_section_option_from_keys(keys)
        id_ = self._get_id_from_section_option(section, option)
        if option is not None and value is None:
            value = ""
        if info is None:
            if option is None:
                info = self.INFO_ADDED_SECT
            else:
                info = self.INFO_ADDED_VAR.format(repr(value))

        # Search for existing conflicting settings.
        conflict_id = None
        found_setting = False
        if config.get([section, option]) is None:
            strip_dupl = rose.macro.REC_ID_STRIP
            for key in config.get_value():
                existing_section = key
                if not existing_section.startswith(section):
                    continue
                existing_base_section = (
                    rose.macro.REC_ID_STRIP.sub("", existing_section))
                if option is None:
                    # For section 'foo', look for 'foo', 'foo{bar}', 'foo(1)'.
                    found_setting = (existing_section == section or
                                     existing_base_section == section)
                else:
                    # For 'foo=bar', don't allow sections 'foo(1)', 'foo{bar}'.
                    found_setting = (existing_section != section and
                                     existing_base_section == section)
                if found_setting:
                    conflict_id = existing_section
                    break
                if option is not None:
                    for keys, node in config.walk([existing_section]):
                        existing_option = keys[1]
                        existing_base_option = (
                            rose.macro.REC_ID_STRIP_DUPL.sub(
                                "", existing_option)
                        )
                        # For option 'foo', look for 'foo', 'foo(1)'.
                        if (existing_section == section and
                                (existing_option == option or
                                 existing_base_option == option)):
                            found_setting = True
                            conflict_id = self._get_id_from_section_option(
                                existing_section, existing_option)
                            break
                    if found_setting:
                        break
        else:
            found_setting = True
            conflict_id = None

        # If already added, quit, unless "forced".
        if found_setting:
            if forced and (conflict_id is None or id_ == conflict_id):
                # If forced, override settings for an identical id.
                return self.change_setting_value(
                    config, keys, value, state, comments, info)
            if conflict_id:
                self.add_report(
                    section, option, value,
                    self.WARNING_ADD_CLASH.format(id_, conflict_id),
                    is_warning=True
                )
            return False

        # Add parent section if missing.
        if option is not None and config.get([section]) is None:
            self.add_setting(config, [section])
        if value is not None and not isinstance(value, basestring):
            text = "New value {0} for {1} is not a string"
            raise ValueError(text.format(repr(value), id_))

        # Set (add) the section/option.
        config.set([section, option], value=value, state=state,
                   comments=comments)
        self.add_report(section, option, value, info)
Example #27
0
    def add_setting(self, config, keys, value=None, forced=False,
                    state=None, comments=None, info=None):
        """Add a setting to the configuration.

        Args:
            config (rose.config.ConfigNode): The application configuration.
            keys (list): A list defining a hierarchy of node.value 'keys'.
                A section will be a list of one keys, an option will have two.
            value (string - optional): String denoting the new setting value.
                Required for options but not for settings.
            forced (bool - optional)
                If True override value if the setting already exists.
            state (str - optional):
                The state of the new setting - should be one of the
                ``rose.config.ConfigNode`` states e.g.
                ``rose.config.ConfigNode.STATE_USER_IGNORED``. Defaults to
                ``rose.config.ConfigNode.STATE_NORMAL``.
            comments (list - optional): List of comment lines (strings) for
                the new setting or ``None``.
            info (string - optional): A short string containing no new lines,
                describing the addition of the setting.

        Returns:
            None
        """
        section, option = self._get_section_option_from_keys(keys)
        id_ = self._get_id_from_section_option(section, option)
        if option is not None and value is None:
            value = ""
        if info is None:
            if option is None:
                info = self.INFO_ADDED_SECT
            else:
                info = self.INFO_ADDED_VAR.format(repr(value))

        # Search for existing conflicting settings.
        conflict_id = None
        found_setting = False
        if config.get([section, option]) is None:
            for key in config.get_value():
                existing_section = key
                if not existing_section.startswith(section):
                    continue
                existing_base_section = (
                    rose.macro.REC_ID_STRIP.sub("", existing_section))
                if option is None:
                    # For section 'foo', look for 'foo', 'foo{bar}', 'foo(1)'.
                    found_setting = (existing_section == section or
                                     existing_base_section == section)
                else:
                    # For 'foo=bar', don't allow sections 'foo(1)', 'foo{bar}'.
                    found_setting = (existing_section != section and
                                     existing_base_section == section)
                if found_setting:
                    conflict_id = existing_section
                    break
                if option is not None:
                    for keys, _ in config.walk([existing_section]):
                        existing_option = keys[1]
                        existing_base_option = (
                            rose.macro.REC_ID_STRIP_DUPL.sub(
                                "", existing_option)
                        )
                        # For option 'foo', look for 'foo', 'foo(1)'.
                        if (existing_section == section and
                                (existing_option == option or
                                 existing_base_option == option)):
                            found_setting = True
                            conflict_id = self._get_id_from_section_option(
                                existing_section, existing_option)
                            break
                    if found_setting:
                        break
        else:
            found_setting = True
            conflict_id = None

        # If already added, quit, unless "forced".
        if found_setting:
            if forced and (conflict_id is None or id_ == conflict_id):
                # If forced, override settings for an identical id.
                return self.change_setting_value(
                    config, keys, value, state, comments, info)
            if conflict_id:
                self.add_report(
                    section, option, value,
                    self.WARNING_ADD_CLASH.format(id_, conflict_id),
                    is_warning=True
                )
            return False

        # Add parent section if missing.
        if option is not None and config.get([section]) is None:
            self.add_setting(config, [section])
        if value is not None and not isinstance(value, str):
            text = "New value {0} for {1} is not a string"
            raise ValueError(text.format(repr(value), id_))

        # Set (add) the section/option.
        config.set([section, option], value=value, state=state,
                   comments=comments)
        self.add_report(section, option, value, info)