Exemplo n.º 1
0
def _merge_yaml(dest, source):
    """Merges source into dest; entries in source take precedence over dest.

    This routine may modify dest and should be assigned to dest, in
    case dest was None to begin with, e.g.:

       dest = _merge_yaml(dest, source)

    Config file authors can optionally end any attribute in a dict
    with `::` instead of `:`, and the key will override that of the
    parent instead of merging.
    """
    def they_are(t):
        return isinstance(dest, t) and isinstance(source, t)

    # If source is None, overwrite with source.
    if source is None:
        return None

    # Source list is prepended (for precedence)
    if they_are(list):
        dest[:] = source + [x for x in dest if x not in source]
        return dest

    # Source dict is merged into dest.
    elif they_are(dict):
        # track keys for marking
        key_marks = {}

        for sk, sv in iteritems(source):
            if _override(sk) or sk not in dest:
                # if sk ended with ::, or if it's new, completely override
                dest[sk] = copy.copy(sv)
            else:
                # otherwise, merge the YAML
                dest[sk] = _merge_yaml(dest[sk], source[sk])

            # this seems unintuitive, but see below. We need this because
            # Python dicts do not overwrite keys on insert, and we want
            # to copy mark information on source keys to dest.
            key_marks[sk] = sk

        # ensure that keys are marked in the destination. The
        # key_marks dict ensures we can get the actual source key
        # objects from dest keys
        for dk in list(dest.keys()):
            if dk in key_marks and syaml.markable(dk):
                syaml.mark(dk, key_marks[dk])
            elif dk in key_marks:
                # The destination key may not be markable if it was derived
                # from a schema default. In this case replace the key.
                val = dest.pop(dk)
                dest[key_marks[dk]] = val

        return dest

    # If we reach here source and dest are either different types or are
    # not both lists or dicts: replace with source.
    return copy.copy(source)
Exemplo n.º 2
0
def _mark_internal(data, name):
    """Add a simple name mark to raw YAML/JSON data.

    This is used by `spack config blame` to show where config lines came from.
    """
    if isinstance(data, dict):
        d = syaml.syaml_dict((_mark_internal(k, name), _mark_internal(v, name))
                             for k, v in data.items())
    elif isinstance(data, list):
        d = syaml.syaml_list(_mark_internal(e, name) for e in data)
    else:
        d = syaml.syaml_type(data)

    if syaml.markable(d):
        d._start_mark = yaml.Mark(name, None, None, None, None, None)
        d._end_mark = yaml.Mark(name, None, None, None, None, None)

    return d
Exemplo n.º 3
0
Arquivo: config.py Projeto: LLNL/spack
def _mark_internal(data, name):
    """Add a simple name mark to raw YAML/JSON data.

    This is used by `spack config blame` to show where config lines came from.
    """
    if isinstance(data, dict):
        d = syaml.syaml_dict((_mark_internal(k, name), _mark_internal(v, name))
                             for k, v in data.items())
    elif isinstance(data, list):
        d = syaml.syaml_list(_mark_internal(e, name) for e in data)
    else:
        d = syaml.syaml_type(data)

    if syaml.markable(d):
        d._start_mark = yaml.Mark(name, None, None, None, None, None)
        d._end_mark = yaml.Mark(name, None, None, None, None, None)

    return d