Esempio 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)
Esempio n. 2
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 both are None, handle specially and return None.
    if source is None and dest is None:
        return None

    # If source is None, overwrite with source.
    elif 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 dest.keys():
            if dk in key_marks:
                syaml.mark(dk, key_marks[dk])

        return dest

    # In any other case, overwrite with a copy of the source value.
    else:
        return copy.copy(source)
Esempio n. 3
0
File: config.py Progetto: LLNL/spack
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 both are None, handle specially and return None.
    if source is None and dest is None:
        return None

    # If source is None, overwrite with source.
    elif 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 dest.keys():
            if dk in key_marks:
                syaml.mark(dk, key_marks[dk])

        return dest

    # In any other case, overwrite with a copy of the source value.
    else:
        return copy.copy(source)